diff options
Diffstat (limited to 'static')
59 files changed, 2322 insertions, 25 deletions
diff --git a/static/blog/robots.txt b/static/blog/robots.txt deleted file mode 100644 index 1f53798..0000000 --- a/static/blog/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: / diff --git a/static/contact/aba.pub b/static/contact/aba.pub index 96e50ed..32bd48f 100644 --- a/static/contact/aba.pub +++ b/static/contact/aba.pub @@ -6,25 +6,40 @@ tzehXAMDqBBPyqlL88XZUBpXTIOyHBqC1kDjwTsIla+6AgepIRZQ2KDUaZrpuvDZ jdnkclNZOIdmJapUfUu37CN4EP0noOkfvLOcsgqedWqtOox0GpGg5zoMFzG//O1H V8H8yj65hsUa2118wXyy5MJ3+a6UkMuROgW5Hingks7md0QHbjQqG8EZherqdYm7 9Aa74y/O82hhYFHJJzpcRUo5hFrUusF3+uWrABEBAAG0KEFuZHJlYXMgQmF1bWFu -biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4WIQQ4rKagJtJc3SJ9 -JIMvY5nc0iEhlQUCWaWx+AIbAwUJA8JnAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIX -gAAKCRAvY5nc0iEhlfnMCADzJPsby7+rBDFmt/QR929SiE35Uod+Q91YWYlC23/E -o3HxRk01GAUmv6InN9cYJoCZEdcXDYJPtJhHjO/DSURDU2xx5gBd3gWbIFIsTiUi -ryqqDyeIoq+pMWzQ9LG3eQfdGfIcRu5jLem7k/naPCQvxSpHf6O3YekwHZqng6i3 -yDmwUp5CSNDxDqV7HnwW6d02kHvA+3Q6undDAWQF0XdP7wgm3mlMVLNkTqDmYeQS -ATptJcOpMEwi8t9mYmuiWYYPwDm492NScK5AoUF0WVK42aG5BEz2Oz9LVtcXKquu -17Zr6xcuKtgM71paCO3dxnlvef0HbFeHFmOTT6lqu1z2uQENBFmlsfgBCADfP4Se -cL8GvCKgVWuoM1tOEaZ/eND4jc4RcYTRdEiZYHfGah8S+kNd21Zpep++FSvQbwb+ -PjdQRbCwn+dBdxgpMhrLfZ3zy3Xtd4EEftq0y8Gyi+6ejJjk8eW7Xvl91objJSyh -J5Fx5v/K9bof9uCTLaWq/aFjcWpovsbbDWrq/OXowp8A69xMPAmJee8zW/Nj7Fv0 -sgQrIGNe3T4BWVncuuzP3YWxCB85ysk99l17joKrQx6w7FaG0e/n+gd1X0YRofYg -eu2UCpswbwfu7pwiWnNtgCajhaw47Og/9FMpsXGvuQs93pOLon7jLlPn1nsOaX5h -NkHfmyYabykXlpZBABEBAAGJATwEGAEIACYWIQQ4rKagJtJc3SJ9JIMvY5nc0iEh -lQUCWaWx+AIbDAUJA8JnAAAKCRAvY5nc0iEhlaMBCADIwsJwRi9XqkxaldehThkx -giQDp6M99J+quKLsevVRtDKi88tSWEhYRNKNjZLkmfQ8cKcR4eSDEIN9135RTK+w -mYq+IWgKIAPaFeMGQmBm2vlKTSpR4cuNMUCCToXwq4vUr5e/jRg+TzTf7j2pH7hi -HIQILaiU74g7KCcR2X8EUxG6Dus1Sk6zcvmnASBirw2M8bgarTBlr8GPpDUxnp7Q -LilZfyClqM29IfDjGOa+9RvOqHeC4m3xW8pqjIEuKOQeMmSY4xX7B01rFgILqhH4 -+IzlxIwq3xx0kxUup0zNLUtzBg2y9W6KX+VwruO4jH3qG91m3l/+1y1jRnQrtVkf -=hS12 +biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4CGwMFCwkIBwIGFQgJ +CgsCBBYCAwECHgECF4AWIQQ4rKagJtJc3SJ9JIMvY5nc0iEhlQUCZTNyywUJDW70 +UwAKCRAvY5nc0iEhleAAB/9M1Evov4qadN3QrU5MT1ZrLYchf+8EZ2zkwZqrxrWR +natt8bYAl2KGt7ADUC5OlT1g2VnKi0Wp6p8J2C4jnHr1+TnuNwMnUaU5YXuF5JHO +XGzQCJCucBRRAcrxYlwHdPIQDsjJGw5F54UCaa6FlN8/mLTyzemdcH9uyiZOw1jx +wiXzm/z49u+olic1al7MgZJ28ih20jSu21wVxCrZoPdXNXTqwoNvYJkzJo3aGfEF +JAcASvNKOEAQRRDHHJpgp5WKvz7rmzJyyO/v6Emof1Dfi/dCsBaOwLmGH2DVK42o +IVfr4jG6jZ0DbpA8oi+9aXIv2gBVgj6R/nHLIQ1JlH7YiQFUBBMBCAA+FiEEOKym +oCbSXN0ifSSDL2OZ3NIhIZUFAlmlsfgCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYC +AwECHgECF4AACgkQL2OZ3NIhIZX5zAgA8yT7G8u/qwQxZrf0EfdvUohN+VKHfkPd +WFmJQtt/xKNx8UZNNRgFJr+iJzfXGCaAmRHXFw2CT7SYR4zvw0lEQ1NsceYAXd4F +myBSLE4lIq8qqg8niKKvqTFs0PSxt3kH3RnyHEbuYy3pu5P52jwkL8UqR3+jt2Hp +MB2ap4Oot8g5sFKeQkjQ8Q6lex58FundNpB7wPt0Orp3QwFkBdF3T+8IJt5pTFSz +ZE6g5mHkEgE6bSXDqTBMIvLfZmJrolmGD8A5uPdjUnCuQKFBdFlSuNmhuQRM9js/ +S1bXFyqrrte2a+sXLirYDO9aWgjt3cZ5b3n9B2xXhxZjk0+partc9okBVAQTAQgA +PgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBDispqAm0lzdIn0kgy9jmdzS +ISGVBQJdS9cGBQkHaIwOAAoJEC9jmdzSISGVEAcH/RfoMGcAw4A4GnlwQO3cBXIb +G6z06H/7gPuAwSwGETBCIh6D3rkpjSw7I8YqXsbpNzWloXOhRoX1jsy3a0Vy5rps +e6dddBXcyJOPSvTgNw3uWU0FbXQHlqVlwJ/SWQq882aOZZFnXITkaxzYK3TZtqRJ +p4vgszEHhtaycMfyeXQNmlWQY0SHXA9AVgxYecIvvxkxp1AZ4GrhHXR9KC40FcSY +CDvXluc6Uuscnl2t2Elxbjl8fpeb2Ifjy34AIUHB8vPPaVqfDfne6MbthYG8gG+s +92NQPlhYjUCPc/IbWD2IvNJObXbBna9jGYsEg0/rR0DzChkzNA5SxJXb6I8DX0e5 +AQ0EWaWx+AEIAN8/hJ5wvwa8IqBVa6gzW04Rpn940PiNzhFxhNF0SJlgd8ZqHxL6 +Q13bVml6n74VK9BvBv4+N1BFsLCf50F3GCkyGst9nfPLde13gQR+2rTLwbKL7p6M +mOTx5bte+X3WhuMlLKEnkXHm/8r1uh/24JMtpar9oWNxami+xtsNaur85ejCnwDr +3Ew8CYl57zNb82PsW/SyBCsgY17dPgFZWdy67M/dhbEIHznKyT32XXuOgqtDHrDs +VobR7+f6B3VfRhGh9iB67ZQKmzBvB+7unCJac22AJqOFrDjs6D/0Uymxca+5Cz3e +k4uifuMuU+fWew5pfmE2Qd+bJhpvKReWlkEAEQEAAYkBPAQYAQgAJgIbDBYhBDis +pqAm0lzdIn0kgy9jmdzSISGVBQJlM3LABQkNbvRIAAoJEC9jmdzSISGV3VsH/2or +KR4Dvf+KYmdjYRSJmN0qczO7x/IZx9WGCIUrKCj+11d8voDOGCPwleiPlDQ6UO0p +TknWn9oH0xuJoRLhZCaxCb04p2x1Urbscb09NJA9opibs3g8lbX1Mjdg3ayeUDb3 +5EkpowtI4tyjkX+sqtBYbwxgqg0kGwtt38xhLutilCIxSD8q92Sm92DKePaEAgGi +NqYf/QUfjWtwswo7B/vhIUNbCBIUk0oWtW9P3HfJ/nQfWyG+N7N9KEvrTXaJ2o0K +pLo22OY6Cg3qbLvbCkQ0/H30bPRQo7dqm6tvWP7V/Qy6PZX7NOiphka4cRw3uI8W +Q1qs4ogfoSGjc/IkYyc= +=co6y -----END PGP PUBLIC KEY BLOCK----- diff --git a/static/hardware/imc-2001/chargen.rom b/static/hardware/imc-2001/chargen.rom Binary files differnew file mode 100644 index 0000000..6c6fed2 --- /dev/null +++ b/static/hardware/imc-2001/chargen.rom diff --git a/static/hardware/imc-2001/manual_imc_2001_2.01.pdf b/static/hardware/imc-2001/manual_imc_2001_2.01.pdf Binary files differnew file mode 100644 index 0000000..80964a0 --- /dev/null +++ b/static/hardware/imc-2001/manual_imc_2001_2.01.pdf diff --git a/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg b/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg Binary files differnew file mode 100644 index 0000000..9e2c206 --- /dev/null +++ b/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg diff --git a/static/images/blog/bacula-lto4-backup/fitting.jpg b/static/images/blog/bacula-lto4-backup/fitting.jpg Binary files differnew file mode 100644 index 0000000..f076c11 --- /dev/null +++ b/static/images/blog/bacula-lto4-backup/fitting.jpg diff --git a/static/images/blog/bacula-lto4-backup/lto4.jpg b/static/images/blog/bacula-lto4-backup/lto4.jpg Binary files differnew file mode 100644 index 0000000..bd9baf7 --- /dev/null +++ b/static/images/blog/bacula-lto4-backup/lto4.jpg diff --git a/static/images/blog/mail-disaster/ibm.png b/static/images/blog/mail-disaster/ibm.png Binary files differnew file mode 100644 index 0000000..70cb125 --- /dev/null +++ b/static/images/blog/mail-disaster/ibm.png diff --git a/static/images/blog/mail-disaster/mail-disaster.png b/static/images/blog/mail-disaster/mail-disaster.png Binary files differnew file mode 100644 index 0000000..a4190ab --- /dev/null +++ b/static/images/blog/mail-disaster/mail-disaster.png diff --git a/static/images/blog/mail-disaster/zy0_de.png b/static/images/blog/mail-disaster/zy0_de.png Binary files differnew file mode 100644 index 0000000..8e218a5 --- /dev/null +++ b/static/images/blog/mail-disaster/zy0_de.png diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg Binary files differnew file mode 100644 index 0000000..e68553d --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg Binary files differnew file mode 100644 index 0000000..6d5754c --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg Binary files differnew file mode 100644 index 0000000..f66bfab --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg Binary files differnew file mode 100644 index 0000000..7ac7d15 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg Binary files differnew file mode 100644 index 0000000..7ac7d15 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg Binary files differnew file mode 100644 index 0000000..5de6c4a --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg Binary files differnew file mode 100644 index 0000000..f66bfab --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg Binary files differnew file mode 100644 index 0000000..c0d4add --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg Binary files differnew file mode 100644 index 0000000..315e293 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg Binary files differnew file mode 100644 index 0000000..8c04eeb --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg Binary files differnew file mode 100644 index 0000000..379cfff --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg Binary files differnew file mode 100644 index 0000000..b5ae239 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg Binary files differnew file mode 100644 index 0000000..2931935 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg Binary files differnew file mode 100644 index 0000000..ccba1a4 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg Binary files differnew file mode 100644 index 0000000..8c1ecfa --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg Binary files differnew file mode 100644 index 0000000..8f257c5 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg Binary files differnew file mode 100644 index 0000000..4ad762e --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg Binary files differnew file mode 100644 index 0000000..f1414a2 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg Binary files differnew file mode 100644 index 0000000..a7d29f3 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg Binary files differnew file mode 100644 index 0000000..975ffea --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg Binary files differnew file mode 100644 index 0000000..5f71a09 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg Binary files differnew file mode 100644 index 0000000..37652c6 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg Binary files differnew file mode 100644 index 0000000..a86a12d --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg Binary files differnew file mode 100644 index 0000000..806b1eb --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg Binary files differnew file mode 100644 index 0000000..4fe8140 --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg Binary files differnew file mode 100644 index 0000000..15f5d4a --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg Binary files differnew file mode 100644 index 0000000..1c7ecca --- /dev/null +++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg diff --git a/static/images/github.svg b/static/images/github.svg deleted file mode 100644 index 84c884b..0000000 --- a/static/images/github.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" ?><svg enable-background="new 0 0 64 64" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Layer_3"><g><g><path d="M32,0C14.327,0,0,14.327,0,32c0,17.673,14.327,32,32,32s32-14.327,32-32C64,14.327,49.673,0,32,0z" fill="#333333"/></g></g><g id="Outline_Filled"><path d="M38.592,50.166h-4.84h-4.844c0,0,0.014-2.874,0-4.844c-6.629,1.428-8.479-3.633-8.479-3.633 c-1.21-2.423-2.423-3.633-2.423-3.633c-2.423-1.438,0-1.21,0-1.21c2.423,0,3.633,2.423,3.633,2.423 c2.126,3.609,5.908,3.028,7.266,2.423c0-1.21,0.53-3.042,1.21-3.633c-5.29-0.595-9.693-3.633-9.693-9.689s1.216-7.266,2.427-8.479 c-0.244-0.597-1.259-2.805,0.037-6.056c0,0,2.38,0,4.803,3.633c1.2-1.2,4.844-1.21,6.056-1.21c1.208,0,4.854,0.01,6.054,1.21 c2.423-3.633,4.809-3.633,4.809-3.633c1.296,3.251,0.282,5.459,0.037,6.056c1.21,1.21,2.423,2.423,2.423,8.479 s-4.397,9.092-9.689,9.689c0.682,0.591,1.21,2.675,1.21,3.633L38.592,50.166L38.592,50.166z" fill="#FFFFFF" id="Cat_3_"/></g></g></svg>
\ No newline at end of file diff --git a/static/images/hardware/book8088/book8088.jpg b/static/images/hardware/book8088/book8088.jpg Binary files differnew file mode 100644 index 0000000..ba8f883 --- /dev/null +++ b/static/images/hardware/book8088/book8088.jpg diff --git a/static/images/hardware/imc-2001/chargen.png b/static/images/hardware/imc-2001/chargen.png Binary files differnew file mode 100644 index 0000000..4aa85ad --- /dev/null +++ b/static/images/hardware/imc-2001/chargen.png diff --git a/static/images/hardware/imc-2001/computer_full.jpg b/static/images/hardware/imc-2001/computer_full.jpg Binary files differnew file mode 100644 index 0000000..00e48ac --- /dev/null +++ b/static/images/hardware/imc-2001/computer_full.jpg diff --git a/static/images/hardware/imc-2001/cpm/README b/static/images/hardware/imc-2001/cpm/README new file mode 100644 index 0000000..8c69856 --- /dev/null +++ b/static/images/hardware/imc-2001/cpm/README @@ -0,0 +1 @@ +APDOS: read apple disks diff --git a/static/images/hardware/imc-2001/cpm/README.MBASIC b/static/images/hardware/imc-2001/cpm/README.MBASIC new file mode 100644 index 0000000..6d69e8e --- /dev/null +++ b/static/images/hardware/imc-2001/cpm/README.MBASIC @@ -0,0 +1 @@ +SYSTEM return to CP/M diff --git a/static/images/hardware/imc-2001/cpm_40chars.jpg b/static/images/hardware/imc-2001/cpm_40chars.jpg Binary files differnew file mode 100644 index 0000000..88517cf --- /dev/null +++ b/static/images/hardware/imc-2001/cpm_40chars.jpg diff --git a/static/images/hardware/imc-2001/floppies/README b/static/images/hardware/imc-2001/floppies/README new file mode 100644 index 0000000..0c4e584 --- /dev/null +++ b/static/images/hardware/imc-2001/floppies/README @@ -0,0 +1,12 @@ +40-track, single-sided, 256 bytes-per-sector +35*256*16 = 143360 + +We should have mostly 16 track ones. The 13 sector ones come +from the old Apple ][s in the old Lyceum server room. + +links +----- + +https://en.wikipedia.org/wiki/List_of_floppy_disk_formats +http://cowlark.com/fluxengine/doc/disk-apple2.html + diff --git a/static/images/hardware/imc-2001/keyboard_cable.jpg b/static/images/hardware/imc-2001/keyboard_cable.jpg Binary files differnew file mode 100644 index 0000000..d9f5d97 --- /dev/null +++ b/static/images/hardware/imc-2001/keyboard_cable.jpg diff --git a/static/images/hardware/imc-2001/keyboard_front.jpg b/static/images/hardware/imc-2001/keyboard_front.jpg Binary files differnew file mode 100644 index 0000000..02c20d8 --- /dev/null +++ b/static/images/hardware/imc-2001/keyboard_front.jpg diff --git a/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg b/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg Binary files differnew file mode 100644 index 0000000..967c7f2 --- /dev/null +++ b/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg diff --git a/static/images/hardware/imc-2001/manual_ascii_table.jpg b/static/images/hardware/imc-2001/manual_ascii_table.jpg Binary files differnew file mode 100644 index 0000000..17e598e --- /dev/null +++ b/static/images/hardware/imc-2001/manual_ascii_table.jpg diff --git a/static/images/hardware/imc-2001/manual_frontpage.jpg b/static/images/hardware/imc-2001/manual_frontpage.jpg Binary files differnew file mode 100644 index 0000000..b575539 --- /dev/null +++ b/static/images/hardware/imc-2001/manual_frontpage.jpg diff --git a/static/images/hardware/imc-2001/motherboard_internal.jpg b/static/images/hardware/imc-2001/motherboard_internal.jpg Binary files differnew file mode 100644 index 0000000..2d9153a --- /dev/null +++ b/static/images/hardware/imc-2001/motherboard_internal.jpg diff --git a/static/images/hardware/imc-2001/new_psu.jpg b/static/images/hardware/imc-2001/new_psu.jpg Binary files differnew file mode 100644 index 0000000..5187d4b --- /dev/null +++ b/static/images/hardware/imc-2001/new_psu.jpg diff --git a/static/images/hardware/imc-2001/old_psu.jpg b/static/images/hardware/imc-2001/old_psu.jpg Binary files differnew file mode 100644 index 0000000..f85483e --- /dev/null +++ b/static/images/hardware/imc-2001/old_psu.jpg diff --git a/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg b/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg Binary files differnew file mode 100644 index 0000000..26e96f9 --- /dev/null +++ b/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg diff --git a/static/images/hardware/imc-2001/romboard.jpg b/static/images/hardware/imc-2001/romboard.jpg Binary files differnew file mode 100644 index 0000000..55ad6d9 --- /dev/null +++ b/static/images/hardware/imc-2001/romboard.jpg diff --git a/static/images/twitter.svg b/static/images/twitter.svg deleted file mode 100644 index 069dad2..0000000 --- a/static/images/twitter.svg +++ /dev/null @@ -1 +0,0 @@ -<?xml version="1.0" ?><svg enable-background="new 0 0 32 32" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Flat_copy"><g><path d="M16,0C7.163,0,0,7.163,0,16c0,8.836,7.163,16,16,16s16-7.164,16-16C32,7.163,24.837,0,16,0z" fill="#333333"/></g><path d="M18.226,8.886c-1.59,0.579-2.595,2.071-2.481,3.704l0.038,0.63l-0.636-0.077 c-2.315-0.296-4.338-1.299-6.056-2.984l-0.84-0.836L8.036,9.94c-0.458,1.376-0.165,2.83,0.789,3.808 c0.509,0.54,0.394,0.617-0.483,0.296c-0.305-0.103-0.573-0.18-0.598-0.141c-0.089,0.09,0.216,1.26,0.458,1.724 c0.331,0.644,1.005,1.273,1.743,1.647l0.624,0.296L9.83,17.581c-0.712,0-0.738,0.013-0.661,0.284 c0.254,0.836,1.259,1.724,2.379,2.11l0.789,0.27l-0.687,0.412c-1.018,0.593-2.214,0.927-3.41,0.951 c-0.573,0.013-1.044,0.064-1.044,0.103c0,0.128,1.553,0.848,2.455,1.132c2.71,0.836,5.929,0.475,8.346-0.952 c1.718-1.016,3.435-3.036,4.237-4.992c0.433-1.041,0.865-2.945,0.865-3.858c0-0.592,0.038-0.669,0.75-1.376 c0.42-0.412,0.814-0.862,0.891-0.99c0.128-0.245,0.114-0.245-0.534-0.026c-1.081,0.386-1.234,0.335-0.699-0.244 c0.394-0.412,0.865-1.158,0.865-1.376c0-0.038-0.191,0.026-0.407,0.141c-0.229,0.129-0.738,0.322-1.12,0.437l-0.687,0.219 L21.535,9.4c-0.344-0.231-0.826-0.489-1.081-0.566C19.804,8.654,18.812,8.68,18.226,8.886z" fill="#FFFFFF"/></g></svg>
\ No newline at end of file diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c new file mode 100644 index 0000000..45984b6 --- /dev/null +++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c @@ -0,0 +1,759 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include <linux/acpi.h> +#include <linux/pci.h> +#include <linux/slab.h> + +#include <drm/drm_device.h> + +#include <linux/firmware.h> + +#include "atom.h" +#include "radeon.h" +#include "radeon_reg.h" + +/* + * BIOS. + */ + +/* If you boot an IGP board with a discrete card as the primary, + * the IGP rom is not accessible via the rom bar as the IGP rom is + * part of the system bios. On boot, the system bios puts a + * copy of the igp rom at the start of vram if a discrete card is + * present. + */ +static bool igp_read_bios_from_vram(struct radeon_device *rdev) +{ + uint8_t __iomem *bios; + resource_size_t vram_base; + resource_size_t size = 256 * 1024; /* ??? */ + + if (!(rdev->flags & RADEON_IS_IGP)) + if (!radeon_card_posted(rdev)) + return false; + + rdev->bios = NULL; + vram_base = pci_resource_start(rdev->pdev, 0); + bios = ioremap(vram_base, size); + if (!bios) { + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + iounmap(bios); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + iounmap(bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + iounmap(bios); + return true; +} + +static bool radeon_read_bios(struct radeon_device *rdev) +{ + uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; + /* XXX: some cards may return 0 for rom size? ddx has a workaround */ + bios = pci_map_rom(rdev->pdev, &size); + if (!bios) { + return false; + } + + val1 = readb(&bios[0]); + val2 = readb(&bios[1]); + + if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; +} + +static bool radeon_read_platform_bios(struct radeon_device *rdev) +{ + phys_addr_t rom = rdev->pdev->rom; + size_t romlen = rdev->pdev->romlen; + void __iomem *bios; + + rdev->bios = NULL; + + if (!rom || romlen == 0) + return false; + + rdev->bios = kzalloc(romlen, GFP_KERNEL); + if (!rdev->bios) + return false; + + bios = ioremap(rom, romlen); + if (!bios) + goto free_bios; + + memcpy_fromio(rdev->bios, bios, romlen); + iounmap(bios); + + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) + goto free_bios; + + return true; +free_bios: + kfree(rdev->bios); + return false; +} + +static bool radeon_read_bios_from_firmware(struct radeon_device *rdev) +{ + const uint8_t __iomem *bios; + resource_size_t size; + const struct firmware *fw = NULL; + + request_firmware(&fw, "radeon/vbios.bin", rdev->dev); + if (!fw) { + DRM_ERROR("No bios\n"); + return false; + } + size = fw->size; + bios = fw->data; + + if (!bios) { + DRM_ERROR("No bios\n"); + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + DRM_ERROR("wrong sig\n"); + release_firmware(fw); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + DRM_ERROR("alloc fail\n"); + release_firmware(fw); + return false; + } + memcpy(rdev->bios, bios, size); + release_firmware(fw); + return true; +} + +#ifdef CONFIG_ACPI +/* ATRM is used to get the BIOS on the discrete cards in + * dual-gpu systems. + */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + +static bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + int ret; + int size = 256 * 1024; + int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; + + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + + if (!found) { + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + } + + if (!found) + return false; + + rdev->bios = kmalloc(size, GFP_KERNEL); + if (!rdev->bios) { + DRM_ERROR("Unable to allocate bios\n"); + return false; + } + + for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); + if (ret < ATRM_BIOS_PAGE) + break; + } + + if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + kfree(rdev->bios); + return false; + } + return true; +} +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +static bool ni_read_disabled_bios(struct radeon_device *rdev) +{ + u32 bus_cntl; + u32 d1vga_control; + u32 d2vga_control; + u32 vga_render_control; + u32 rom_cntl; + bool r; + + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + if (!ASIC_IS_NODCE(rdev)) { + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + } + WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(R600_BUS_CNTL, bus_cntl); + if (!ASIC_IS_NODCE(rdev)) { + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + } + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r700_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t cg_spll_func_cntl = 0; + uint32_t cg_spll_status; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + if (rdev->family == CHIP_RV730) { + cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); + + /* enable bypass mode */ + WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | + R600_SPLL_BYPASS_EN)); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + + WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } else + WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + if (rdev->family == CHIP_RV730) { + WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + } + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r600_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t general_pwrmgt; + uint32_t low_vid_lower_gpio_cntl; + uint32_t medium_vid_lower_gpio_cntl; + uint32_t high_vid_lower_gpio_cntl; + uint32_t ctxsw_vid_lower_gpio_cntl; + uint32_t lower_gpio_enable; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); + low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); + medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); + high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); + ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); + lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + WREG32(R600_ROM_CNTL, + ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | + (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | + R600_SCK_OVERWRITE)); + + WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, + (low_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, + (medium_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, + (high_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, + (ctxsw_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); + WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); + return r; +} + +static bool avivo_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t gpiopad_a; + uint32_t gpiopad_en; + uint32_t gpiopad_mask; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(RV370_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + gpiopad_en = RREG32(RADEON_GPIOPAD_EN); + gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + WREG32(RADEON_GPIOPAD_A, 0); + WREG32(RADEON_GPIOPAD_EN, 0); + WREG32(RADEON_GPIOPAD_MASK, 0); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(RV370_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(RADEON_GPIOPAD_A, gpiopad_a); + WREG32(RADEON_GPIOPAD_EN, gpiopad_en); + WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); + return r; +} + +static bool legacy_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t crtc_gen_cntl; + uint32_t crtc2_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t fp2_gen_cntl; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + if (rdev->flags & RADEON_IS_PCIE) + bus_cntl = RREG32(RV370_BUS_CNTL); + else + bus_cntl = RREG32(RADEON_BUS_CNTL); + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); + crtc2_gen_cntl = 0; + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + fp2_gen_cntl = 0; + + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + } + + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + else + WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Turn off mem requests and CRTC for both controllers */ + WREG32(RADEON_CRTC_GEN_CNTL, + ((crtc_gen_cntl & ~RADEON_CRTC_EN) | + (RADEON_CRTC_DISP_REQ_EN_B | + RADEON_CRTC_EXT_DISP_EN))); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, + ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | + RADEON_CRTC2_DISP_REQ_EN_B)); + } + /* Turn off CRTC */ + WREG32(RADEON_CRTC_EXT_CNTL, + ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | + (RADEON_CRTC_SYNC_TRISTAT | + RADEON_CRTC_DISPLAY_DIS))); + + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); + } + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, bus_cntl); + else + WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + } + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } + return r; +} + +static bool radeon_read_disabled_bios(struct radeon_device *rdev) +{ + if (rdev->flags & RADEON_IS_IGP) + return igp_read_bios_from_vram(rdev); + else if (rdev->family >= CHIP_BARTS) + return ni_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RV770) + return r700_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_R600) + return r600_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RS600) + return avivo_read_disabled_bios(rdev); + else + return legacy_read_disabled_bios(rdev); +} + +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + struct acpi_table_header *hdr; + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + unsigned offset; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + tbl_size = hdr->length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + return false; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + offset = vfct->VBIOSImageOffset; + + while (offset < tbl_size) { + GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset); + VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader; + + offset += sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); + return false; + } + + offset += vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + return false; + } + + if (vhdr->ImageLength && + vhdr->PCIBus == rdev->pdev->bus->number && + vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) && + vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) && + vhdr->VendorID == rdev->pdev->vendor && + vhdr->DeviceID == rdev->pdev->device) { + rdev->bios = kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); + + if (!rdev->bios) + return false; + return true; + } + } + + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + return false; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +bool radeon_get_bios(struct radeon_device *rdev) +{ + bool r; + uint16_t tmp; + + r = radeon_atrm_get_bios(rdev); + if (!r) + r = radeon_acpi_vfct_bios(rdev); + if (!r) + r = igp_read_bios_from_vram(rdev); + if (!r) + r = radeon_read_bios(rdev); + if (!r) + r = radeon_read_disabled_bios(rdev); + if (!r) + r = radeon_read_platform_bios(rdev); + if (!r) + r = radeon_read_bios_from_firmware(rdev); + + if (!r || rdev->bios == NULL) { + DRM_ERROR("Unable to locate a BIOS ROM\n"); + rdev->bios = NULL; + return false; + } + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); + goto free_bios; + } + + tmp = RBIOS16(0x18); + if (RBIOS8(tmp + 0x14) != 0x0) { + DRM_INFO("Not an x86 BIOS ROM, not using.\n"); + goto free_bios; + } + + rdev->bios_header_start = RBIOS16(0x48); + if (!rdev->bios_header_start) { + goto free_bios; + } + tmp = rdev->bios_header_start + 4; + if (!memcmp(rdev->bios + tmp, "ATOM", 4) || + !memcmp(rdev->bios + tmp, "MOTA", 4)) { + rdev->is_atom_bios = true; + } else { + rdev->is_atom_bios = false; + } + + DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); + return true; +free_bios: + kfree(rdev->bios); + rdev->bios = NULL; + return false; +} diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c new file mode 100644 index 0000000..b7c099a --- /dev/null +++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c @@ -0,0 +1,764 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ + +#include <linux/acpi.h> +#include <linux/pci.h> +#include <linux/slab.h> + +#include <drm/drm_device.h> + +#include <linux/firmware.h> + +#include "atom.h" +#include "radeon.h" +#include "radeon_reg.h" + +/* + * BIOS. + */ + +/* If you boot an IGP board with a discrete card as the primary, + * the IGP rom is not accessible via the rom bar as the IGP rom is + * part of the system bios. On boot, the system bios puts a + * copy of the igp rom at the start of vram if a discrete card is + * present. + */ +static bool igp_read_bios_from_vram(struct radeon_device *rdev) +{ + uint8_t __iomem *bios; + resource_size_t vram_base; + resource_size_t size = 256 * 1024; /* ??? */ + + if (!(rdev->flags & RADEON_IS_IGP)) + if (!radeon_card_posted(rdev)) + return false; + + rdev->bios = NULL; + vram_base = pci_resource_start(rdev->pdev, 0); + bios = ioremap(vram_base, size); + if (!bios) { + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + iounmap(bios); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + iounmap(bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + iounmap(bios); + return true; +} + +static bool radeon_read_bios(struct radeon_device *rdev) +{ + uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; + /* XXX: some cards may return 0 for rom size? ddx has a workaround */ + bios = pci_map_rom(rdev->pdev, &size); + if (!bios) { + return false; + } + + val1 = readb(&bios[0]); + val2 = readb(&bios[1]); + + if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; +} + +static bool radeon_read_platform_bios(struct radeon_device *rdev) +{ + phys_addr_t rom = rdev->pdev->rom; + size_t romlen = rdev->pdev->romlen; + void __iomem *bios; + + rdev->bios = NULL; + + if (!rom || romlen == 0) + return false; + + rdev->bios = kzalloc(romlen, GFP_KERNEL); + if (!rdev->bios) + return false; + + bios = ioremap(rom, romlen); + if (!bios) + goto free_bios; + + memcpy_fromio(rdev->bios, bios, romlen); + iounmap(bios); + + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) + goto free_bios; + + return true; +free_bios: + kfree(rdev->bios); + return false; +} + +static bool radeon_read_bios_from_firmware(struct radeon_device *rdev) +{ + const uint8_t __iomem *bios; + resource_size_t size; + const struct firmware *fw = NULL; + + request_firmware(&fw, "radeon/vbios.bin", rdev->dev); + if (!fw) { + DRM_ERROR("No bios\n"); + return false; + } + size = fw->size; + bios = fw->data; + + if (!bios) { + DRM_ERROR("No bios\n"); + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + DRM_ERROR("wrong sig\n"); + release_firmware(fw); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + DRM_ERROR("alloc fail\n"); + release_firmware(fw); + return false; + } + memcpy(rdev->bios, bios, size); + release_firmware(fw); + return true; +} + +#ifdef CONFIG_ACPI +/* ATRM is used to get the BIOS on the discrete cards in + * dual-gpu systems. + */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + +static bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + int ret; + int size = 256 * 1024; + int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; + + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (ACPI_SUCCESS(status)) { + found = true; + break; + } + } + + if (!found) { + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (ACPI_SUCCESS(status)) { + found = true; + break; + } + } + } + + if (!found) + return false; + pci_dev_put(pdev); + + rdev->bios = kmalloc(size, GFP_KERNEL); + if (!rdev->bios) { + DRM_ERROR("Unable to allocate bios\n"); + return false; + } + + for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); + if (ret < ATRM_BIOS_PAGE) + break; + } + + if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + kfree(rdev->bios); + return false; + } + return true; +} +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +static bool ni_read_disabled_bios(struct radeon_device *rdev) +{ + u32 bus_cntl; + u32 d1vga_control; + u32 d2vga_control; + u32 vga_render_control; + u32 rom_cntl; + bool r; + + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + if (!ASIC_IS_NODCE(rdev)) { + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + } + WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(R600_BUS_CNTL, bus_cntl); + if (!ASIC_IS_NODCE(rdev)) { + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + } + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r700_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t cg_spll_func_cntl = 0; + uint32_t cg_spll_status; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + if (rdev->family == CHIP_RV730) { + cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); + + /* enable bypass mode */ + WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | + R600_SPLL_BYPASS_EN)); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + + WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } else + WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + if (rdev->family == CHIP_RV730) { + WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + } + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r600_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t general_pwrmgt; + uint32_t low_vid_lower_gpio_cntl; + uint32_t medium_vid_lower_gpio_cntl; + uint32_t high_vid_lower_gpio_cntl; + uint32_t ctxsw_vid_lower_gpio_cntl; + uint32_t lower_gpio_enable; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); + low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); + medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); + high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); + ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); + lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + WREG32(R600_ROM_CNTL, + ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | + (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | + R600_SCK_OVERWRITE)); + + WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, + (low_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, + (medium_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, + (high_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, + (ctxsw_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); + WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); + return r; +} + +static bool avivo_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t gpiopad_a; + uint32_t gpiopad_en; + uint32_t gpiopad_mask; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(RV370_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + gpiopad_en = RREG32(RADEON_GPIOPAD_EN); + gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + WREG32(RADEON_GPIOPAD_A, 0); + WREG32(RADEON_GPIOPAD_EN, 0); + WREG32(RADEON_GPIOPAD_MASK, 0); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(RV370_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(RADEON_GPIOPAD_A, gpiopad_a); + WREG32(RADEON_GPIOPAD_EN, gpiopad_en); + WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); + return r; +} + +static bool legacy_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t crtc_gen_cntl; + uint32_t crtc2_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t fp2_gen_cntl; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + if (rdev->flags & RADEON_IS_PCIE) + bus_cntl = RREG32(RV370_BUS_CNTL); + else + bus_cntl = RREG32(RADEON_BUS_CNTL); + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); + crtc2_gen_cntl = 0; + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + fp2_gen_cntl = 0; + + if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + } + + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + else + WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Turn off mem requests and CRTC for both controllers */ + WREG32(RADEON_CRTC_GEN_CNTL, + ((crtc_gen_cntl & ~RADEON_CRTC_EN) | + (RADEON_CRTC_DISP_REQ_EN_B | + RADEON_CRTC_EXT_DISP_EN))); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, + ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | + RADEON_CRTC2_DISP_REQ_EN_B)); + } + /* Turn off CRTC */ + WREG32(RADEON_CRTC_EXT_CNTL, + ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | + (RADEON_CRTC_SYNC_TRISTAT | + RADEON_CRTC_DISPLAY_DIS))); + + if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); + } + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, bus_cntl); + else + WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + } + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } + return r; +} + +static bool radeon_read_disabled_bios(struct radeon_device *rdev) +{ + if (rdev->flags & RADEON_IS_IGP) + return igp_read_bios_from_vram(rdev); + else if (rdev->family >= CHIP_BARTS) + return ni_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RV770) + return r700_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_R600) + return r600_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RS600) + return avivo_read_disabled_bios(rdev); + else + return legacy_read_disabled_bios(rdev); +} + +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + struct acpi_table_header *hdr; + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + unsigned offset; + bool r = false; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + tbl_size = hdr->length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + offset = vfct->VBIOSImageOffset; + + while (offset < tbl_size) { + GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset); + VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader; + + offset += sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); + goto out; + } + + offset += vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out; + } + + if (vhdr->ImageLength && + vhdr->PCIBus == rdev->pdev->bus->number && + vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) && + vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) && + vhdr->VendorID == rdev->pdev->vendor && + vhdr->DeviceID == rdev->pdev->device) { + rdev->bios = kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); + if (rdev->bios) + r = true; + + goto out; + } + } + + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + +out: + acpi_put_table(hdr); + return r; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +bool radeon_get_bios(struct radeon_device *rdev) +{ + bool r; + uint16_t tmp; + + r = radeon_atrm_get_bios(rdev); + if (!r) + r = radeon_acpi_vfct_bios(rdev); + if (!r) + r = igp_read_bios_from_vram(rdev); + if (!r) + r = radeon_read_bios(rdev); + if (!r) + r = radeon_read_disabled_bios(rdev); + if (!r) + r = radeon_read_platform_bios(rdev); + if (!r) + r = radeon_read_bios_from_firmware(rdev); + + if (!r || rdev->bios == NULL) { + DRM_ERROR("Unable to locate a BIOS ROM\n"); + rdev->bios = NULL; + return false; + } + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); + goto free_bios; + } + + tmp = RBIOS16(0x18); + if (RBIOS8(tmp + 0x14) != 0x0) { + DRM_INFO("Not an x86 BIOS ROM, not using.\n"); + goto free_bios; + } + + rdev->bios_header_start = RBIOS16(0x48); + if (!rdev->bios_header_start) { + goto free_bios; + } + tmp = rdev->bios_header_start + 4; + if (!memcmp(rdev->bios + tmp, "ATOM", 4) || + !memcmp(rdev->bios + tmp, "MOTA", 4)) { + rdev->is_atom_bios = true; + } else { + rdev->is_atom_bios = false; + } + + DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); + return true; +free_bios: + kfree(rdev->bios); + rdev->bios = NULL; + return false; +} diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios.c new file mode 100644 index 0000000..e7b7c42 --- /dev/null +++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios.c @@ -0,0 +1,749 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#include <drm/drmP.h> +#include "radeon_reg.h" +#include "radeon.h" +#include "atom.h" + +#include <linux/slab.h> +#include <linux/acpi.h> + +#include <linux/firmware.h> + +/* + * BIOS. + */ + +/* If you boot an IGP board with a discrete card as the primary, + * the IGP rom is not accessible via the rom bar as the IGP rom is + * part of the system bios. On boot, the system bios puts a + * copy of the igp rom at the start of vram if a discrete card is + * present. + */ +static bool igp_read_bios_from_vram(struct radeon_device *rdev) +{ + uint8_t __iomem *bios; + resource_size_t vram_base; + resource_size_t size = 256 * 1024; /* ??? */ + + if (!(rdev->flags & RADEON_IS_IGP)) + if (!radeon_card_posted(rdev)) + return false; + + rdev->bios = NULL; + vram_base = pci_resource_start(rdev->pdev, 0); + bios = ioremap(vram_base, size); + if (!bios) { + DRM_ERROR("No BIOS\n"); + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + iounmap(bios); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + DRM_ERROR("alloc fail\n"); + iounmap(bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + iounmap(bios); + return true; +} + +static bool radeon_read_bios_from_firmware(struct radeon_device *rdev) +{ + const uint8_t __iomem *bios; + resource_size_t size; + const struct firmware *fw = NULL; + + request_firmware(&fw, "radeon/vbios.bin", rdev->dev); + if (!fw) { + DRM_ERROR("No bios\n"); + return false; + } + size = fw->size; + bios = fw->data; + + if (!bios) { + DRM_ERROR("No bios\n"); + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + DRM_ERROR("wrong sig\n"); + release_firmware(fw); + return false; + } + rdev->bios = kmalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + DRM_ERROR("alloc fail\n"); + release_firmware(fw); + return false; + } + memcpy(rdev->bios, bios, size); + release_firmware(fw); + return true; +} + +static bool radeon_read_bios(struct radeon_device *rdev) +{ + uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; + /* XXX: some cards may return 0 for rom size? ddx has a workaround */ + bios = pci_map_rom(rdev->pdev, &size); + if (!bios) { + return false; + } + + val1 = readb(&bios[0]); + val2 = readb(&bios[1]); + + if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } + memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; +} + +static bool radeon_read_platform_bios(struct radeon_device *rdev) +{ + uint8_t __iomem *bios; + size_t size; + + rdev->bios = NULL; + + bios = pci_platform_rom(rdev->pdev, &size); + if (!bios) { + return false; + } + + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + return false; + } + rdev->bios = kmemdup(bios, size, GFP_KERNEL); + if (rdev->bios == NULL) { + return false; + } + + return true; +} + +#ifdef CONFIG_ACPI +/* ATRM is used to get the BIOS on the discrete cards in + * dual-gpu systems. + */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + +static bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + int ret; + int size = 256 * 1024; + int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; + + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + + if (!found) { + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } + } + + if (!found) + return false; + + rdev->bios = kmalloc(size, GFP_KERNEL); + if (!rdev->bios) { + DRM_ERROR("Unable to allocate bios\n"); + return false; + } + + for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); + if (ret < ATRM_BIOS_PAGE) + break; + } + + if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + kfree(rdev->bios); + return false; + } + return true; +} +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +static bool ni_read_disabled_bios(struct radeon_device *rdev) +{ + u32 bus_cntl; + u32 d1vga_control; + u32 d2vga_control; + u32 vga_render_control; + u32 rom_cntl; + bool r; + + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + if (!ASIC_IS_NODCE(rdev)) { + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + } + WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(R600_BUS_CNTL, bus_cntl); + if (!ASIC_IS_NODCE(rdev)) { + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + } + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r700_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t cg_spll_func_cntl = 0; + uint32_t cg_spll_status; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + if (rdev->family == CHIP_RV730) { + cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); + + /* enable bypass mode */ + WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | + R600_SPLL_BYPASS_EN)); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + + WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } else + WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + if (rdev->family == CHIP_RV730) { + WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + /* wait for SPLL_CHG_STATUS to change to 1 */ + cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = RREG32(R600_CG_SPLL_STATUS); + } + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +static bool r600_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t rom_cntl; + uint32_t general_pwrmgt; + uint32_t low_vid_lower_gpio_cntl; + uint32_t medium_vid_lower_gpio_cntl; + uint32_t high_vid_lower_gpio_cntl; + uint32_t ctxsw_vid_lower_gpio_cntl; + uint32_t lower_gpio_enable; + bool r; + + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(R600_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + rom_cntl = RREG32(R600_ROM_CNTL); + general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); + low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); + medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); + high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); + ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); + lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + WREG32(R600_ROM_CNTL, + ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | + (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | + R600_SCK_OVERWRITE)); + + WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, + (low_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, + (medium_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, + (high_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, + (ctxsw_vid_lower_gpio_cntl & ~0x400)); + WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(R600_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(R600_ROM_CNTL, rom_cntl); + WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); + WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); + WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); + WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); + WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); + WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); + return r; +} + +static bool avivo_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t d1vga_control; + uint32_t d2vga_control; + uint32_t vga_render_control; + uint32_t gpiopad_a; + uint32_t gpiopad_en; + uint32_t gpiopad_mask; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + bus_cntl = RREG32(RV370_BUS_CNTL); + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + gpiopad_en = RREG32(RADEON_GPIOPAD_EN); + gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + WREG32(RADEON_GPIOPAD_A, 0); + WREG32(RADEON_GPIOPAD_EN, 0); + WREG32(RADEON_GPIOPAD_MASK, 0); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_VGA_RENDER_CONTROL, + (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + WREG32(RV370_BUS_CNTL, bus_cntl); + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); + WREG32(RADEON_GPIOPAD_A, gpiopad_a); + WREG32(RADEON_GPIOPAD_EN, gpiopad_en); + WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); + return r; +} + +static bool legacy_read_disabled_bios(struct radeon_device *rdev) +{ + uint32_t seprom_cntl1; + uint32_t viph_control; + uint32_t bus_cntl; + uint32_t crtc_gen_cntl; + uint32_t crtc2_gen_cntl; + uint32_t crtc_ext_cntl; + uint32_t fp2_gen_cntl; + bool r; + + seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); + viph_control = RREG32(RADEON_VIPH_CONTROL); + if (rdev->flags & RADEON_IS_PCIE) + bus_cntl = RREG32(RV370_BUS_CNTL); + else + bus_cntl = RREG32(RADEON_BUS_CNTL); + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); + crtc2_gen_cntl = 0; + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + fp2_gen_cntl = 0; + + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + } + + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } + + WREG32(RADEON_SEPROM_CNTL1, + ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | + (0xc << RADEON_SCK_PRESCALE_SHIFT))); + + /* disable VIP */ + WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + + /* enable the rom */ + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); + else + WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); + + /* Turn off mem requests and CRTC for both controllers */ + WREG32(RADEON_CRTC_GEN_CNTL, + ((crtc_gen_cntl & ~RADEON_CRTC_EN) | + (RADEON_CRTC_DISP_REQ_EN_B | + RADEON_CRTC_EXT_DISP_EN))); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, + ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | + RADEON_CRTC2_DISP_REQ_EN_B)); + } + /* Turn off CRTC */ + WREG32(RADEON_CRTC_EXT_CNTL, + ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | + (RADEON_CRTC_SYNC_TRISTAT | + RADEON_CRTC_DISPLAY_DIS))); + + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); + } + + r = radeon_read_bios(rdev); + + /* restore regs */ + WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); + WREG32(RADEON_VIPH_CONTROL, viph_control); + if (rdev->flags & RADEON_IS_PCIE) + WREG32(RV370_BUS_CNTL, bus_cntl); + else + WREG32(RADEON_BUS_CNTL, bus_cntl); + WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + } + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) { + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + } + return r; +} + +static bool radeon_read_disabled_bios(struct radeon_device *rdev) +{ + if (rdev->flags & RADEON_IS_IGP) + return igp_read_bios_from_vram(rdev); + else if (rdev->family >= CHIP_BARTS) + return ni_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RV770) + return r700_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_R600) + return r600_read_disabled_bios(rdev); + else if (rdev->family >= CHIP_RS600) + return avivo_read_disabled_bios(rdev); + else + return legacy_read_disabled_bios(rdev); +} + +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + struct acpi_table_header *hdr; + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + unsigned offset; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + tbl_size = hdr->length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + return false; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + offset = vfct->VBIOSImageOffset; + + while (offset < tbl_size) { + GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset); + VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader; + + offset += sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); + return false; + } + + offset += vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + return false; + } + + if (vhdr->ImageLength && + vhdr->PCIBus == rdev->pdev->bus->number && + vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) && + vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) && + vhdr->VendorID == rdev->pdev->vendor && + vhdr->DeviceID == rdev->pdev->device) { + rdev->bios = kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); + + if (!rdev->bios) + return false; + return true; + } + } + + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + return false; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif + +bool radeon_get_bios(struct radeon_device *rdev) +{ + bool r; + uint16_t tmp; + + r = radeon_atrm_get_bios(rdev); + if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) + r = igp_read_bios_from_vram(rdev); + if (r == false) + r = radeon_read_bios(rdev); + if (r == false) + r = radeon_read_disabled_bios(rdev); + if (r == false) + r = radeon_read_platform_bios(rdev); + if (r == false) + r = radeon_read_bios_from_firmware(rdev); + if (r == false || rdev->bios == NULL) { + DRM_ERROR("Unable to locate a BIOS ROM\n"); + rdev->bios = NULL; + return false; + } + if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { + printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]); + goto free_bios; + } + + tmp = RBIOS16(0x18); + if (RBIOS8(tmp + 0x14) != 0x0) { + DRM_INFO("Not an x86 BIOS ROM, not using.\n"); + goto free_bios; + } + + rdev->bios_header_start = RBIOS16(0x48); + if (!rdev->bios_header_start) { + goto free_bios; + } + tmp = rdev->bios_header_start + 4; + if (!memcmp(rdev->bios + tmp, "ATOM", 4) || + !memcmp(rdev->bios + tmp, "MOTA", 4)) { + rdev->is_atom_bios = true; + } else { + rdev->is_atom_bios = false; + } + + DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); + return true; +free_bios: + kfree(rdev->bios); + rdev->bios = NULL; + return false; +} |