diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 10aa9f00c7..0000000000 --- a/.clang-format +++ /dev/null @@ -1,16 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM -IndentWidth: 4 -ColumnLimit: 100 -AllowShortBlocksOnASingleLine: Empty -AllowShortFunctionsOnASingleLine: Inline -AllowShortLoopsOnASingleLine: true -AllowShortIfStatementsOnASingleLine: Never -AlignConsecutiveMacros: true -AlignEscapedNewlines: Left -BreakBeforeBraces: Custom -BraceWrapping: - AfterFunction: true -PointerAlignment: Right ---- diff --git a/.errorviz-version b/.errorviz-version new file mode 100644 index 0000000000..6da28dde76 --- /dev/null +++ b/.errorviz-version @@ -0,0 +1 @@ +0.1.1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9d91ac5720..95033100ea 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,11 @@ actual.out qemu.log rusty-tags.vi +.vscode-ctags +.gdb_history +.idea +bin +lib +lib64 +/.cargo +/*.log diff --git a/Cargo.lock b/Cargo.lock index 12d08af516..442d55950d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,24 @@ version = 3 [[package]] name = "aarch64-cpu" -version = "9.3.1" +version = "9.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb711c57d60565ba8f6523eb371e6243639617d817b4df1ae09af250af1af411" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" dependencies = [ - "tock-registers", + "tock-registers 0.8.1", ] +[[package]] +name = "accessor" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd8b2abd55bf1f9cffbf00fd594566c51a9d31402553284920c1309ca8351086" + [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -56,9 +62,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "arceos-bwbench" @@ -149,6 +155,13 @@ dependencies = [ "axstd", ] +[[package]] +name = "arceos-raspi4-usb" +version = "0.1.0" +dependencies = [ + "axstd", +] + [[package]] name = "arceos-shell" version = "0.1.0" @@ -180,6 +193,25 @@ dependencies = [ "axstd", ] +[[package]] +name = "arceos-usb" +version = "0.1.0" +dependencies = [ + "axalloc", + "axstd", +] + +[[package]] +name = "arceos-uvc" +version = "0.1.0" +dependencies = [ + "axalloc", + "axfeat", + "axhal", + "axstd", + "driver_usb", +] + [[package]] name = "arceos-yield" version = "0.1.0" @@ -224,7 +256,7 @@ dependencies = [ "bindgen", "flatten_objects", "lazy_static", - "spin 0.9.8", + "spin", "static_assertions", ] @@ -232,30 +264,30 @@ dependencies = [ name = "arm_gic" version = "0.1.0" dependencies = [ - "tock-registers", + "tock-registers 0.8.1", ] [[package]] name = "arm_pl011" version = "0.1.0" dependencies = [ - "tock-registers", + "tock-registers 0.8.1", ] [[package]] name = "atomic-polyfill" -version = "0.1.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" dependencies = [ "critical-section", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axalloc" @@ -264,6 +296,7 @@ dependencies = [ "allocator", "axerrno", "cfg-if", + "lazy_static", "log", "memory_addr", "spinlock", @@ -356,7 +389,7 @@ version = "0.1.0" dependencies = [ "axfs_vfs", "log", - "spin 0.9.8", + "spin", ] [[package]] @@ -365,7 +398,7 @@ version = "0.1.0" dependencies = [ "axfs_vfs", "log", - "spin 0.9.8", + "spin", ] [[package]] @@ -373,7 +406,7 @@ name = "axfs_vfs" version = "0.1.0" dependencies = [ "axerrno", - "bitflags 2.4.0", + "bitflags 2.6.0", "log", ] @@ -387,7 +420,7 @@ dependencies = [ "axalloc", "axconfig", "axlog", - "bitflags 2.4.0", + "bitflags 2.6.0", "cfg-if", "crate_interface", "dw_apb_uart", @@ -400,12 +433,12 @@ dependencies = [ "page_table_entry", "percpu", "ratio", - "raw-cpuid 11.0.1", + "raw-cpuid 11.1.0", "riscv", "sbi-rt", "spinlock", "static_assertions", - "tock-registers", + "tock-registers 0.8.1", "x2apic", "x86", "x86_64", @@ -456,7 +489,7 @@ dependencies = [ "lazy_init", "log", "smoltcp", - "spin 0.9.8", + "spin", ] [[package]] @@ -538,7 +571,7 @@ source = "git+https://github.com/lhw2002426/bcm2835-sdhci.git?rev=e974f16#e974f1 dependencies = [ "aarch64-cpu", "log", - "tock-registers", + "tock-registers 0.8.1", "volatile 0.2.7", ] @@ -548,7 +581,7 @@ version = "0.66.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "lazy_static", @@ -561,7 +594,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.29", + "syn 2.0.72", "which", ] @@ -585,9 +618,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitmap-allocator" @@ -599,34 +632,34 @@ dependencies = [ [[package]] name = "bitmaps" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" +checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" [[package]] name = "buddy_system_allocator" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f9365b6b0c9e1663ca4ca9440c00eda46bc85a3407070be8b5e0d8d1f29629" +checksum = "d44d578cadd17312c75e7d0ef489361f160ace58f7139aa32001fee1a51b89b5" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "capability" version = "0.1.0" dependencies = [ "axerrno", - "bitflags 2.4.0", + "bitflags 2.6.0", ] [[package]] @@ -637,12 +670,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cexpr" @@ -659,26 +689,36 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ch341" +version = "0.1.0" +dependencies = [ + "axalloc", + "axfeat", + "axhal", + "axstd", + "driver_usb", +] + [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time", "wasm-bindgen", - "winapi", + "windows-targets", ] [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -687,15 +727,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -703,9 +743,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -714,18 +754,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.23" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03aef18ddf7d879c15ce20f04826ef8418101c7e528014c3eeea13321047dca3" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.3.23" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ce6fffb678c9b80a70b6b6de0aad31df727623a70fd9a842c30cd573e2fa98" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstyle", "clap_lex", @@ -733,9 +773,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "const-default" @@ -743,11 +783,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" +[[package]] +name = "const-enum" +version = "0.1.0" +source = "git+https://github.com/dbydd/const-enum-new.git#ad1a010691f1ba50b3753f5a89055f1ac1111cfb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core_detect" @@ -761,7 +811,7 @@ version = "0.1.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] @@ -806,54 +856,42 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "defmt" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2d011b2fee29fb7d659b83c43fce9a2cb4df453e16d441a51448e448f3f98" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -861,22 +899,22 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54f0216f6c5acb5ae1a47050a6645024e6edafc2ee32d421955eccfef12ef92e" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" dependencies = [ "defmt-parser", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] name = "defmt-parser" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269924c02afd7f94bc4cecbfa5c379f6ffcf9766b3408fe63d22c728654eccd0" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" dependencies = [ "thiserror", ] @@ -905,19 +943,49 @@ dependencies = [ name = "driver_net" version = "0.1.0" dependencies = [ + "bit_field", "driver_common", "ixgbe-driver", "log", - "spin 0.9.8", + "spin", + "tock-registers 0.8.1", ] [[package]] name = "driver_pci" version = "0.1.0" dependencies = [ + "aarch64-cpu", + "bit_field", + "log", + "pci_types", + "ratio", + "tock-registers 0.8.1", "virtio-drivers", ] +[[package]] +name = "driver_usb" +version = "0.1.0" +dependencies = [ + "axalloc", + "axconfig", + "axhal", + "axtask", + "bit_field", + "byteorder", + "const-enum", + "driver_common", + "driver_pci", + "log", + "memory_addr", + "num-derive 0.4.2", + "num-traits", + "spinlock", + "tock-registers 0.9.0", + "xhci", +] + [[package]] name = "driver_virtio" version = "0.1.0" @@ -933,14 +1001,14 @@ dependencies = [ name = "dw_apb_uart" version = "0.1.0" dependencies = [ - "tock-registers", + "tock-registers 0.8.1", ] [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embedded-graphics" @@ -983,25 +1051,14 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "fatfs" version = "0.4.0" @@ -1029,13 +1086,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1046,9 +1103,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "half" -version = "1.8.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "handler_table" @@ -1065,41 +1126,50 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heapless" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", "hash32", "rustc_version", - "spin 0.9.8", + "spin", "stable_deref_trait", ] [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1113,9 +1183,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -1123,12 +1193,12 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", + "libc", "windows-sys", ] @@ -1143,9 +1213,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "ixgbe-driver" @@ -1161,9 +1231,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1182,11 +1252,11 @@ version = "0.1.0" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -1197,18 +1267,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "winapi", + "windows-targets", ] [[package]] @@ -1217,15 +1287,15 @@ version = "0.1.0" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1233,9 +1303,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "managed" @@ -1245,18 +1315,9 @@ checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memory_addr" @@ -1264,9 +1325,9 @@ version = "0.1.0" [[package]] name = "micromath" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" [[package]] name = "minimal-lexical" @@ -1300,35 +1361,47 @@ dependencies = [ ] [[package]] -name = "num-traits" -version = "0.2.16" +name = "num-derive" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "autocfg", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "hermit-abi", - "libc", + "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "page_table" @@ -1344,16 +1417,26 @@ name = "page_table_entry" version = "0.1.0" dependencies = [ "aarch64-cpu", - "bitflags 2.4.0", + "bitflags 2.6.0", "memory_addr", "x86_64", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pci_types" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "ebac2b2ee11791f721a51184b632a916b3044f2ee7b2374e7fdcfdf3eaf29c79" +dependencies = [ + "bit_field", + "bitflags 2.6.0", +] [[package]] name = "peeking_take_while" @@ -1368,7 +1451,7 @@ dependencies = [ "cfg-if", "kernel_guard", "percpu_macros", - "spin 0.9.8", + "spin", "x86", ] @@ -1378,14 +1461,14 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -1396,15 +1479,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -1417,12 +1500,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.12" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] @@ -1451,18 +1534,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1512,18 +1595,18 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.1" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", ] [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1531,21 +1614,19 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "regex" -version = "1.9.3" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -1555,9 +1636,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1566,9 +1647,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "riscv" @@ -1610,11 +1691,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.8" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1623,15 +1704,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1675,35 +1756,35 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.185" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -1712,9 +1793,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab_allocator" @@ -1737,12 +1818,6 @@ dependencies = [ "managed", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -1798,9 +1873,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1809,33 +1884,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "syn 2.0.72", ] [[package]] @@ -1858,17 +1922,23 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" +[[package]] +name = "tock-registers" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" + [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", @@ -1881,20 +1951,20 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "version_check" @@ -1904,10 +1974,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "virtio-drivers" -version = "0.4.0" -source = "git+https://github.com/rcore-os/virtio-drivers.git?rev=409ee72#409ee723c92adf309e825a7b87f53049707ed306" +version = "0.7.1" +source = "git+https://github.com/rcore-os/virtio-drivers.git?rev=4b60f5d#4b60f5d341a7211dfec7382062f965c5433c51c2" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "log", "zerocopy", ] @@ -1938,20 +2008,14 @@ checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1960,9 +2024,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1970,24 +2034,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1995,28 +2059,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2024,73 +2088,53 @@ dependencies = [ [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -2099,60 +2143,66 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.14" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09770118a7eb1ccaf4a594a221334119a44a814fcb0d31c5b85e83e97227a97" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] [[package]] name = "x2apic" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "547152b57dd1ae0ce7a4ef1c6470f6039aa7ed22e2179d5bc4f3eda1304e0db3" +checksum = "cbcd582541cbb8ef1dfc24a3c849a64ff074b1b512af723ad90056558d424602" dependencies = [ "bit", "bitflags 1.3.2", @@ -2174,21 +2224,34 @@ dependencies = [ [[package]] name = "x86_64" -version = "0.14.10" +version = "0.14.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100555a863c0092238c2e0e814c1096c1e5cf066a309c696a87e907b5f8c5d69" +checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062" dependencies = [ "bit_field", - "bitflags 1.3.2", + "bitflags 2.6.0", "rustversion", "volatile 0.4.6", ] +[[package]] +name = "xhci" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f3f0483969259f2adb6524054400d94ac352e59fa37da6c6ca3b9b3d83ff83" +dependencies = [ + "accessor", + "bit_field", + "num-derive 0.3.3", + "num-traits", + "paste", +] + [[package]] name = "zerocopy" -version = "0.6.3" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b9c234616391070b0b173963ebc65a9195068e7ed3731c6edac2ec45ebe106" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", "zerocopy-derive", @@ -2196,11 +2259,11 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.6.3" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f7f3a471f98d0a61c34322fbbfd10c384b07687f680d4119813713f72308d91" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.72", ] diff --git a/Cargo.toml b/Cargo.toml index 2d41b98b64..e83e841f81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ members = [ "crates/driver_net", "crates/driver_pci", "crates/driver_virtio", + "crates/driver_usb", "crates/flatten_objects", "crates/handler_table", "crates/kernel_guard", @@ -36,6 +37,7 @@ members = [ "crates/timer_list", "crates/tuple_for_each", + "modules/axalloc", "modules/axconfig", "modules/axdisplay", @@ -71,7 +73,9 @@ members = [ "apps/task/priority", "apps/task/tls", "apps/cli", - "apps/boards/raspi4", + "apps/usb", + "apps/boards/raspi4", + "apps/boards/raspi4-usb", "apps/uvc", "apps/ch341", ] diff --git a/Makefile b/Makefile index b351596584..58be5a464d 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,9 @@ # - `ACCEL`: Enable hardware acceleration (KVM on linux) # - `QEMU_LOG`: Enable QEMU logging (log file is "qemu.log") # - `NET_DUMP`: Enable network packet dump (log file is "netdump.pcap") -# - `NET_DEV`: QEMU netdev backend types: user, tap +# - `NET_DEV`: QEMU netdev backend types: user, tap, bridge +# - `VFIO_PCI`: PCI device address in the format "bus:dev.func" to passthrough +# - `VHOST`: Enable vhost-net for tap backend (only for `NET_DEV=tap`) # * Network options: # - `IP`: ArceOS IPv4 address (default is 10.0.2.15 for QEMU user netdev) # - `GW`: Gateway IPv4 address (default is 10.0.2.2 for QEMU user netdev) @@ -48,6 +50,8 @@ DISK_IMG ?= disk.img QEMU_LOG ?= n NET_DUMP ?= n NET_DEV ?= user +VFIO_PCI ?= +VHOST ?= n # Network options IP ?= 10.0.2.15 @@ -103,6 +107,10 @@ else ifeq ($(ARCH), aarch64) ACCEL ?= n PLATFORM_NAME ?= aarch64-qemu-virt TARGET := aarch64-unknown-none-softfloat +# else ifeq ($(ARCH), phytium-pi) +# ACCEL ?= n +# PLATFORM_NAME ?= aarch64-phytium-pi +# TARGET := aarch64-unknown-none-softfloat else $(error "ARCH" must be one of "x86_64", "riscv64", or "aarch64") endif @@ -141,8 +149,12 @@ include scripts/make/utils.mk include scripts/make/build.mk include scripts/make/qemu.mk include scripts/make/test.mk + + ifeq ($(PLATFORM_NAME), aarch64-raspi4) include scripts/make/raspi4.mk +else ifeq ($(PLATFORM_NAME), aarch64-phytium-pi) + include scripts/make/phytium-pi.mk else ifeq ($(PLATFORM_NAME), aarch64-bsta1000b) include scripts/make/bsta1000b-fada.mk endif @@ -154,6 +166,14 @@ disasm: run: build justrun +shumei: + qemu-system-aarch64 -m 2G -smp 4 -cpu cortex-a72 -machine raspi4b -nographic -kernel kernel8.img + +# debugs: +# qemu-system-aarch64 -s -S -machine raspi4b -m 2G -cpu cortex-a72 -kernel kernel8.img -nographic + + + justrun: $(call run_qemu) diff --git a/api/arceos_api/src/lib.rs b/api/arceos_api/src/lib.rs index 69fec6eaf4..eacf0f5f2d 100644 --- a/api/arceos_api/src/lib.rs +++ b/api/arceos_api/src/lib.rs @@ -3,7 +3,6 @@ //! [ArceOS]: https://github.com/rcore-os/arceos #![no_std] -#![feature(ip_in_core)] #![feature(doc_auto_cfg)] #![feature(doc_cfg)] #![allow(unused_imports)] diff --git a/api/arceos_posix_api/src/lib.rs b/api/arceos_posix_api/src/lib.rs index 1e0e126e9e..75eb9bd7ce 100644 --- a/api/arceos_posix_api/src/lib.rs +++ b/api/arceos_posix_api/src/lib.rs @@ -4,7 +4,6 @@ #![cfg_attr(all(not(test), not(doc)), no_std)] #![feature(ip_in_core)] -#![feature(result_option_inspect)] #![feature(doc_cfg)] #![feature(doc_auto_cfg)] #![allow(clippy::missing_safety_doc)] diff --git a/api/axfeat/Cargo.toml b/api/axfeat/Cargo.toml index 2947a7ea1d..8d0ea37dee 100644 --- a/api/axfeat/Cargo.toml +++ b/api/axfeat/Cargo.toml @@ -45,6 +45,7 @@ net = ["alloc", "paging", "axdriver/virtio-net", "dep:axnet", "axruntime/net"] # Display display = ["alloc", "paging", "axdriver/virtio-gpu", "dep:axdisplay", "axruntime/display"] + # Device drivers bus-mmio = ["axdriver?/bus-mmio"] bus-pci = ["axdriver?/bus-pci"] diff --git a/apps/boards/raspi4-usb/Cargo.toml b/apps/boards/raspi4-usb/Cargo.toml new file mode 100644 index 0000000000..5c77842be0 --- /dev/null +++ b/apps/boards/raspi4-usb/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "arceos-raspi4-usb" +version = "0.1.0" +edition = "2021" +authors = ["Rui Zhou "] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +axstd = { path = "../../../ulib/axstd" } + + + diff --git a/apps/boards/raspi4-usb/README.md b/apps/boards/raspi4-usb/README.md new file mode 100644 index 0000000000..bfaab99928 --- /dev/null +++ b/apps/boards/raspi4-usb/README.md @@ -0,0 +1,25 @@ + +### 编译生成并烧录 + +Raspberry Pi Imager 烧录一个64位系统SD卡,删除所有内容。 +从Raspberry Pi firmware repo中将以下文件复制到SD卡上: + +[fixup4.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat)
+[start4.elf](https://github.com/raspberrypi/firmware/raw/master/boot/start4.elf)
+[bcm2711-rpi-4-b.dtb](https://github.com/raspberrypi/firmware/raw/master/boot/bcm2711-rpi-4-b.dtb)
+ +[config.txt](./config.txt) + +从 tools 文件夹复制 chainboot 固件到SD卡上: +[kernel8.img](../../../tools/raspi4/common/image/chainboot/kernel8.img) + + + + +项目根目录下执行: +```shell +make PLATFORM=aarch64-raspi4 A=apps/boards/raspi4-usb LOG=debug chainboot +``` +开发板接好 usb转串口,插入usb,并上电。 + +![](./hello.png) \ No newline at end of file diff --git a/apps/boards/raspi4-usb/config.txt b/apps/boards/raspi4-usb/config.txt new file mode 100644 index 0000000000..a53f6ed413 --- /dev/null +++ b/apps/boards/raspi4-usb/config.txt @@ -0,0 +1,2 @@ +arm_64bit=1 +init_uart_clock=48000000 \ No newline at end of file diff --git a/apps/boards/raspi4-usb/hello.png b/apps/boards/raspi4-usb/hello.png new file mode 100644 index 0000000000..9eaf682cb3 Binary files /dev/null and b/apps/boards/raspi4-usb/hello.png differ diff --git a/apps/boards/raspi4-usb/src/main.rs b/apps/boards/raspi4-usb/src/main.rs new file mode 100644 index 0000000000..7f65154696 --- /dev/null +++ b/apps/boards/raspi4-usb/src/main.rs @@ -0,0 +1,10 @@ +#![no_std] +#![no_main] + +use axstd::println; + +#[no_mangle] +fn main() { + println!("usb test!!!"); +} + diff --git a/apps/ch341/Cargo.toml b/apps/ch341/Cargo.toml new file mode 100644 index 0000000000..cb5465bb1c --- /dev/null +++ b/apps/ch341/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ch341" +version = "0.1.0" +edition = "2021" + +[features] +default = [] + +[dependencies] +axstd = { path = "../../ulib/axstd" } +driver_usb ={ path = "../../crates/driver_usb",features=["xhci"]} +axalloc = { path = "../../modules/axalloc"} +axfeat = {path = "../../api/axfeat", features = ["multitask","sched_rr","paging"]} +axhal = {path="../../modules/axhal"} \ No newline at end of file diff --git a/apps/ch341/src/main.rs b/apps/ch341/src/main.rs new file mode 100644 index 0000000000..31ecc105d5 --- /dev/null +++ b/apps/ch341/src/main.rs @@ -0,0 +1,40 @@ +#![no_std] +#![no_main] +#![allow(warnings)] + +use axalloc::GlobalNoCacheAllocator; +use axhal::{mem::VirtAddr, paging::PageSize}; +use driver_usb::{USBSystem, USBSystemConfig}; + +#[macro_use] +extern crate axstd as std; + +#[derive(Clone)] +struct PlatformAbstraction; + +impl driver_usb::abstractions::OSAbstractions for PlatformAbstraction { + type VirtAddr = VirtAddr; + type DMA = GlobalNoCacheAllocator; + + const PAGE_SIZE: usize = PageSize::Size4K as usize; + + fn dma_alloc(&self) -> Self::DMA { + axalloc::global_no_cache_allocator() + } +} + +impl driver_usb::abstractions::HALAbstractions for PlatformAbstraction { + fn force_sync_cache() {} +} + +#[no_mangle] +fn main() { + let mut usbsystem = driver_usb::USBSystem::new({ + USBSystemConfig::new(0xffff_0000_31a0_8000, 48, 0, PlatformAbstraction) + }) + .init() + .init_probe() + .drive_all1() + .init_probe1() + .drive_all2(); +} diff --git a/apps/cli/src/cmd.rs b/apps/cli/src/cmd.rs index 9fed8c4cb5..139ace43e3 100644 --- a/apps/cli/src/cmd.rs +++ b/apps/cli/src/cmd.rs @@ -1,5 +1,7 @@ use std::io::{self}; +// use driver_usb::host::{xhci::MemoryMapper, USBHost, USBHostConfig, Xhci}; + #[cfg(all(not(feature = "axstd"), unix))] macro_rules! print_err { @@ -18,9 +20,23 @@ const CMD_TABLE: &[(&str, CmdHandler)] = &[ ("help", do_help), ("uname", do_uname), ("ldr", do_ldr), - ("str", do_str) + ("str", do_str), + // ("test_xhci", test_xhci), ]; +// fn test_xhci(_args: &str) { +// // driver_usb::try_init(0x31a08000 as usize); +// // unsafe { xhci::Registers::new(0xffff_0000_31a0_8000 as usize, MemoryMapper {}) }; + +// let phytium_cfg_id_0 = (0xffff_0000_31a0_8000, 48, 0); + + +// let config = USBHostConfig::new( +// phytium_cfg_id_0.0, phytium_cfg_id_0.1, phytium_cfg_id_0.2); +// let usb = USBHost::::new(config).unwrap(); + +// } + fn do_uname(_args: &str) { let arch = option_env!("AX_ARCH").unwrap_or(""); let platform = option_env!("AX_PLATFORM").unwrap_or(""); @@ -83,7 +99,6 @@ fn do_ldr(args: &str) { } } - // use crate::mem::phys_to_virt; // use core::ptr::{read_volatile, write_volatile}; @@ -131,7 +146,6 @@ fn do_str(args: &str) { str_one(addr, val).unwrap(); // 调用 str_one 函数并传递 addr 和 val } } - } pub fn run_cmd(line: &[u8]) { @@ -153,3 +167,5 @@ fn split_whitespace(str: &str) -> (&str, &str) { str.find(char::is_whitespace) .map_or((str, ""), |n| (&str[..n], str[n + 1..].trim())) } + +fn test_net(str: &str) {} diff --git a/apps/cli/src/main.rs b/apps/cli/src/main.rs index e10360e87d..192a73cb26 100644 --- a/apps/cli/src/main.rs +++ b/apps/cli/src/main.rs @@ -1,5 +1,6 @@ #![cfg_attr(feature = "axstd", no_std)] #![cfg_attr(feature = "axstd", no_main)] +#![allow(warnings)] #[macro_use] #[cfg(feature = "axstd")] diff --git a/apps/fs/shell/src/cmd.rs b/apps/fs/shell/src/cmd.rs index dd652e892d..7bcc5d5ba0 100644 --- a/apps/fs/shell/src/cmd.rs +++ b/apps/fs/shell/src/cmd.rs @@ -28,7 +28,7 @@ const CMD_TABLE: &[(&str, CmdHandler)] = &[ ("rm", do_rm), ("uname", do_uname), ("ldr", do_ldr), - ("str", do_str) + ("str", do_str), ]; fn file_type_to_char(ty: FileType) -> char { @@ -348,7 +348,6 @@ fn do_str(args: &str) { str_one(addr, val).unwrap(); // 调用 str_one 函数并传递 addr 和 val } } - } pub fn run_cmd(line: &[u8]) { diff --git a/apps/helloworld/Cargo.toml b/apps/helloworld/Cargo.toml index 9b759ec55a..0d09b7715e 100644 --- a/apps/helloworld/Cargo.toml +++ b/apps/helloworld/Cargo.toml @@ -8,3 +8,4 @@ authors = ["Yuekai Jia "] [dependencies] axstd = { path = "../../ulib/axstd", optional = true } +# axfeat = {path = "../../api/axfeat/",features = ["phytium","bus-pci","usb-host"]} diff --git a/apps/helloworld/helloworld_aarch64-phytium-pi.elf.id0 b/apps/helloworld/helloworld_aarch64-phytium-pi.elf.id0 new file mode 100644 index 0000000000..f5dbc7c766 Binary files /dev/null and b/apps/helloworld/helloworld_aarch64-phytium-pi.elf.id0 differ diff --git a/apps/helloworld/helloworld_aarch64-phytium-pi.elf.id1 b/apps/helloworld/helloworld_aarch64-phytium-pi.elf.id1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/helloworld/helloworld_aarch64-phytium-pi.elf.nam b/apps/helloworld/helloworld_aarch64-phytium-pi.elf.nam new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/usb/Cargo.toml b/apps/usb/Cargo.toml new file mode 100644 index 0000000000..1ab4baab29 --- /dev/null +++ b/apps/usb/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "arceos-usb" +version = "0.1.0" +edition = "2021" +authors = ["zhourui "] + + +[features] +default = [] + +[dependencies] + +axstd = { path = "../../ulib/axstd" } +axalloc = { path = "../../modules/axalloc"} \ No newline at end of file diff --git a/apps/usb/src/main.rs b/apps/usb/src/main.rs new file mode 100644 index 0000000000..4a10cd2d79 --- /dev/null +++ b/apps/usb/src/main.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] +#![allow(warnings)] + +#[macro_use] +extern crate axstd as std; + +// use core::time::Duration; +// use std::thread::sleep; + +// use axalloc::GlobalNoCacheAllocator; +// use driver_usb::{ +// host::{ +// xhci::{self, Xhci}, +// USBHost, USBHostConfig, +// }, +// OsDep, +// }; + +// #[derive(Clone)] +// struct OsDepImp; + +// impl OsDep for OsDepImp { +// type DMA = GlobalNoCacheAllocator; + +// const PAGE_SIZE: usize = axalloc::PAGE_SIZE; +// fn dma_alloc(&self) -> Self::DMA { +// axalloc::global_no_cache_allocator() +// } + +// fn force_sync_cache() {} +// } + +#[no_mangle] +fn main() { + println!("since we rearranged the code frame, this app has been deprecated,if you want to use, please refer to apps/uvc to modify these codes"); + // let phytium_cfg_id_0 = (0xffff_0000_31a0_8000, 48, 0); + + // let config = USBHostConfig::new( + // phytium_cfg_id_0.0, + // phytium_cfg_id_0.1, + // phytium_cfg_id_0.2, + // OsDepImp {}, + // ); + + // let mut usb = USBHost::new::>(config).unwrap(); + + // sleep(Duration::from_millis(300)); + + // usb.poll().unwrap(); + + // let mut device_list = usb.device_list(); + + // let mut hid = device_list.pop().unwrap(); + + // hid.test_hid_mouse().unwrap(); + // println!("test done!"); + // // hid.test_mass_storage().unwrap(); +} diff --git a/apps/uvc/Cargo.toml b/apps/uvc/Cargo.toml new file mode 100644 index 0000000000..3c40e724d7 --- /dev/null +++ b/apps/uvc/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "arceos-uvc" +version = "0.1.0" +edition = "2021" +authors = ["dbydd "] + +[dependencies] + +axstd = { path = "../../ulib/axstd" } +driver_usb ={ path = "../../crates/driver_usb",features=["xhci"]} +axalloc = { path = "../../modules/axalloc"} +axfeat = {path = "../../api/axfeat", features = ["multitask","sched_rr","paging"]} +axhal = {path="../../modules/axhal"} \ No newline at end of file diff --git a/apps/uvc/src/main.rs b/apps/uvc/src/main.rs new file mode 100644 index 0000000000..359c54feb2 --- /dev/null +++ b/apps/uvc/src/main.rs @@ -0,0 +1,38 @@ +#![no_std] +#![no_main] +#![allow(warnings)] + +use axalloc::GlobalNoCacheAllocator; +use axhal::{mem::VirtAddr, paging::PageSize}; +use driver_usb::{USBSystem, USBSystemConfig}; + +#[macro_use] +extern crate axstd as std; + +#[derive(Clone)] +struct PlatformAbstraction; + +impl driver_usb::abstractions::OSAbstractions for PlatformAbstraction { + type VirtAddr = VirtAddr; + type DMA = GlobalNoCacheAllocator; + + const PAGE_SIZE: usize = PageSize::Size4K as usize; + + fn dma_alloc(&self) -> Self::DMA { + axalloc::global_no_cache_allocator() + } +} + +impl driver_usb::abstractions::HALAbstractions for PlatformAbstraction { + fn force_sync_cache() {} +} + +#[no_mangle] +fn main() { + let mut usbsystem = driver_usb::USBSystem::new({ + USBSystemConfig::new(0xffff_0000_31a0_8000, 48, 0, PlatformAbstraction) + }) + .init() + .init_probe() + .drive_all(); +} diff --git a/arceos-fada.bin.gz b/arceos-fada.bin.gz new file mode 100644 index 0000000000..34f2cc2d3f Binary files /dev/null and b/arceos-fada.bin.gz differ diff --git a/arceos-fada.itb b/arceos-fada.itb new file mode 100644 index 0000000000..f3dd8003c1 Binary files /dev/null and b/arceos-fada.itb differ diff --git a/arceos-phytium-pi.bin.gz b/arceos-phytium-pi.bin.gz new file mode 100644 index 0000000000..b0b3ca43c3 Binary files /dev/null and b/arceos-phytium-pi.bin.gz differ diff --git a/arceos-phytiym-pi.itb b/arceos-phytiym-pi.itb new file mode 100644 index 0000000000..1b4700a7d2 Binary files /dev/null and b/arceos-phytiym-pi.itb differ diff --git a/crates/allocator/src/lib.rs b/crates/allocator/src/lib.rs index 5ced1b9921..7a79161d0e 100644 --- a/crates/allocator/src/lib.rs +++ b/crates/allocator/src/lib.rs @@ -9,7 +9,6 @@ //! - [`IdAllocator`]: Used to allocate unique IDs. #![no_std] -#![feature(result_option_inspect)] #![cfg_attr(feature = "allocator_api", feature(allocator_api))] #[cfg(feature = "bitmap")] diff --git a/crates/driver_block/src/ramdisk.rs b/crates/driver_block/src/ramdisk.rs index 2e240c787b..55eed096b2 100644 --- a/crates/driver_block/src/ramdisk.rs +++ b/crates/driver_block/src/ramdisk.rs @@ -45,7 +45,7 @@ impl RamDisk { } } -impl const BaseDriverOps for RamDisk { +impl BaseDriverOps for RamDisk { fn device_type(&self) -> DeviceType { DeviceType::Block } diff --git a/crates/driver_common/src/lib.rs b/crates/driver_common/src/lib.rs index c249b98837..a341784e5b 100644 --- a/crates/driver_common/src/lib.rs +++ b/crates/driver_common/src/lib.rs @@ -27,6 +27,8 @@ pub enum DeviceType { Net, /// Graphic display device (e.g., GPU) Display, + /// USB host controller + USBHost, } /// The error type for device operation failures. @@ -54,7 +56,6 @@ pub enum DevError { pub type DevResult = Result; /// Common operations that require all device drivers to implement. -#[const_trait] pub trait BaseDriverOps: Send + Sync { /// The name of the device. fn device_name(&self) -> &str; diff --git a/crates/driver_net/Cargo.toml b/crates/driver_net/Cargo.toml index 5018c4a7c8..dfa7fe59d7 100644 --- a/crates/driver_net/Cargo.toml +++ b/crates/driver_net/Cargo.toml @@ -12,9 +12,12 @@ documentation = "https://rcore-os.github.io/arceos/driver_net/index.html" [features] default = [] ixgbe = ["dep:ixgbe-driver"] +phytium=[] [dependencies] spin = "0.9" log = "0.4" driver_common = { path = "../driver_common" } ixgbe-driver = {git = "https://github.com/KuangjuX/ixgbe-driver.git", rev = "8e5eb74", optional = true} +tock-registers="0.8" +bit_field = "0.10" \ No newline at end of file diff --git a/crates/driver_net/src/lib.rs b/crates/driver_net/src/lib.rs index 0f9c9ed363..ec90750fab 100644 --- a/crates/driver_net/src/lib.rs +++ b/crates/driver_net/src/lib.rs @@ -8,7 +8,10 @@ #[cfg(feature = "ixgbe")] /// ixgbe NIC device driver. pub mod ixgbe; + mod net_buf; +#[cfg(feature = "phytium")] +mod phytiym_ethernet_controller; use core::ptr::NonNull; diff --git a/crates/driver_pci/Cargo.toml b/crates/driver_pci/Cargo.toml index 062cbd0a69..1bb6467449 100644 --- a/crates/driver_pci/Cargo.toml +++ b/crates/driver_pci/Cargo.toml @@ -9,5 +9,17 @@ homepage = "https://github.com/rcore-os/arceos" repository = "https://github.com/rcore-os/arceos/tree/main/crates/driver_pci" documentation = "https://rcore-os.github.io/arceos/driver_pci/index.html" +[features] +bcm2711 = [] +virtio = [] + [dependencies] -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers.git", rev = "409ee72" } +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers.git", rev = "4b60f5d" } +log="0.4" +ratio = { path = "../../crates/ratio" } +pci_types = "0.6" +tock-registers="0.8" +bit_field = "0.10" + +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = "9.4" \ No newline at end of file diff --git a/crates/driver_pci/src/bcm2711.rs b/crates/driver_pci/src/bcm2711.rs new file mode 100644 index 0000000000..fe4cd135a0 --- /dev/null +++ b/crates/driver_pci/src/bcm2711.rs @@ -0,0 +1,563 @@ +use crate::types::{ConfigCommand, ConifgPciPciBridge}; +use crate::{err::*, Access, PciAddress}; +use aarch64_cpu::registers::*; +use core::{marker::PhantomData, ops::Add, ptr::NonNull}; +use ratio::Ratio; +use tock_registers::{ + interfaces::{ReadWriteable, Readable, Writeable}, + register_bitfields, register_structs, + registers::{ReadOnly, ReadWrite}, +}; +use virtio_drivers::transport::mmio; + +register_bitfields![ + u32, + // /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */ + // 0x00ac + // BRCM_PCIE_CAP_REGS [], + + // Broadcom STB PCIe Register Offsets + // 0x0188 + RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 [ + LITTLE_ENDIAN OFFSET(0) NUMBITS(1) [], + ENDIAN_MODE_BAR2 OFFSET(0xC) NUMBITS(1) [], + ], + + // 0x043c + RC_CFG_PRIV1_ID_VAL3 [ + CLASS_ID OFFSET(0) NUMBITS(24) [ + pcie_pcie_bridge = 0x060400 + ], + ], + // 0x04dc + // PCIE_RC_CFG_PRIV1_LINK_CAPABILITY [], + + + // 0x1100 + // RC_DL_MDIO_ADDR [], + + // 0x1104 + // RC_DL_MDIO_WR_DATA [], + // 0x1108 + // RC_DL_MDIO_RD_DATA + + // 0x4008 + MISC_MISC_CTRL [ + SCB_ACCESS_EN OFFSET(12) NUMBITS(1) [], + CFG_READ_UR_MODE OFFSET(13) NUMBITS(1) [], + MAX_BURST_SIZE OFFSET(20) NUMBITS(2) [], + SCB0_SIZE OFFSET(27) NUMBITS(5) [ + init_val = 0x17, + ], + SCB1_SIZE OFFSET(22) NUMBITS(5) [], + SCB2_SIZE OFFSET(0) NUMBITS(1) [], + ], + // 0x400c + MISC_CPU_2_PCIE_MEM_WIN0_LO [ + MEM_WIN0_LO OFFSET(0) NUMBITS(32) [ + // TODO + init_val = 0x0000_0000 + ], + ], + // 0x4010 + MISC_CPU_2_PCIE_MEM_WIN0_HI [ + MEM_WIN0_HI OFFSET(0) NUMBITS(32) [ + init_val = 0x0000_0006 + ], + ], + + // 0x4204 + + + // 0x402C + MISC_RC_BAR1_CONFIG_LO [ + MEM_WIN OFFSET(0) NUMBITS(5)[] + ], + + // 0x4034 + MISC_RC_BAR2_CONFIG_LO [ + VALUE_LO OFFSET(0) NUMBITS(32)[ + init_val = 0x11, + ] + ], + // 0x4038 + MISC_RC_BAR2_CONFIG_HI [ + VALUE_HI OFFSET(0) NUMBITS(32)[ + init_val = 0x4, + ] + ], + // 0x403C + MISC_RC_BAR3_CONFIG_LO [ + MEM_WIN OFFSET(0) NUMBITS(5)[] + ], + + // 0x4044 + // MISC_MSI_BAR_CONFIG_LO + // 0x4048 + // MISC_MSI_BAR_CONFIG_HI + // 0x404c + // MISC_MSI_DATA_CONFIG + // 0x4060 + // MISC_EOI_CTRL + // 0x4064 + // MISC_PCIE_CTRL + // 0x4068 + MISC_PCIE_STATUS [ + CHECK_BITS OFFSET(4) NUMBITS(2)[], + RC_MODE OFFSET(7) NUMBITS(1)[], + ], + // 0x406c + MISC_REVISION [ + MISC_REVISION OFFSET(0) NUMBITS(32)[] + ], + + // 0x4070 + MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT [ + MEM_WIN0_BASE_LIMIT OFFSET(0) NUMBITS(32)[ + // TODO + init_val = 0 + ] + ], + // 0x4080 + MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI [ + MEM_WIN0_BASE_HI OFFSET(0) NUMBITS(32)[ + init_val = 6 + ] + ], + // 0x4084 + MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI [ + MEM_WIN0_LIMIT_HI OFFSET(0) NUMBITS(32)[ + init_val = 6 + ] + ], + // 0x4204 + MISC_HARD_PCIE_HARD_DEBUG [ + CLKREQ_DEBUG_ENABLE OFFSET(0) NUMBITS(1) [], + CLKREQ_L1SS_ENABLE OFFSET(21) NUMBITS(1) [], + SERDES_IDDQ OFFSET(27) NUMBITS(1) [], + ], + + // 0x4300 INTR2_CPU_BASE + INTR2_CPU_STATUS [ + INTR_STATUS OFFSET(0) NUMBITS(32) [], + ], + // 0x4304 0x4300 + 0x4 + INTR2_CPU_SET [ + INTR_SET OFFSET(0) NUMBITS(32) [], + ], + // 0x4308 0x4300 + 0x8 + INTR2_CPU_CLR [ + INTR_CLR OFFSET(0) NUMBITS(32) [] + ], + // 0x430c 0x4300 + 0x0c + INTR2_CPU_MASK_STATUS [ + INTR_MASK_STATUS OFFSET(0) NUMBITS(32) [] + ], + // 0x4310 0x4300 + 0x10 + INTR2_CPU_MASK_SET [ + INTR_MASK_SET OFFSET(0) NUMBITS(32) [] + ], + // 0x4314 0x4500 + 0x14 + INTR2_CPU_MASK_CLR [ + INTR_MASK_CLR OFFSET(0) NUMBITS(32) [] + ], + // 0x4500 MSI_INTR2_BASE + MSI_INTR2_STATUS [ + INTR_STATUS OFFSET(0) NUMBITS(32) [], + ], + // 0x4504 0x4500 + 0x4 + MSI_INTR2_SET [ + INTR_SET OFFSET(0) NUMBITS(32) [], + ], + // 0x4508 0x4500 + 0x8 + MSI_INTR2_CLR [ + INTR_CLR OFFSET(0) NUMBITS(32) [] + ], + // 0x450c 0x4500 + 0x0c + MSI_INTR2_MASK_STATUS [ + INTR_MASK_STATUS OFFSET(0) NUMBITS(32) [] + ], + // 0x4510 0x4500 + 0x10 + MSI_INTR2_MASK_SET [ + INTR_MASK_SET OFFSET(0) NUMBITS(32) [] + ], + // 0x4514 0x4500 + 0x14 + MSI_INTR2_MASK_CLR [ + INTR_MASK_CLR OFFSET(0) NUMBITS(32) [] + ], + + + // 0x8000 + // EXT_CFG_DATA + // 0x9000 + // EXT_CFG_INDEX + + // 0x9210 + RGR1_SW_INIT_1 [ + RGR1_SW_INTI_1_PERST OFFSET(0) NUMBITS(1) [], + RGR1_SW_INTI_1_INIT OFFSET(1) NUMBITS(1) [], + ], + + RC_CFG_VENDOR_SPECIFIC_REG1 [ + ENDIAN_MODE OFFSET(2) NUMBITS(2) [ + LITTLE_ENDIAN = 0 + ], + ], + + RC_CFG_PRIV1_LINK_CAPABILITY [ + ASPM_SUPPORT OFFSET(10) NUMBITS(2)[ + + ] + ] + +]; + +register_structs! { + /// Pl011 registers. + BCM2711PCIeHostBridgeRegs { + (0x00 => _rsvd1), + (0x0188 => rc_cfg_vendor_vendor_specific_reg1: ReadWrite), + (0x018C => _rsvd222), + (0x043c => rc_cfg_priv1_id_val3: ReadWrite), + (0x0440 => _rsvdd2), + (0x04dc => rc_cfg_priv1_link_capability: ReadWrite), + (0x04e0 => _rsvdd3), + (0x1100 => rc_dl_mdio_addr), + (0x1104 => rc_dl_mdio_wr_data), + (0x1108 => rc_dl_mdio_rd_data), + (0x4008 => misc_misc_ctrl: ReadWrite), + (0x400C => misc_cpu_2_pcie_mem_win0_lo: ReadWrite), + (0x4010 => misc_cpu_2_pcie_mem_win0_hi: ReadWrite), + (0x4014 => _rsvd22), + (0x4028 => _rsvd2), + (0x402C => misc_rc_bar1_config_lo: ReadWrite), + (0x4030 => _rsvdd), + (0x4034 => misc_rc_bar2_config_lo: ReadWrite), + (0x4038 => misc_rc_bar2_config_hi: ReadWrite), + (0x403C => misc_rc_bar3_config_lo: ReadWrite), + (0x4040 => _rsvddd), + (0x4044 => misc_msi_bar_config_lo), + (0x4048 => misc_msi_bar_config_hi), + (0x404c => misc_msi_data_config ), + (0x4060 => misc_eoi_ctrl), + (0x4064 => misc_pcie_ctrl), + (0x4068 => misc_pcie_status: ReadOnly), + (0x406C => misc_revision: ReadWrite), + (0x4070 => misc_cpu_2_pcie_mem_win0_base_limit: ReadWrite), + (0x4074 => hole), + (0x4080 => misc_cpu_2_pcie_mem_win0_base_hi: ReadWrite), + (0x4084 => misc_cpu_2_pcie_mem_win0_limit_hi: ReadWrite), + (0x4088 => hole2), + (0x4204 => misc_hard_pcie_hard_debug: ReadWrite), + (0x4208 => _rsvd3), + /// cpu intr + (0x4300 => intr2_cpu_status: ReadWrite), + (0x4304 => intr2_cpu_set: ReadWrite), + (0x4308 => intr2_cpu_clr: ReadWrite), + (0x430C => intr2_cpu_mask_status: ReadWrite), + (0x4310 => intr2_cpu_mask_set: ReadWrite), + (0x4314 => intr2_cpu_mask_clr: ReadWrite), + (0x4318 => hole3), + /// msi intr + (0x4500 => msi_intr2_status: ReadWrite), + (0x4504 => msi_intr2_set: ReadWrite), + (0x4508 => msi_intr2_clr: ReadWrite), + (0x450C => msi_intr2_mask_status: ReadWrite), + (0x4510 => msi_intr2_mask_set: ReadWrite), + (0x4514 => msi_intr2_mask_clr: ReadWrite), + (0x4518 => hole4), + /// Interrupt Clear Register. + (0x9210 => rgr1_sw_init: ReadWrite), + (0x9214 => _rsvd4), + (0x9310 => @END), + } +} + +impl BCM2711PCIeHostBridgeRegs { + fn pcie_link_up(&self) -> bool { + self.misc_pcie_status.read(MISC_PCIE_STATUS::CHECK_BITS) == 0x3 + } + + fn set_gen(&self, gen: u32) { + const PCI_EXP_LNKCTL2: usize = 48; + const PCI_EXP_LNKCAP: usize = 12; + const PCI_EXP_LNKCAP_SLS: u32 = 0x0000000f; + + unsafe { + let cap_base = self as *const BCM2711PCIeHostBridgeRegs as *const u8 as usize + 0x00ac; + let mut lnkctl2 = ((cap_base + PCI_EXP_LNKCTL2) as *const u16).read_volatile(); + let mut lnkcap = ((cap_base + PCI_EXP_LNKCAP) as *const u32).read_volatile(); + lnkcap = (lnkcap & !PCI_EXP_LNKCAP_SLS) | gen; + + ((cap_base + PCI_EXP_LNKCAP) as *mut u32).write_volatile(lnkcap); + + lnkctl2 = (lnkctl2 & !0xf) | gen as u16; + + ((cap_base + PCI_EXP_LNKCTL2) as *mut u16).write_volatile(lnkctl2); + } + } +} + +use core::time::Duration; +use log::{debug, info}; + +const RGR1_SW_INIT_1: usize = 0x9210; +const EXT_CFG_INDEX: usize = 0x9000; +const EXT_CFG_DATA: usize = 0x8000; +// const EXT_CFG_DATA: usize = 0x9004; + +#[derive(Clone)] +pub struct BCM2711 {} + +fn cfg_index(addr: PciAddress) -> usize { + ((addr.device as u32) << 15 | (addr.function as u32) << 12 | (addr.bus as u32) << 20) as usize +} + +impl BCM2711 { + unsafe fn do_setup(mmio_base: usize) { + let regs = &mut *(mmio_base as *mut BCM2711PCIeHostBridgeRegs); + + debug!("PCIe link start @0x{:X}...", mmio_base); + /* + * Reset the bridge, assert the fundamental reset. Note for some SoCs, + * e.g. BCM7278, the fundamental reset should not be asserted here. + * This will need to be changed when support for other SoCs is added. + */ + regs.rgr1_sw_init.modify( + RGR1_SW_INIT_1::RGR1_SW_INTI_1_INIT::SET + RGR1_SW_INIT_1::RGR1_SW_INTI_1_PERST::SET, + ); + debug!("assert fundamental reset"); + /* + * The delay is a safety precaution to preclude the reset signal + * from looking like a glitch. + */ + busy_wait(Duration::from_micros(100)); + + /* Take the bridge out of reset */ + regs.rgr1_sw_init + .modify(RGR1_SW_INIT_1::RGR1_SW_INTI_1_INIT::CLEAR); + debug!("deassert bridge reset"); + + // enable serdes + regs.misc_hard_pcie_hard_debug + .modify(MISC_HARD_PCIE_HARD_DEBUG::SERDES_IDDQ::CLEAR); + debug!("enable serdes"); + /* Wait for SerDes to be stable */ + busy_wait(core::time::Duration::from_micros(100)); + + /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */ + regs.misc_misc_ctrl.write( + MISC_MISC_CTRL::MAX_BURST_SIZE::SET + + MISC_MISC_CTRL::SCB_ACCESS_EN::SET + + MISC_MISC_CTRL::CFG_READ_UR_MODE::SET + + MISC_MISC_CTRL::SCB2_SIZE::SET, + ); + + regs.misc_rc_bar2_config_lo + .write(MISC_RC_BAR2_CONFIG_LO::VALUE_LO::init_val); + regs.misc_rc_bar2_config_hi + .write(MISC_RC_BAR2_CONFIG_HI::VALUE_HI::init_val); + + regs.misc_misc_ctrl.set(0x88003000); + + /* Disable the PCIe->GISB memory window (RC_BAR1) */ + regs.misc_rc_bar1_config_lo + .modify(MISC_RC_BAR1_CONFIG_LO::MEM_WIN::CLEAR); + /* Disable the PCIe->SCB memory window (RC_BAR3) */ + regs.misc_rc_bar3_config_lo + .modify(MISC_RC_BAR3_CONFIG_LO::MEM_WIN::CLEAR); + + /* Mask all interrupts since we are not handling any yet */ + regs.msi_intr2_mask_set + .write(MSI_INTR2_MASK_SET::INTR_MASK_SET::SET); + + /* Clear any interrupts we find on boot */ + regs.msi_intr2_clr.write(MSI_INTR2_CLR::INTR_CLR::SET); + + /* Unassert the fundamental reset */ + regs.rgr1_sw_init + .modify(RGR1_SW_INIT_1::RGR1_SW_INTI_1_PERST::CLEAR); + + /* + * Wait for 100ms after PERST# deassertion; see PCIe CEM specification + * sections 2.2, PCIe r5.0, 6.6.1. + */ + busy_wait(core::time::Duration::from_millis(100)); + + debug!("PCIe wait for link up..."); + + /* Give the RC/EP time to wake up, before trying to configure RC. + * Intermittently check status for link-up, up to a total of 100ms. + */ + for _ in 0..100 { + if regs.pcie_link_up() { + break; + } + busy_wait(core::time::Duration::from_millis(1)); + } + + if !regs.pcie_link_up() { + panic!("pcie link down!"); + } + + // check if controller is running in root complex mode. if bit 7 is not set, and error + { + let val = regs.misc_pcie_status.read(MISC_PCIE_STATUS::RC_MODE); + if val != 0x1 { + panic!("PCIe controller is not running in root complex mode"); + } + } + + // outbound memory + // regs.misc_cpu_2_pcie_mem_win0_lo.set(0xC0000000); + // regs.misc_cpu_2_pcie_mem_win0_hi.set(0x0); + regs.misc_cpu_2_pcie_mem_win0_lo.set(0x0); + regs.misc_cpu_2_pcie_mem_win0_hi.set(0x6); + regs.misc_cpu_2_pcie_mem_win0_base_limit.set(0x3FF00000); + regs.misc_cpu_2_pcie_mem_win0_base_hi + .write(MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI::MEM_WIN0_BASE_HI::init_val); + regs.misc_cpu_2_pcie_mem_win0_limit_hi + .write(MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI::MEM_WIN0_LIMIT_HI::init_val); + /* + * For config space accesses on the RC, show the right class for + * a PCIe-PCIe bridge (the default setting is to be EP mode). + */ + regs.rc_cfg_priv1_id_val3 + .modify(RC_CFG_PRIV1_ID_VAL3::CLASS_ID::pcie_pcie_bridge); + + // ssc + //todo + + let lnksta = ((mmio_base + 0xac + 18) as *const u16).read_volatile(); + + let cls = lnksta & 0xf; + + let nlw = (lnksta & 0x03f0) >> 4; + + info!( + "PCIe BRCM: link up, {} Gbps x{:?}", + link_speed_to_str(cls), + nlw + ); + + regs.rc_cfg_vendor_vendor_specific_reg1 + .write(RC_CFG_VENDOR_SPECIFIC_REG1::ENDIAN_MODE::LITTLE_ENDIAN); + + /* + * We used to enable the CLKREQ# input here, but a few PCIe cards don't + * attach anything to the CLKREQ# line, so we shouldn't assume that + * it's connected and working. The controller does allow detecting + * whether the port on the other side of our link is/was driving this + * signal, so we could check before we assume. But because this signal + * is for power management, which doesn't make sense in a bootloader, + * let's instead just unadvertise ASPM support. + */ + regs.rc_cfg_priv1_link_capability + .modify(RC_CFG_PRIV1_LINK_CAPABILITY::ASPM_SUPPORT::CLEAR); + } +} + +fn link_speed_to_str(cls: u16) -> &'static str { + match cls { + 0x1 => "2.5", + 0x2 => "5.0", + 0x3 => "8.0", + _ => "??", + } +} + +impl Access for BCM2711 { + fn map_conf(mmio_base: usize, addr: PciAddress) -> Option { + // bus 0 bus 1 只有一个Device + if addr.bus <= 2 && addr.device > 0 { + return None; + } + + if addr.bus == 0 { + return Some(mmio_base); + } + + let idx = cfg_index(addr); + unsafe { + ((mmio_base + EXT_CFG_INDEX) as *mut u32).write_volatile(idx as u32); + } + return Some(mmio_base + EXT_CFG_DATA); + } + + fn probe_bridge(mmio_base: usize, bridge: &ConifgPciPciBridge) { + debug!("bridge bcm2711"); + + bridge.set_cache_line_size(64 / 4); + bridge.set_memory_base((0xF8000000u32 >> 16) as u16); + bridge.set_memory_limit((0xF8000000u32 >> 16) as u16); + bridge.set_control(0x01); + unsafe { + (bridge.cfg_addr as *mut u8) + .offset(0xac + 0x1c) + .write_volatile(0x10); + } + + bridge.to_header().set_command([ + ConfigCommand::MemorySpaceEnable, + ConfigCommand::BusMasterEnable, + ConfigCommand::ParityErrorResponse, + ConfigCommand::SERREnable, + ]) + } + + fn setup(mmio_base: usize) { + init_early(); + unsafe { + Self::do_setup(mmio_base); + } + } +} + +/// Number of nanoseconds in a second. +pub const NANOS_PER_SEC: u64 = 1_000_000_000; +static mut CNTPCT_TO_NANOS_RATIO: Ratio = Ratio::zero(); +static mut NANOS_TO_CNTPCT_RATIO: Ratio = Ratio::zero(); +/// Early stage initialization: stores the timer frequency. +fn init_early() { + let freq = CNTFRQ_EL0.get(); + unsafe { + CNTPCT_TO_NANOS_RATIO = Ratio::new(NANOS_PER_SEC as u32, freq as u32); + NANOS_TO_CNTPCT_RATIO = CNTPCT_TO_NANOS_RATIO.inverse(); + } +} + +pub fn current_ticks() -> u64 { + CNTPCT_EL0.get() +} +/// Converts hardware ticks to nanoseconds. +#[inline] +pub fn ticks_to_nanos(ticks: u64) -> u64 { + unsafe { CNTPCT_TO_NANOS_RATIO.mul_trunc(ticks) } +} + +/// Converts nanoseconds to hardware ticks. +#[inline] +pub fn nanos_to_ticks(nanos: u64) -> u64 { + unsafe { NANOS_TO_CNTPCT_RATIO.mul_trunc(nanos) } +} + +/// Returns the current clock time in nanoseconds. +pub fn current_time_nanos() -> u64 { + ticks_to_nanos(current_ticks()) +} + +pub fn current_time() -> Duration { + Duration::from_nanos(current_time_nanos()) +} + +/// Busy waiting for the given duration. +pub fn busy_wait(dur: Duration) { + busy_wait_until(current_time() + dur); +} + +/// Busy waiting until reaching the given deadline. +pub fn busy_wait_until(deadline: Duration) { + while current_time() < deadline { + core::hint::spin_loop(); + } +} diff --git a/crates/driver_pci/src/err.rs b/crates/driver_pci/src/err.rs new file mode 100644 index 0000000000..ea73b6b27a --- /dev/null +++ b/crates/driver_pci/src/err.rs @@ -0,0 +1,20 @@ +use core::fmt::{Display, Formatter}; + +/// Errors accessing a PCI device. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PciError { + /// The device reported an invalid BAR type. + InvalidBarType, + +} + +impl Display for PciError { + fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { + match self { + Self::InvalidBarType => write!(f, "Invalid PCI BAR type."), + } + } +} + + +pub type Result =core::result:: Result; \ No newline at end of file diff --git a/crates/driver_pci/src/lib.rs b/crates/driver_pci/src/lib.rs index 4ae0b9b978..b3e419a641 100644 --- a/crates/driver_pci/src/lib.rs +++ b/crates/driver_pci/src/lib.rs @@ -7,47 +7,62 @@ //! [2]: https://docs.rs/virtio-drivers/latest/virtio_drivers/transport/pci/bus/index.html #![no_std] +#![allow(warnings)] +#![feature(cfg_match)] -pub use virtio_drivers::transport::pci::bus::{BarInfo, Cam, HeaderType, MemoryBarType, PciError}; -pub use virtio_drivers::transport::pci::bus::{ - CapabilityInfo, Command, DeviceFunction, DeviceFunctionInfo, PciRoot, Status, -}; +#[cfg(feature = "bcm2711")] +mod bcm2711; +extern crate alloc; +pub mod err; +mod root_complex; +pub mod types; +use core::ops::Range; -/// Used to allocate MMIO regions for PCI BARs. -pub struct PciRangeAllocator { - _start: u64, - end: u64, - current: u64, +pub use root_complex::*; +use types::ConifgPciPciBridge; +// pub use virtio_drivers::transport::pci::bus::{BarInfo}; + +#[derive(Clone, Copy)] +pub struct PciAddress { + pub bus: usize, + pub device: usize, + pub function: usize, +} +impl core::fmt::Display for PciAddress { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function) + } } -impl PciRangeAllocator { - /// Creates a new allocator from a memory range. - pub const fn new(base: u64, size: u64) -> Self { - Self { - _start: base, - end: base + size, - current: base, - } +cfg_match! { + cfg(feature = "bcm2711")=>{ + pub type RootComplex = PciRootComplex; } + _=>{ + struct DummyPciRoot; + pub type RootComplex = PciRootComplex; + impl Access for DummyPciRoot { + fn setup(mmio_base: usize) {} - /// Allocates a memory region with the given size. - /// - /// The `size` should be a power of 2, and the returned value is also a - /// multiple of `size`. - pub fn alloc(&mut self, size: u64) -> Option { - if !size.is_power_of_two() { - return None; - } - let ret = align_up(self.current, size); - if ret + size > self.end { - return None; - } + fn probe_bridge(mmio_base: usize, bridge_header: &ConifgPciPciBridge) {} - self.current = ret + size; - Some(ret) + fn map_conf(mmio_base: usize, addr: PciAddress) -> Option { + None + } + } } } -const fn align_up(addr: u64, align: u64) -> u64 { - (addr + align - 1) & !(align - 1) +pub type PciRoot = RootComplex; +pub type DeviceFunction = PciAddress; +pub type BarInfo = types::Bar; + +pub fn new_root_complex(mmio_base: usize, bar_range: Range) -> RootComplex { + PciRootComplex::new(mmio_base, bar_range) +} + +pub trait Access { + fn setup(mmio_base: usize); + fn probe_bridge(mmio_base: usize, bridge_header: &ConifgPciPciBridge); + fn map_conf(mmio_base: usize, addr: PciAddress) -> Option; } diff --git a/crates/driver_pci/src/root_complex.rs b/crates/driver_pci/src/root_complex.rs new file mode 100644 index 0000000000..5c34bb464f --- /dev/null +++ b/crates/driver_pci/src/root_complex.rs @@ -0,0 +1,348 @@ +use crate::err::*; +use crate::types::*; +use crate::Access; +use crate::PciAddress; +use alloc::vec::Vec; +use core::fmt; +use core::fmt::{Display, Formatter}; +use core::marker::PhantomData; +use core::ops::Range; +use log::*; +use tock_registers::interfaces::{ReadWriteable, Readable}; +use tock_registers::{ + register_bitfields, register_structs, + registers::{ReadOnly, ReadWrite}, +}; +const MAX_BUS: usize = 256; +const MAX_DEVICES: usize = 32; +const MAX_FUNCTIONS: usize = 8; + +/// The root complex of a PCI bus. +#[derive(Clone)] +pub struct PciRootComplex { + mmio_base: usize, + allocator: PciRangeAllocator, + _marker: PhantomData, +} + +impl PciRootComplex { + pub fn new(mmio_base: usize, bar_range: Range) -> Self { + A::setup(mmio_base); + Self { + mmio_base, + allocator: PciRangeAllocator::new(bar_range), + _marker: PhantomData::default(), + } + } +} + +impl PciRootComplex { + /// Enumerates PCI devices on the given bus. + pub fn enumerate_bus(&self) -> BusDeviceIterator { + // Safe because the BusDeviceIterator only reads read-only fields. + let root = Self { + mmio_base: self.mmio_base, + allocator: self.allocator.clone(), + _marker: PhantomData::default(), + }; + BusDeviceIterator { + root, + next: PciAddress { + bus: 0, + device: 0, + function: 0, + }, + stack: Vec::new(), + } + } + + pub fn bar_info(&self, bdf: PciAddress, slot: u8) -> Option { + let cfg_addr = A::map_conf(self.mmio_base, bdf).unwrap(); + let mut ep = ConifgEndpoint::new(cfg_addr); + ep.bar(slot) + } + + fn read(&self, bdf: PciAddress, offset: usize)->T{ + let cfg_addr = A::map_conf(self.mmio_base, bdf).unwrap(); + unsafe{ + let addr = cfg_addr + offset; + (addr as *const T).read_volatile() + } + } + + fn write(&self, bdf: PciAddress, offset: usize, value: T){ + let cfg_addr = A::map_conf(self.mmio_base, bdf).unwrap(); + unsafe{ + let addr = cfg_addr + offset; + (addr as *mut T).write_volatile(value) + } + } +} +/// An iterator which enumerates PCI devices and functions on a given bus. +pub struct BusDeviceIterator { + /// This must only be used to read read-only fields, and must not be exposed outside this + /// module, because it uses the same CAM as the main `PciRoot` instance. + root: PciRootComplex, + next: PciAddress, + stack: Vec, +} + +impl BusDeviceIterator {} + +impl Iterator for BusDeviceIterator { + type Item = (PciAddress, DeviceFunctionInfo, ConfigSpace); + + fn next(&mut self) -> Option { + loop { + if self.next.function >= MAX_FUNCTIONS { + self.next.function = 0; + self.next.device += 1; + } + + if self.next.device >= MAX_DEVICES { + if let Some(parent) = self.stack.pop() { + let sub = self.next.bus; + self.next.bus = parent.bus; + self.next.device = parent.device + 1; + self.next.function = 0; + let cfg_addr = A::map_conf(self.root.mmio_base, parent.clone()).unwrap(); + let bridge = ConifgPciPciBridge::new(cfg_addr); + trace!("Bridge {} set subordinate: {:X}", parent, sub); + bridge.set_subordinate_bus_number(sub as _); + } else { + return None; + } + } + + let current = self.next.clone(); + + let cfg_addr = match A::map_conf(self.root.mmio_base, current.clone()) { + Some(c) => c, + None => { + if current.function == 0 { + self.next.device += 1; + } else { + self.next.function += 1; + } + continue; + } + }; + + // debug!("begin: {} @ 0x{:X}", current, cfg_addr); + let header = PciHeader::new(cfg_addr); + let (vid, did) = header.vendor_id_and_device_id(); + // debug!("vid {:X}, did {:X}", vid, did); + + if vid == 0xffff { + if current.function == 0 { + self.next.device += 1; + } else { + self.next.function += 1; + } + continue; + } + let multi = header.has_multiple_functions(); + + let header_type = header.header_type(); + let (dv, bc, sc, interface) = header.revision_and_class(); + let mut info = DeviceFunctionInfo::default(); + info.vendor_id = vid; + info.device_id = did; + info.revision = dv; + info.class = bc; + info.subclass = sc; + info.header_type = header_type; + info.prog_if = interface; + let config_space; + match header_type { + HeaderType::PciPciBridge => { + let bridge = ConifgPciPciBridge::new(cfg_addr); + self.stack.push(current.clone()); + self.next.bus += 1; + self.next.device = 0; + self.next.function = 0; + bridge.set_secondary_bus_number(self.next.bus as _); + bridge.set_subordinate_bus_number(0xff); + A::probe_bridge(self.root.mmio_base, &bridge); + config_space = ConfigSpace { + address: current.clone(), + cfg_addr, + header, + kind: ConfigKind::PciPciBridge { inner: bridge }, + } + } + HeaderType::Endpoint => { + if current.function == 0 && !multi { + self.next.device += 1; + } else { + self.next.function += 1; + } + let ep = config_ep(cfg_addr, &mut self.root.allocator); + config_space = ConfigSpace { + address: current.clone(), + cfg_addr, + header, + kind: ConfigKind::Endpoint { inner: ep }, + } + } + _ => { + if current.function == 0 && !multi { + self.next.device += 1; + } else { + self.next.function += 1; + } + continue; + } + } + + let out = (current.clone(), info, config_space); + return Some(out); + } + + None + } +} + +fn config_ep(cfg_addr: usize, allocator: &mut PciRangeAllocator) -> ConifgEndpoint { + let mut ep = ConifgEndpoint::new(cfg_addr); + let mut slot = 0; + while slot < ConifgEndpoint::MAX_BARS { + let bar = ep.bar(slot); + match bar { + Some(bar) => match bar { + Bar::Io { port } => { + debug!(" BAR {}: IO port: {:X}", slot, port); + } + Bar::Memory64 { + address, + size, + prefetchable, + } => { + let addr = allocator.alloc(size).unwrap(); + unsafe { + ep.write_bar64(slot, addr); + } + debug!( + " BAR {}: MEM [{:#x}, {:#x}){}{}", + slot, + addr, + addr + size, + " 64bit", + if prefetchable { " pref" } else { "" }, + ); + + slot += 1; + } + Bar::Memory32 { + address, + size, + prefetchable, + } => { + let addr = allocator.alloc(size as u64).unwrap() as u32; + unsafe { + ep.write_bar32(slot, addr); + } + debug!( + " BAR {}: MEM [{:#x}, {:#x}){}{}", + slot, + addr, + addr + size, + " 32bit", + if prefetchable { " pref" } else { "" }, + ); + } + }, + None => {} + } + + slot += 1; + } + + ep +} + +/// Information about a PCI device function. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct DeviceFunctionInfo { + /// The PCI vendor ID. + pub vendor_id: u16, + /// The PCI device ID. + pub device_id: u16, + /// The PCI class. + pub class: u8, + /// The PCI subclass. + pub subclass: u8, + /// The PCI programming interface byte. + pub prog_if: u8, + /// The PCI revision ID. + pub revision: u8, + /// The type of PCI device. + pub header_type: HeaderType, +} + +impl Default for DeviceFunctionInfo { + fn default() -> Self { + Self { + header_type: HeaderType::PciPciBridge, + vendor_id: 0, + device_id: 0, + class: 0, + subclass: 0, + prog_if: 0, + revision: 0, + } + } +} + +impl Display for DeviceFunctionInfo { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!( + f, + "{:04X}:{:04X} (class {:02x}.{:02x}, rev {:02x}) {:?}", + self.vendor_id, + self.device_id, + self.class, + self.subclass, + self.revision, + self.header_type, + ) + } +} + +/// Used to allocate MMIO regions for PCI BARs. +#[derive(Clone)] +struct PciRangeAllocator { + range: Range, + current: u64, +} + +impl PciRangeAllocator { + /// Creates a new allocator from a memory range. + pub fn new(range: Range) -> Self { + Self { + range: range.clone(), + current: range.start, + } + } + + /// Allocates a memory region with the given size. + /// + /// The `size` should be a power of 2, and the returned value is also a + /// multiple of `size`. + pub fn alloc(&mut self, size: u64) -> Option { + if !size.is_power_of_two() { + return None; + } + let ret = align_up(self.current, size); + if ret + size > self.range.end { + return None; + } + + self.current = ret + size; + Some(ret) + } +} + +const fn align_up(addr: u64, align: u64) -> u64 { + (addr + align - 1) & !(align - 1) +} diff --git a/crates/driver_pci/src/types.rs b/crates/driver_pci/src/types.rs new file mode 100644 index 0000000000..6a0ae58b1c --- /dev/null +++ b/crates/driver_pci/src/types.rs @@ -0,0 +1,415 @@ +use crate::PciAddress; +use bit_field::BitField; +use tock_registers::interfaces::ReadWriteable; +use tock_registers::interfaces::Readable; +use tock_registers::interfaces::Writeable; +use tock_registers::registers::ReadOnly; +use tock_registers::{register_bitfields, register_structs, registers::ReadWrite}; + +register_bitfields![ + u32, + + RC_CFG_REGS1 [ + VENDOR_ID OFFSET(0) NUMBITS(16) [], + DEVICE_ID OFFSET(16) NUMBITS(16) [], + ], + + RC_CFG_REGS3 [ + REVISION OFFSET(0) NUMBITS(8)[], + INTERFACE OFFSET(8) NUMBITS(8)[], + SUB_CLASS OFFSET(16) NUMBITS(8)[], + BASE_CLASS OFFSET(24) NUMBITS(8)[], + ], + RC_CFG_REGS4 [ + HEADER_TYPE OFFSET(16) NUMBITS(7)[ + Endpoint = 0, + PciPciBridge = 1, + CardBusBridge = 3, + ], + HAS_MULTIPLE_FUNCTIONS OFFSET(23) NUMBITS(1)[ + False = 0, + True = 1, + ] + ], + + RC_CFG_BUS_NUMS_REG1 [ + PRIMARY_BUS_NUMBER OFFSET(0) NUMBITS(8) [], + SECONDARY_BUS_NUMBER OFFSET(8) NUMBITS(8) [], + SUBORDINATE_BUS_NUMBER OFFSET(16) NUMBITS(8) [], + ], +]; + +register_bitfields! { + u16, + RC_CFG_COMMAND[ + IO_SPACE_ENABLE OFFSET(0) NUMBITS(1) [], + MEMORY_SPACE_ENABLE OFFSET(1) NUMBITS(1) [], + BUS_MASTER_ENABLE OFFSET(2) NUMBITS(1) [], + SPECIAL_CYCLE_ENABLE OFFSET(3) NUMBITS(1) [], + MEMORY_WRITE_AND_INVALIDATE OFFSET(4) NUMBITS(1) [], + VGA_PALETTE_SNOOP OFFSET(5) NUMBITS(1) [], + PARITY_ERROR_RESPONSE OFFSET(6) NUMBITS(1) [], + IDSEL_STEP_WAIT_CYCLE_CONTROL OFFSET(7) NUMBITS(1) [], + SERR_ENABLE OFFSET(8) NUMBITS(1) [], + FAST_BACK_TO_BACK_ENABLE OFFSET(9) NUMBITS(1) [], + INTERRUPT_DISABLE OFFSET(10) NUMBITS(1) [], + ], + + RC_CFG_STATUS[ + IMMEDIATE_READINESS OFFSET(0) NUMBITS(3) [], + INTERRUPT_STATUS OFFSET(3) NUMBITS(1) [], + CAPABILITIES_LIST OFFSET(4) NUMBITS(1) [], + CAPABLE_66MHZ OFFSET(5) NUMBITS(1) [], + ], +} + +register_structs! { + HeaderRegs { + (0x00 => reg1: ReadOnly), + (0x04 => command: ReadWrite), + (0x06 => status: ReadOnly), + (0x08 => reg3: ReadOnly), + (0x0c => reg4: ReadOnly), + (0x10 => @END), + } +} + +register_structs! { + PCIBridgeRegs { + (0x00 => _rsvd1), + (0x0C => cache_line_size: ReadWrite), + (0x0D => _rsvd2), + (0x18 => primary_bus_number: ReadWrite), + (0x19 => secondary_bus_number: ReadWrite), + (0x1a => subordinate_bus_number: ReadWrite), + (0x1b => secondary_latency_timer: ReadWrite), + (0x1c => _io), + (0x20 => memory_base: ReadWrite), + (0x22 => memory_limit: ReadWrite), + (0x24 => _rsvd3), + (0x3C => _interrupt_line), + (0x3D => interrupt_pin), + (0x3E => control: ReadWrite), + (0x3F => _rsvd4), + (0x40 => @END), + } +} +register_structs! { + EndpointRegs { + (0x00 => _rsvd1), + (0x10 => bar0: ReadWrite), + (0x14 => bar1: ReadWrite), + (0x18 => bar2: ReadWrite), + (0x1C => bar3: ReadWrite), + (0x20 => bar4: ReadWrite), + (0x24 => bar5: ReadWrite), + (0x28 => _card_bus_cis), + (0x40 => @END), + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum HeaderType { + Endpoint, + PciPciBridge, + CardBusBridge, + Unknown(u8), +} + +#[derive(Clone)] +pub struct PciHeader { + cfg_base: usize, +} + +impl PciHeader { + pub fn new(cfg_base: usize) -> PciHeader { + PciHeader { cfg_base } + } + + fn regs(&self) -> &'static HeaderRegs { + unsafe { &*(self.cfg_base as *const HeaderRegs) } + } + + pub fn vendor_id_and_device_id(&self) -> (u16, u16) { + let regs = self.regs(); + ( + regs.reg1.read(RC_CFG_REGS1::VENDOR_ID) as u16, + regs.reg1.read(RC_CFG_REGS1::DEVICE_ID) as u16, + ) + } + + pub fn has_multiple_functions(&self) -> bool { + match self + .regs() + .reg4 + .read_as_enum(RC_CFG_REGS4::HAS_MULTIPLE_FUNCTIONS) + { + Some(RC_CFG_REGS4::HAS_MULTIPLE_FUNCTIONS::Value::True) => true, + _ => false, + } + } + + pub fn header_type(&self) -> HeaderType { + match self.regs().reg4.read_as_enum(RC_CFG_REGS4::HEADER_TYPE) { + Some(RC_CFG_REGS4::HEADER_TYPE::Value::Endpoint) => HeaderType::Endpoint, + Some(RC_CFG_REGS4::HEADER_TYPE::Value::PciPciBridge) => HeaderType::PciPciBridge, + Some(RC_CFG_REGS4::HEADER_TYPE::Value::CardBusBridge) => HeaderType::CardBusBridge, + None => HeaderType::Unknown(0), + } + } + pub fn revision_and_class(&self) -> (Revision, BaseClass, SubClass, Interface) { + let reg3 = &self.regs().reg3; + return ( + reg3.read(RC_CFG_REGS3::REVISION) as u8, + reg3.read(RC_CFG_REGS3::BASE_CLASS) as u8, + reg3.read(RC_CFG_REGS3::SUB_CLASS) as u8, + reg3.read(RC_CFG_REGS3::INTERFACE) as u8, + ); + } + pub fn set_command(&self, command: impl IntoIterator) { + let cmd = command + .into_iter() + .fold(0u16, |acc, a| acc + a.clone() as u16); + self.regs().command.set(cmd) + } +} + +pub type Revision = u8; +pub type BaseClass = u8; +pub type SubClass = u8; +pub type Interface = u8; + +#[derive(Clone, Copy, Debug)] +#[repr(u16)] +pub enum ConfigCommand { + IoSpaceEnable = 1 << 0, + MemorySpaceEnable = 1 << 1, + BusMasterEnable = 1 << 2, + SpecialCycleEnable = 1 << 3, + MemoryWriteAndInvalidate = 1 << 4, + VGAPaletteSnoop = 1 << 5, + ParityErrorResponse = 1 << 6, + IDSELStepWaitCycleControl = 1 << 7, + SERREnable = 1 << 8, + FastBackToBackEnable = 1 << 9, + InterruptDisable = 1 << 10, +} + +pub struct ConifgPciPciBridge { + pub(crate) cfg_addr: usize, +} + +impl ConifgPciPciBridge { + pub fn new(cfg_addr: usize) -> ConifgPciPciBridge { + ConifgPciPciBridge { cfg_addr } + } + + fn regs(&self) -> &'static PCIBridgeRegs { + unsafe { &*(self.cfg_addr as *const PCIBridgeRegs) } + } + pub fn to_header(&self) -> PciHeader { + PciHeader::new(self.cfg_addr) + } + + pub fn set_primary_bus_number(&self, bus: u8) { + self.regs().primary_bus_number.set(bus); + } + + pub fn set_secondary_bus_number(&self, bus: u8) { + self.regs().secondary_bus_number.set(bus); + } + + pub fn set_subordinate_bus_number(&self, bus: u8) { + self.regs().subordinate_bus_number.set(bus); + } + + pub fn set_memory_base(&self, base: u16) { + self.regs().memory_base.set(base); + } + + pub fn set_memory_limit(&self, limit: u16) { + self.regs().memory_limit.set(limit); + } + + pub fn set_cache_line_size(&self, size: u8) { + self.regs().cache_line_size.set(size); + } + + pub fn set_control(&self, ctl: u8){ + self.regs().control.set(ctl); + } + +} + +pub struct ConifgEndpoint { + cfg_addr: usize, +} +impl ConifgEndpoint { + pub const MAX_BARS: u8 = 6; + + pub fn new(cfg_addr: usize) -> Self { + Self { cfg_addr } + } + + fn regs(&self) -> &'static EndpointRegs { + unsafe { &*(self.cfg_addr as *const EndpointRegs) } + } + pub fn to_header(&self) -> PciHeader { + PciHeader::new(self.cfg_addr) + } + + fn read(offset: usize) -> u32 { + unsafe { (offset as *const u32).read_volatile() } + } + fn write(offset: usize, value: u32) { + unsafe { (offset as *mut u32).write_volatile(value) } + } + + /// Get the contents of a BAR in a given slot. Empty bars will return `None`. + /// + /// ### Note + /// 64-bit memory BARs use two slots, so if one is decoded in e.g. slot #0, this method should not be called + /// for slot #1 + pub fn bar(&self, slot: u8) -> Option { + if slot >= Self::MAX_BARS { + return None; + } + + let offset = self.cfg_addr + 0x10 + (slot as usize) * 4; + let bar = Self::read(offset); + + /* + * If bit 0 is `0`, the BAR is in memory. If it's `1`, it's in I/O. + */ + if bar.get_bit(0) == false { + let prefetchable = bar.get_bit(3); + let address = bar.get_bits(4..32) << 4; + + match bar.get_bits(1..3) { + 0b00 => { + let size = unsafe { + Self::write(offset, 0xfffffff0); + let mut readback = unsafe { (offset as *const u32).read_volatile() }; + Self::write(offset, address); + + /* + * If the entire readback value is zero, the BAR is not implemented, so we return `None`. + */ + if readback == 0x0 { + return None; + } + + readback.set_bits(0..4, 0); + 1 << readback.trailing_zeros() + }; + Some(Bar::Memory32 { + address, + size, + prefetchable, + }) + } + + 0b10 => { + /* + * If the BAR is 64 bit-wide and this slot is the last, there is no second slot to read. + */ + if slot >= 5 { + return None; + } + + let address_upper = Self::read(offset + 4); + + let mut size = unsafe { + Self::write(offset, 0xfffffff0); + Self::write(offset + 4, 0xffffffff); + let mut readback_low = Self::read(offset); + let readback_high = Self::read(offset + 4); + Self::write(offset, address); + Self::write(offset + 4, address_upper); + + /* + * If the readback from the first slot is not 0, the size of the BAR is less than 4GiB. + */ + readback_low.set_bits(0..4, 0); + if readback_low != 0 { + (1 << readback_low.trailing_zeros()) as u64 + } else { + 1u64 << ((readback_high.trailing_zeros() + 32) as u64) + } + }; + + let address64 = { + let mut address = address as u64; + // TODO: do we need to mask off the lower bits on this? + address.set_bits(32..64, address_upper as u64); + address + }; + Some(Bar::Memory64 { + address: address64, + size, + prefetchable, + }) + } + // TODO: should we bother to return an error here? + _ => panic!("BAR Memory type is reserved!"), + } + } else { + Some(Bar::Io { + port: bar.get_bits(2..32) << 2, + }) + } + } + + pub fn write_bar64(&mut self, slot: u8, value: u64) { + unsafe { + let offset = self.cfg_addr + 0x10 + (slot as usize) * 4; + Self::write(offset, value.get_bits(0..32) as u32); + Self::write(offset + 4, value.get_bits(32..64) as u32); + } + } + + pub fn write_bar32(&mut self, slot: u8, value: u32) { + let offset = self.cfg_addr + 0x10 + (slot as usize) * 4; + unsafe { + Self::write(offset, value as u32); + } + } +} + +pub const MAX_BARS: usize = 6; + +#[derive(Clone, Copy, Debug)] +pub enum Bar { + Memory32 { + address: u32, + size: u32, + prefetchable: bool, + }, + Memory64 { + address: u64, + size: u64, + prefetchable: bool, + }, + Io { + port: u32, + }, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum BarWriteError { + NoSuchBar, + InvalidValue, +} + +pub struct ConfigSpace { + pub address: PciAddress, + pub cfg_addr: usize, + pub header: PciHeader, + pub kind: ConfigKind, +} + +pub enum ConfigKind { + Endpoint { inner: ConifgEndpoint }, + PciPciBridge { inner: ConifgPciPciBridge }, +} + diff --git a/crates/driver_usb/Cargo.lock b/crates/driver_usb/Cargo.lock new file mode 100644 index 0000000000..5d9cc838a5 --- /dev/null +++ b/crates/driver_usb/Cargo.lock @@ -0,0 +1,1000 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers 0.8.1", +] + +[[package]] +name = "accessor" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd8b2abd55bf1f9cffbf00fd594566c51a9d31402553284920c1309ca8351086" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "arm_gic" +version = "0.1.0" +dependencies = [ + "tock-registers 0.8.1", +] + +[[package]] +name = "arm_pl011" +version = "0.1.0" +dependencies = [ + "tock-registers 0.8.1", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axconfig" +version = "0.1.0" +dependencies = [ + "serde", + "toml_edit", +] + +[[package]] +name = "axhal" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", + "arm_gic", + "arm_pl011", + "axconfig", + "axlog", + "bitflags 2.4.2", + "cfg-if", + "crate_interface 0.1.1", + "dw_apb_uart", + "handler_table", + "kernel_guard", + "lazy_init", + "log", + "memory_addr", + "page_table_entry", + "percpu", + "ratio", + "raw-cpuid 11.0.1", + "riscv", + "sbi-rt", + "spinlock", + "static_assertions", + "tock-registers 0.8.1", + "x2apic", + "x86", + "x86_64", +] + +[[package]] +name = "axlog" +version = "0.1.0" +dependencies = [ + "cfg-if", + "crate_interface 0.1.1", + "log", + "spinlock", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.4.2", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.48", + "which", +] + +[[package]] +name = "bit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b645c5c09a7d4035949cfce1a915785aaad6f17800c35fda8a8c311c491f284" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "crate_interface" +version = "0.1.1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "crate_interface" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54b79db793871881b52a1eb5dc6fd869743122e34795f12db8e183dcb6a4f28" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "driver_common" +version = "0.1.0" + +[[package]] +name = "driver_pci" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", + "bit_field", + "log", + "pci_types", + "ratio", + "tock-registers 0.8.1", + "virtio-drivers", +] + +[[package]] +name = "driver_usb" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", + "axconfig", + "axhal", + "bit_field", + "driver_common", + "driver_pci", + "log", + "page_table", + "page_table_entry", + "spinlock", + "tock-registers 0.9.0", + "xhci", +] + +[[package]] +name = "dw_apb_uart" +version = "0.1.0" +dependencies = [ + "tock-registers 0.8.1", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "handler_table" +version = "0.1.0" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "impl_libusb" +version = "0.1.0" +dependencies = [ + "bindgen", +] + +[[package]] +name = "indexmap" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "kernel_guard" +version = "0.1.0" +dependencies = [ + "cfg-if", + "crate_interface 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_init" +version = "0.1.0" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memory_addr" +version = "0.1.0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "page_table" +version = "0.1.0" +dependencies = [ + "log", + "memory_addr", + "page_table_entry", +] + +[[package]] +name = "page_table_entry" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", + "bitflags 2.4.2", + "memory_addr", + "x86_64", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pci_types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831e5bebf010674bc2e8070b892948120d4c453c71f37387e1ffea5636620dbe" +dependencies = [ + "bit_field", + "bitflags 2.4.2", +] + +[[package]] +name = "percpu" +version = "0.1.0" +dependencies = [ + "cfg-if", + "percpu_macros", + "spin", + "x86", +] + +[[package]] +name = "percpu_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn 2.0.48", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ratio" +version = "0.1.0" + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "raw-cpuid" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +dependencies = [ + "bitflags 2.4.2", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "riscv" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa3145d2fae3778b1e31ec2e827b228bdc6abd9b74bb5705ba46dcb82069bc4f" +dependencies = [ + "bit_field", + "critical-section", + "embedded-hal", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "sbi-rt" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c113c53291db8ac141e01f43224ed488b8d6001ab66737b82e04695a43a42b7" +dependencies = [ + "sbi-spec", +] + +[[package]] +name = "sbi-spec" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4027cf9bb591a9fd0fc0e283be6165c5abe96cb73e9f0e24738c227f425377" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinlock" +version = "0.1.0" +dependencies = [ + "cfg-if", + "kernel_guard", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" + +[[package]] +name = "tock-registers" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "virtio-drivers" +version = "0.7.1" +source = "git+https://github.com/rcore-os/virtio-drivers.git?rev=4b60f5d#4b60f5d341a7211dfec7382062f965c5433c51c2" +dependencies = [ + "bitflags 2.4.2", + "log", + "zerocopy", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" +dependencies = [ + "memchr", +] + +[[package]] +name = "x2apic" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbcd582541cbb8ef1dfc24a3c849a64ff074b1b512af723ad90056558d424602" +dependencies = [ + "bit", + "bitflags 1.3.2", + "paste", + "raw-cpuid 10.7.0", + "x86_64", +] + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid 10.7.0", +] + +[[package]] +name = "x86_64" +version = "0.14.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b835097a84e4457323331ec5d6eb23d096066cbfb215d54096dcb4b2e85f500" +dependencies = [ + "bit_field", + "bitflags 2.4.2", + "rustversion", + "volatile", +] + +[[package]] +name = "xhci" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f3f0483969259f2adb6524054400d94ac352e59fa37da6c6ca3b9b3d83ff83" +dependencies = [ + "accessor", + "bit_field", + "num-derive", + "num-traits", + "paste", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] diff --git a/crates/driver_usb/Cargo.toml b/crates/driver_usb/Cargo.toml new file mode 100644 index 0000000000..f2dad5347a --- /dev/null +++ b/crates/driver_usb/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "driver_usb" +version = "0.1.0" +edition = "2021" +description = "Common traits and types for usb device drivers" +license = "GPL-3.0-or-later OR Apache-2.0" +homepage = "https://github.com/rcore-os/arceos" +repository = "https://github.com/rcore-os/arceos/tree/main/crates/driver_usb" +documentation = "https://rcore-os.github.io/arceos/driver_usb/index.html" + + +[features] +default = ["xhci","packed_drivers"] +packed_drivers=[] +xhci=[] + +[dependencies] +xhci = "0.9" +log="0.4" +memory_addr = {path= "../../crates/memory_addr"} +spinlock = { path = "../../crates/spinlock" } +tock-registers = "0.9.0" +bit_field = "0.10" +num-derive = "0.4.0" +num-traits = { version = "0.2.16", default-features = false } +byteorder = { version = "1.4.3", default-features = false } +const-enum = {git = "https://github.com/dbydd/const-enum-new.git"} +# hidreport = {path = "../../crates/hidreport"} + + + +# arceos +driver_common = { path = "../driver_common" } +driver_pci = { path = "../driver_pci" } +axhal = {path = "../../modules/axhal",features=["irq"]} +axtask = {path = "../../modules/axtask",features = ["multitask","sched_rr"]} +axconfig = {path = "../../modules/axconfig"} +axalloc = {path="../../modules/axalloc"} diff --git a/crates/driver_usb/guide/Pasted image 20240714095350.png b/crates/driver_usb/guide/Pasted image 20240714095350.png new file mode 100644 index 0000000000..cae730e6e5 Binary files /dev/null and b/crates/driver_usb/guide/Pasted image 20240714095350.png differ diff --git a/crates/driver_usb/guide/code_file_structure.log b/crates/driver_usb/guide/code_file_structure.log new file mode 100644 index 0000000000..30068c29c9 --- /dev/null +++ b/crates/driver_usb/guide/code_file_structure.log @@ -0,0 +1,26 @@ +. +├── Cargo.lock +├── Cargo.toml +├── guide +│   ├── code_file_structure.log +│   ├── code_structure.md +│   └── quickstart_usb.md +└── src + ├── addr.rs + ├── ax + │   └── mod.rs + ├── device_types.rs + ├── dma.rs + ├── err.rs + ├── host + │   ├── device.rs + │   ├── mod.rs + │   └── xhci + │   ├── context.rs + │   ├── event.rs + │   ├── mod.rs + │   ├── registers.rs + │   └── ring.rs + └── lib.rs + +6 directories, 18 files diff --git a/crates/driver_usb/guide/code_structure.md b/crates/driver_usb/guide/code_structure.md new file mode 100644 index 0000000000..28006da287 --- /dev/null +++ b/crates/driver_usb/guide/code_structure.md @@ -0,0 +1,210 @@ +# 代码结构导读 + +## 前情提要 + +在之前的代码结构导读中,我们介绍了位于分支"phytium_pi_port"上的代码。目前,随着 xhci 部分的结束,我们已经将代码重构并迁移到了"phytium_pi_dev"分支,最新的驱动架构能够应对更多复杂情况,但结构也发生了大的变化,因此,我们重新做一遍代码导读。 + +## 文件结构 + +```log +. +├── Cargo.lock +├── Cargo.toml +├── guide +│   ├── code_file_structure.log +│   ├── code_structure.md +│   └── quickstart_usb.md +└── src + ├── addr.rs + ├── ax + │   └── mod.rs + ├── device_types.rs + ├── dma.rs + ├── err.rs + ├── host + │   ├── device.rs + │   ├── mod.rs + │   └── xhci + │   ├── context.rs + │   ├── event.rs + │   ├── mod.rs + │   ├── registers.rs + │   └── ring.rs + └── lib.rs +6 directories, 18 files +``` + +## 入口 + +目前,我们暂时抛弃了原来的 cli 手动启动,而是将 usb 模块的引导做成了一个[app](../../../apps/usb/src/main.rs): + +```rust + +#[derive(Clone)] +struct OsDepImp; + +impl OsDep for OsDepImp { //我们优化了驱动的架构,将其重构为系统无关的库,因此我们需要引入对各个操作系统进行适配的抽象层,也就是说,我们将驱动需要操作系统做的事情抽象了出来,形成了这个trait:"OsDep" + type DMA = GlobalNoCacheAllocator; + + const PAGE_SIZE: usize = axalloc::PAGE_SIZE; + fn dma_alloc(&self) -> Self::DMA { //就目前来说,我们仅仅只需要操作系统负责分配出No Cache的内存区域(DMA)即可。 + axalloc::global_no_cache_allocator() + } +} + +#[cfg_attr(feature = "axstd", no_mangle)] +fn main() { + let phytium_cfg_id_0 = (0xffff_0000_31a0_8000, 48, 0); + + let config = USBHostConfig::new( + phytium_cfg_id_0.0, + phytium_cfg_id_0.1, + phytium_cfg_id_0.2, + OsDepImp {}, + ); + + let usb = USBHost::new::>(config).unwrap(); + + usb.poll(); +} +``` + +让我们看看[USBHostConfig](../src/host/mod.rs)里有什么: + +```rust +#[derive(Clone)] +pub struct USBHostConfig +where O: OsDep +{ + pub(crate) base_addr: VirtAddr, + pub(crate) irq_num: u32, //中断系统相关:中断号。 + pub(crate) irq_priority: u32, //中断系统相关:中断优先级。注:目前中断系统尚未适配 + pub(crate) os: O //集成了操作系统相关操作的trait对象 +} +``` + +接下来,是与我们曾经的代码逻辑相似的 USBHost(XHCI)初始化流程,也就是[USBHost::new](../src/host/xhci/mod.rs)方法,这部分所做事情与移植之前相差不大,请读者自行比对理解。 + +## 深入 + +让我们来看看最新的进展,在 USBHost 创建之后,就会被调用 poll 方法,这个方法的作用是进行设备的枚举: + +```rust + fn probe(&self) -> Result { + let mut port_id_list = Vec::new(); + { + let mut g = self.regs.lock(); + let regs = &mut g.regs; + let port_len = regs.port_register_set.len(); + for i in 0..port_len { + let portsc = ®s.port_register_set.read_volatile_at(i).portsc; + info!( + "{TAG} Port {}: Enabled: {}, Connected: {}, Speed {}, Power {}", + i, + portsc.port_enabled_disabled(), + portsc.current_connect_status(), + portsc.port_speed(), + portsc.port_power() + ); + + if !portsc.port_enabled_disabled() { + continue; + } + + port_id_list.push(i); //寻找所有连接上了设备的port + } + } + for port_id in port_id_list { + let slot = self.device_slot_assignment(port_id); //首先,是为设备分配slot + self.address_device(slot, port_id); //在这里,我们配置对应slot的上下文(context),并请求xhci为设备设置地址 + self.set_ep0_packet_size(slot); //通过控制传输,获取准确的endpoint 0传输数据包大小 + self.setup_fetch_all_dev_desc(slot); //在以上的配置完成后,获取设备的全部描述符。 + } + + self.dev_ctx + .lock() + .attached_set + .iter_mut() + .for_each(|dev| {}); //TODO: 为设备选择制定的配置,而后开始传输。目前我们先做一个HID设备(鼠标/键盘) + Ok(()) + } +``` + +## 任务分解 1-设备描述符 + +设备描述符是设备所包含的描述信息,在这里,我们一次性获取所有的描述符信息,并在需要的时候获取对应条目的描述符 + +设备描述符有许多种类,不同的种类描述了不同的信息,比如 device 就可能会包含设备的厂家/设备的类型等信息,[参考](../src/host/usb/descriptors/mod.rs): + +```rust +#[derive(ConstEnum, Copy, Clone, Debug)] +#[allow(non_camel_case_types)] +pub(crate) enum Type { + //USB 1.1: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + Device = 1, + Configuration = 2, + String = 3, + Interface = 4, + Endpoint = 5, + // USB 2.0: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + DeviceQualifier = 6, + OtherSpeedConfiguration = 7, + InterfacePower1 = 8, + Hid = 0x21, + HIDReport = 0x22, + HIDPhysical = 0x23, + // USB 3.0+: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + OTG = 0x09, + Debug = 0x0a, + InterfaceAssociation = 0x0b, + Bos = 0x0f, + DeviceCapability = 0x10, + SuperSpeedEndpointCompanion = 0x30, + SuperSpeedPlusIsochEndpointCompanion = 0x31, +} +``` + +这些类型,每一个都对应了不同的 Descriptor,每个 Descriptor 又有不同的数据结构,好在我们目前暂时不用全部实现,只实现需要的部分即可。我们所需要关心的代码位于这里, + +```rust +impl Descriptor { + pub(crate) fn from_slice(raw: &[u8]) -> Result { + assert_eq!(raw.len(), raw[0].into()); + match FromPrimitive::from_u8(raw[1]) { + Some(t) => { + let raw: *const [u8] = raw; + match t { + // SAFETY: This operation is safe because the length of `raw` is equivalent to the + // one of the descriptor. + //todo 任务1:我们所需要的就是在这里补充描述符的创建,在setup_fetch_all_dev_desc方法中,这个方法会被调用多次以反序列化设备传输过来的描述符 + Type::Device => Ok(Self::Device(unsafe { ptr::read(raw.cast()) })), + Type::Configuration => { + Ok(Self::Configuration(unsafe { ptr::read(raw.cast()) })) + } + Type::String => Ok(Self::Str), + Type::Interface => Ok(Self::Interface(unsafe { ptr::read(raw.cast()) })), + Type::Endpoint => Ok(Self::Endpoint(unsafe { ptr::read(raw.cast()) })), + Type::Hid => Ok(Self::Hid), + other => unimplemented!("please implement descriptor type:{:?}", other), + } + } + None => Err(Error::UnrecognizedType(raw[1])), + } + } +} +``` + +额外的参考资料: + +- [USB 中文网-关于设备描述符的部分](https://www.usbzh.com/article/detail-104.html) +- USB3.2 spec 文档:在资料附件中 + +## 任务分解 2:设备配置选择 + +在获取到了描述符后,我们要从设备提供的几种配置中选择一种来设置端点(endpoint),参考:[redox 的代码](https://github.com/redox-os/drivers/blob/master/xhcid/src/xhci/scheme.rs#L595) + +这部分在我们的代码中应当位于[根据设备描述符查找驱动](../src/host/xhci/xhci_device.rs)时 + +## 任务分解 3-HID 驱动编写-键盘 + +先写一个键盘驱动,参考 [redox 代码](https://github.com/redox-os/drivers/tree/master/usbhidd) diff --git a/crates/driver_usb/guide/quickstart_usb.md b/crates/driver_usb/guide/quickstart_usb.md new file mode 100644 index 0000000000..5b2577b972 --- /dev/null +++ b/crates/driver_usb/guide/quickstart_usb.md @@ -0,0 +1,62 @@ +# USB/XHCI驱动 前情提要&背景知识 +* 什么是xhci? +* 答: xhci是USB的控制器, USB1.0的控制器是UHCI/OHCI, 2.0是EHCI, EHCI不向下兼容1.0, 直到USB3.0的XHCI出现,统一了操作标准 +* 具体的来说,有没有参考资料? +* 答:有,之后整理好群里打包发 +* XHCI可以做什么? +* 答:分为两部分,首先XHCI控制器负责整个USB系统的数据与其他内存空间的交互,其次,XHCI控制器负责控制USB设备 + * 追问:控制和传输,有区别吗? + * 答:有,传输不改变设备的状态,具体来说,不管是USB HUB还是USB FUNCTION,其实都是状态机 + * 追问2: HUB/FUNCTION又是什么? + * 答:这么描述吧: + * 首先HUB/FUNCTION都是USB设备 + * HUB是可以管理设备的设备(比如扩展坞,值得一提的是其实整个USB设备树的根-称为ROOTHUB,其实也只不过是一个特殊的扩展坞而已) + * FUNCTION是实际上有功能的设备(例:起存储功能的U盘,起网卡功能的USB网卡...) + * 追问3:再说说状态机的事? + * 答:在Intel的XHCI文档中搜索state machine来了解各部分的状态 +* 好吧:那么USB系统是如何构成的? +* 答:宏观上是树状结构,逻辑上USB设备都是事件驱动的事件机器: + * 对于HUB,其内部有两种事件发送端,但是事件的接收端是统一的: + * 事件接收端:EventRing-其实是个消息队列,当EventRing接收到事件后会想办法通知操作系统-用中断,或者操作系统主动轮询这个队列以检查新到的事件 + * 内部事件发送端:CommandRing-负责发送改变HUB状态的/调用HUB硬件实现的功能的请求事件的地方 + * 设备事件发送端:TransferRing-负责发送与设备的EndPoint交互(控制/传输都通过这个ring进行)的事件的地方 + * 追问:Endpoint是什么? + * 答:是在物理上传输数据的部分,一个设备可以有很多个EndPoint,具体数量随USB协议版本而变化,EndPoint一般是单向的,Hub与设备的EndPoint建立通信后,这个逻辑概念上的数据传输路线就被叫做数据管道 + * 但是Endpoint0是特殊的,他必然存在,且是唯一同时可以双向通信的EndPoint,负责与HUB交换设备的"控制"事件,人们喜欢把Endpoint0的传输操作叫做"控制传输" + * 为什么要这么设计?因为更多的管道就是更多的带宽! + * 事件传输单元:TRB(Transfer Request Block)-每个TRB都由4位u32组成,且容纳这些数据的内存必须16位对齐,其中第四个u32的10-15位内保存的是TRB类型(即事件类型)的唯一标识符 + * 事实上,这三个Ring在数据结构上拥有相同的实现方式: + 其中RING_LENGTH随不同设备而改变,属于配置选项,同时,ring的最后一个单元总是要放一个LinkTrb以标明这里是ring的结尾,需要从头开始循环。 + ```rust + let ring = [[u32;4];RING_LENGTH]; + let enqueue_pointer:*const [u32;4]; + let dequeue_pointer:*const [u32;4]; + let cycle_bit:bool; + ``` + * 追问:循环? + * 答:是的,ring表示这玩意是个用数组实现的循环队列,当然,也有队头(dequeue)和队尾(enqueue),这两个指针中间的TRB就是正在处理的事件,同时,为了硬件纠错,还引入了cycle_bit,正在处理的事件的cycle_bit必须与环的cycle_bit一致才被视为有效事件,否则当成很久之前就已经处理过了,会直接跳过/报错。 + * TRB大体可分为三类:Control/Transfer/Event TRB,名字就已经表明了他们分别在什么地方出现 + * 对于设备,我们其实并不关心,这部分是制造厂商要负责的事情,我们只在乎数据/控制的传输,把它当成一个塞进去命令就会给反馈的黑盒即可 + * 具体说说! + * 答:好吧,与设备的通信如同TCP协议一样,有着"三次握手"的格式 + * 首先,发送Setup TRB---这表示一次事件的开始,以及表明了接下来要传输什么数据,setup TRB的类型是有限的,已经在xhci文档/usb文档里列了出来,请自行查阅 + * 然后,发送Data TRB---这部分是可选的,有些TRB并不需要发送数据,比如GetDescriptor TRB,这个Setup TRB中就已经包含了完整的请求信息(请求的数据条目的编号) + * 最后:发送Status TRB--标准着这次事件的结束,其中包含了一些额外的控制信息,与中断系统/连续传输有关 + * 最后的最后:敲响门铃寄存器来通知设备接受事件,并在EventRing/本设备的doorbell中断上等待设备回报回来的事件。 + * doorbell是什么? + * 硬件上的实现,这玩意是一个数组,主要用处就是通知被分配在特定slot上的设备有事件被发起,请接收并处理 + * 其中doorbell 0比较特殊,它被称为"默认地址"-实际上是控制器自己,当一个设备刚插上HUB时,它会被分配到默认地址上,(因为这时设备还没有被分配地址),这也就意味着xhci一次性只能处理一个设备插进来的情况,如果在极短的时间插进来了多个设备,那么其他设备就得排队等待 + * 同时这也意味着,每个doorbell 都对应 一个分配出去的slot id,具体的请看xhci 文档 + * 那么什么是Slot? + * 有这么两个概念: + * port-HUB物理上有多少个usb口,每个port都有一个寄存器,这些寄存器是连续分配的,可以当初一个数组。 + * slot-hub一共能管理多少设备(包括下游设备,比如hub接hub),每个设备都有一个slot id,这样就抽象掉了port号的概念。 + * 我还是不明白,控制器怎么知道如何管理这些设备,具体来说,如何进行控制? + * 答:通过dcbaa/, Device Context Base Address Array + * Device Context,指的是我们为设备分配的内存区域,是用于控制设备的Endpoint+Slot的区域。 + * dcbaa,是我们分配的一个数组,其上包含了各个Device Context的地址(指针) + * dcbaap,是xhci的一个寄存器,其值由我们配置为指向dcbaa的地址,xhci正是通过这个寄存器来知道/控制设备的配置状态的。 +* 好吧,能将整个流程完整的描述一遍吗?我是指程序上? +* 答:从[这里](../src/lib.rs)的try_init函数入手,这是整个驱动的入口,同时辅以xhci文档的第四章来确定你当前看的是哪一步。同时也可以参考[飞腾派的官方嵌入式sdk](https:/gitee.com/phytium_embedded/phytium-standalone-sdk) +* 行!那么目前还需要干什么? +* 参考[问题文件夹](../question),其中是与飞腾官方所沟通的一些问题,也是我们驱动目前需要解决的问题,如果有新问题,也请加进去。 \ No newline at end of file diff --git "a/crates/driver_usb/guide/\345\237\272\344\272\216\351\243\236\350\205\276\346\264\276\347\232\204Arceos\347\247\273\346\244\215\344\270\216\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/crates/driver_usb/guide/\345\237\272\344\272\216\351\243\236\350\205\276\346\264\276\347\232\204Arceos\347\247\273\346\244\215\344\270\216\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221.md" new file mode 100644 index 0000000000..ffcd61f9a5 --- /dev/null +++ "b/crates/driver_usb/guide/\345\237\272\344\272\216\351\243\236\350\205\276\346\264\276\347\232\204Arceos\347\247\273\346\244\215\344\270\216\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221.md" @@ -0,0 +1,159 @@ + +## 1. 环境和工具准备 + + + +## 2. 系统移植 + +Arceos在前期移植系统中的情况是启动之后什么都没输出死机,我们为了找到死机原因所在添加了`put_debug2`函数(未开启分页后输出字符)和`put_debug_paged2`函数(开启分页后输出字符)与飞腾派默认的UART1串口通信输出字符,在开机启动过程中的每个函数之间都插入这个函数,通过观察串口中输出的字符个数来判断系统启动过程中是哪个函数导致了死机。 + +```rust +#[cfg(all(target_arch = "aarch64", platform_family = "aarch64-phytium-pi"))] +#[no_mangle] +unsafe extern "C" fn put_debug2() { + let state = (0x2800D018 as usize) as *mut u8; + let put = (0x2800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; +} + +#[cfg(all(target_arch = "aarch64", platform_family = "aarch64-phytium-pi"))] +#[no_mangle] +unsafe extern "C" fn put_debug_paged2() { + let state = (0xFFFF00002800D018 as usize) as *mut u8; + let put = (0xFFFF00002800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; +} +``` + +我们定位到了是`axprint!`宏导致的死机原因,随后正确的修改了串口配置。 + +下面是修改过的配置清单 +### platforms/aarch64-phytium-pi.toml +``` +kernel-base-paddr = "0x90100000" +kernel-base-vaddr = "0xffff_0000_9010_0000" +uart-paddr = "0x2800_D000" +uart-irq = "24" +``` +### tools/phytium-pi/phytium-pi.its +``` +load = <0x90100000>; +entry = <0x90100000>; +``` + + +## 3.串口驱动开发应用 + +根据手册定义需要的寄存器(默认波特率是115200,无需定义处理波特率相关寄存器) + +![[Pasted image 20240714095350.png]] + +```rust +register_structs! { + /// Pl011 registers. + Pl011UartRegs { + /// Data Register. + (0x00 => dr: ReadWrite), + (0x04 => _reserved0), + /// Flag Register. + (0x18 => fr: ReadOnly), + (0x1c => _reserved1), + /// Control register. + (0x30 => cr: ReadWrite), + /// Interrupt FIFO Level Select Register. + (0x34 => ifls: ReadWrite), + /// Interrupt Mask Set Clear Register. + (0x38 => imsc: ReadWrite), + /// Raw Interrupt Status Register. + (0x3c => ris: ReadOnly), + /// Masked Interrupt Status Register. + (0x40 => mis: ReadOnly), + /// Interrupt Clear Register. + (0x44 => icr: WriteOnly), + (0x48 => @END), + } +} +``` + +实现初始化,读写字符,响应中断 + +```rust +/// The Pl011 Uart +/// +/// The Pl011 Uart provides a programing interface for: +/// 1. Construct a new Pl011 UART instance +/// 2. Initialize the Pl011 UART +/// 3. Read a char from the UART +/// 4. Write a char to the UART +/// 5. Handle a UART IRQ +pub struct Pl011Uart { + base: NonNull, +} + +unsafe impl Send for Pl011Uart {} +unsafe impl Sync for Pl011Uart {} + +impl Pl011Uart { + /// Constrcut a new Pl011 UART instance from the base address. + pub const fn new(base: *mut u8) -> Self { + Self { + base: NonNull::new(base).unwrap().cast(), + } + } + + const fn regs(&self) -> &Pl011UartRegs { + unsafe { self.base.as_ref() } + } + + /// Initializes the Pl011 UART. + /// + /// It clears all irqs, sets fifo trigger level, enables rx interrupt, enables receives + pub fn init(&mut self) { + // clear all irqs + self.regs().icr.set(0x7ff); + + // set fifo trigger level + self.regs().ifls.set(0); // 1/8 rxfifo, 1/8 txfifo. + + // enable rx interrupt + self.regs().imsc.set(1 << 4); // rxim + + // enable receive + self.regs().cr.set((1 << 0) | (1 << 8) | (1 << 9)); // tx enable, rx enable, uart enable + } + + /// Output a char c to data register + pub fn putchar(&mut self, c: u8) { + while self.regs().fr.get() & (1 << 5) != 0 {} + self.regs().dr.set(c as u32); + } + + /// Return a byte if pl011 has received, or it will return `None`. + pub fn getchar(&mut self) -> Option { + if self.regs().fr.get() & (1 << 4) == 0 { + Some(self.regs().dr.get() as u8) + } else { + None + } + } + + /// Return true if pl011 has received an interrupt + pub fn is_receive_interrupt(&self) -> bool { + let pending = self.regs().mis.get(); + pending & (1 << 4) != 0 + } + + /// Clear all interrupts + pub fn ack_interrupts(&mut self) { + self.regs().icr.set(0x7ff); + } +} + +``` +## 4.USB驱动应用开发(高级拓展功能) + + + + diff --git a/crates/driver_usb/src/abstractions/dma.rs b/crates/driver_usb/src/abstractions/dma.rs new file mode 100644 index 0000000000..dcd9f514c0 --- /dev/null +++ b/crates/driver_usb/src/abstractions/dma.rs @@ -0,0 +1,215 @@ +use core::{ + alloc::{AllocError, Allocator, Layout}, + fmt::Debug, + marker::PhantomData, + mem::size_of, + ops::{Deref, DerefMut}, + ptr::{slice_from_raw_parts, slice_from_raw_parts_mut, NonNull}, +}; + +use alloc::vec::Vec; +use axalloc::global_no_cache_allocator; +use log::debug; + +pub struct DMA +where + T: ?Sized, + A: Allocator, +{ + layout: Layout, + data: NonNull<[u8]>, + allocator: A, + __marker: PhantomData, +} + +unsafe impl Send for DMA +where + T: ?Sized, + A: Allocator, +{ +} + +impl DMA +where + T: Sized, + A: Allocator, +{ + /// 从 `value` `align` 和 `allocator` 创建 DMA, + /// 若不符合以下条件则 Panic `LayoutError`: + /// + /// * `align` 不能为 0, + /// + /// * `align` 必须是2的幂次方。 + pub fn new(value: T, align: usize, allocator: A) -> Self { + //计算所需内存大小 + let buff_size = size_of::(); + // 根据元素数量和对其要求创建内存布局 + let layout = Layout::from_size_align(buff_size, align).unwrap(); + // 使用分配器分配内存 + let mut data = allocator.allocate(layout).unwrap(); + let mut ptr = data.cast(); + unsafe { + ptr.write(value); + }; + Self { + layout, + data, + allocator, + __marker: PhantomData::default(), + } + } + + pub fn new_singleton_page4k(value: T, allocator: A) -> Self { + Self::new(value, 4096, allocator) + } + + pub fn fill_zero(mut self) -> Self { + unsafe { self.data.as_mut().iter_mut().for_each(|u| *u = 0u8) } + self + } +} + +impl DMA +where + T: ?Sized, + A: Allocator, +{ + /// 返回 [DMA] 地址 + pub fn addr(&self) -> usize { + self.data.addr().into() + } + + pub fn length_for_bytes(&self) -> usize { + self.layout.size() + } + + pub fn addr_len_tuple(&self) -> (usize, usize) { + (self.addr(), self.length_for_bytes()) + } +} + +impl DMA<[T], A> +where + T: Sized, + A: Allocator, +{ + pub fn zeroed(count: usize, align: usize, allocator: A) -> Self { + let t_size = size_of::(); + let size = count * t_size; + + // 根据元素数量和对其要求创建内存布局 + let layout = Layout::from_size_align(size, align).unwrap(); + // 使用分配器分配内存 + let mut data = allocator.allocate(layout).unwrap(); + + unsafe { + for mut one in data.as_mut() { + *one = 0; + } + } + + unsafe { + Self { + layout, + data, + allocator, + __marker: PhantomData::default(), + } + } + } + + pub fn new_vec(init: T, count: usize, align: usize, allocator: A) -> Self { + let t_size = size_of::(); + let size = count * t_size; + + // 根据元素数量和对其要求创建内存布局 + let layout = Layout::from_size_align(size, align).unwrap(); + // 使用分配器分配内存 + let mut data = allocator.allocate(layout).unwrap(); + // debug!("allocated data:{:?}", data); + + unsafe { + for i in 0..count { + let data = &mut data.as_mut()[i * t_size..(i + 1) * t_size]; + let t_ptr = &init as *const T as *const u8; + let t_data = &*slice_from_raw_parts(t_ptr, t_size); + data.copy_from_slice(t_data); + } + } + + unsafe { + Self { + layout, + data, + allocator, + __marker: PhantomData::default(), + } + } + } +} + +impl Deref for DMA<[T], A> +where + A: Allocator, +{ + type Target = [T]; + + fn deref(&self) -> &Self::Target { + unsafe { + let len = self.data.len() / size_of::(); + let ptr = self.data.cast::(); + &*slice_from_raw_parts(ptr.as_ptr(), len) + } + } +} + +impl DerefMut for DMA<[T], A> +where + A: Allocator, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + let len = self.data.len() / size_of::(); + let mut ptr = self.data.cast::().as_ptr(); + &mut *slice_from_raw_parts_mut(ptr, len) + } + } +} + +impl Deref for DMA +where + A: Allocator, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { + let ptr = self.data.cast::(); + ptr.as_ref() + } + } +} + +impl DerefMut for DMA +where + A: Allocator, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + let mut ptr = self.data.cast::(); + ptr.as_mut() + } + } +} +impl Drop for DMA +where + T: ?Sized, + A: Allocator, +{ + fn drop(&mut self) { + unsafe { + let ptr = self.data.cast::(); + self.allocator.deallocate(ptr, self.layout); + } + } +} diff --git a/crates/driver_usb/src/abstractions/mod.rs b/crates/driver_usb/src/abstractions/mod.rs new file mode 100644 index 0000000000..8a20979389 --- /dev/null +++ b/crates/driver_usb/src/abstractions/mod.rs @@ -0,0 +1,26 @@ +pub mod dma; + +use core::{alloc::Allocator, fmt::Debug}; + +// pub trait PlatformAbstractions: Clone + Send + Sync + Sized { +// type VirtAddr; +// const PAGE_SIZE: usize; +// type DMA: Allocator + Send + Sync + Clone; +// fn dma_alloc(&self) -> Self::DMA; +// fn force_sync_cache(); +// } + +pub trait PlatformAbstractions: OSAbstractions + HALAbstractions {} + +impl PlatformAbstractions for A where A: OSAbstractions + HALAbstractions {} + +pub trait OSAbstractions: Clone + Send + Sync + Sized { + type VirtAddr: From + Into + Clone + Send + Sync; + type DMA: Allocator + Send + Sync + Clone; + const PAGE_SIZE: usize; + fn dma_alloc(&self) -> Self::DMA; + // fn interrupt_handler();//ADD Interrupt feature? +} +pub trait HALAbstractions: Clone + Send + Sync + Sized { + fn force_sync_cache(); +} diff --git a/crates/driver_usb/src/err.rs b/crates/driver_usb/src/err.rs new file mode 100644 index 0000000000..5dc38b61b9 --- /dev/null +++ b/crates/driver_usb/src/err.rs @@ -0,0 +1,30 @@ +use alloc::string::String; +use core::fmt::{write, Display}; +use xhci::ring::trb::event::CompletionCode; + +#[derive(Debug)] +pub enum Error { + Unknown(String), + Param(String), + CMD(CompletionCode), + Pip, + TimeOut, + DontDoThatOnControlPipe, +} + +impl Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Error::Unknown(msg) => write!(f, "unknown usb err: {}", msg), + Error::Param(msg) => write!(f, "param err: {}", msg), + Error::TimeOut => write!(f, "timeout"), + Error::CMD(cmd) => write!(f, "cmd fail: {:#?}", cmd), + Error::Pip => write!(f, "piped"), + Error::DontDoThatOnControlPipe => { + write!(f, "don't do that on controller pipe! illegal operation!") + } + } + } +} + +pub type Result = core::result::Result; diff --git a/crates/driver_usb/src/glue/driver_independent_device_instance.rs b/crates/driver_usb/src/glue/driver_independent_device_instance.rs new file mode 100644 index 0000000000..ea6e6327e7 --- /dev/null +++ b/crates/driver_usb/src/glue/driver_independent_device_instance.rs @@ -0,0 +1,39 @@ +use core::hash::Hash; + +use alloc::sync::Arc; +use spinlock::SpinNoIrq; + +use crate::{ + abstractions::PlatformAbstractions, + host::data_structures::{host_controllers::ControllerArc, MightBeInited}, + usb::descriptors::topological_desc::TopologicalUSBDescriptorRoot, +}; + +#[derive(Clone)] +pub struct DriverIndependentDeviceInstance +where + O: PlatformAbstractions, +{ + pub slotid: usize, + pub configuration_val: usize, + pub interface_val: usize, + pub current_alternative_interface_value: usize, + pub descriptors: Arc>, + pub controller: ControllerArc, +} + +impl DriverIndependentDeviceInstance +where + O: PlatformAbstractions, +{ + pub fn new(slotid: usize, controller: ControllerArc) -> Self { + Self { + slotid: slotid, + descriptors: Arc::new(MightBeInited::default()), + controller: controller, + configuration_val: 1, + interface_val: 0, + current_alternative_interface_value: 0, + } + } +} diff --git a/crates/driver_usb/src/glue/glue_usb_host.rs b/crates/driver_usb/src/glue/glue_usb_host.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/driver_usb/src/glue/glue_usb_host.rs @@ -0,0 +1 @@ + diff --git a/crates/driver_usb/src/glue/mod.rs b/crates/driver_usb/src/glue/mod.rs new file mode 100644 index 0000000000..88b2d529e8 --- /dev/null +++ b/crates/driver_usb/src/glue/mod.rs @@ -0,0 +1,3 @@ +pub mod driver_independent_device_instance; +pub mod glue_usb_host; +pub mod ucb; diff --git a/crates/driver_usb/src/glue/ucb.rs b/crates/driver_usb/src/glue/ucb.rs new file mode 100644 index 0000000000..6117b75055 --- /dev/null +++ b/crates/driver_usb/src/glue/ucb.rs @@ -0,0 +1,40 @@ +use core::marker::PhantomData; + +use xhci::ring::trb::event::CompletionCode; + +use crate::abstractions::PlatformAbstractions; +pub struct UCB +where + O: PlatformAbstractions, +{ + //UCB A.K.A Usb Complete Block + pub code: CompleteCode, + _phantom_data: PhantomData, +} + +impl UCB +where + O: PlatformAbstractions, +{ + pub fn new(code: CompleteCode) -> Self { + Self { + code, + _phantom_data: PhantomData, + } + } +} + +#[derive(Debug)] +pub enum CompleteCode { + Event(TransferEventCompleteCode), + Debug, +} + +#[derive(Debug)] +pub enum TransferEventCompleteCode { + Success, + Halt, + Stall, + Unknown(u8), + IsochComplete, +} diff --git a/crates/driver_usb/src/host/data_structures/host_controllers/mod.rs b/crates/driver_usb/src/host/data_structures/host_controllers/mod.rs new file mode 100644 index 0000000000..637836b47a --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/host_controllers/mod.rs @@ -0,0 +1,74 @@ +pub mod xhci; +use core::sync::atomic::{fence, Ordering}; + +use ::xhci::{ + context::{EndpointType, Input}, + ring::trb::{command, event}, +}; +use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use log::trace; +use spinlock::SpinNoIrq; + +use crate::{ + abstractions::{dma::DMA, OSAbstractions, PlatformAbstractions}, + err::Result, + glue::{driver_independent_device_instance::DriverIndependentDeviceInstance, ucb::UCB}, + usb::{ + operation::{Configuration, Debugop, ExtraStep}, + trasnfer::{bulk::BulkTransfer, control::ControlTransfer, interrupt::InterruptTransfer, isoch::IsochTransfer}, + }, + USBSystemConfig, +}; + +pub trait Controller: Send +where + O: PlatformAbstractions, +{ + fn new(config: Arc>>) -> Self + where + Self: Sized; + + fn init(&mut self); + fn probe(&mut self) -> Vec; + fn control_transfer( + &mut self, + dev_slot_id: usize, + urb_req: ControlTransfer, + ) -> crate::err::Result>; + + fn interrupt_transfer( + &mut self, + dev_slot_id: usize, + urb_req: InterruptTransfer, + ) -> crate::err::Result>; + + fn bulk_transfer( + &mut self, + dev_slot_id: usize, + urb_req: BulkTransfer, + ) -> crate::err::Result>; + + fn isoch_transfer( + &mut self, + dev_slot_id: usize, + urb_req: IsochTransfer, + ) -> crate::err::Result>; + + fn configure_device( + &mut self, + dev_slot_id: usize, + urb_req: Configuration, + dev: Option<&mut DriverIndependentDeviceInstance>, + ) -> crate::err::Result>; + + fn extra_step(&mut self, dev_slot_id: usize, urb_req: ExtraStep) -> crate::err::Result>; + + fn device_slot_assignment(&mut self) -> usize; + fn address_device(&mut self, slot_id: usize, port_id: usize); + fn control_fetch_control_point_packet_size(&mut self, slot_id: usize) -> u8; + fn set_ep0_packet_size(&mut self, dev_slot_id: usize, max_packet_size: u16); + + fn debug_op(&mut self, dev_slot_id: usize, debug_op: Debugop) -> crate::err::Result>; +} + +pub(crate) type ControllerArc = Arc>>>; diff --git a/crates/driver_usb/src/host/data_structures/host_controllers/xhci/context.rs b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/context.rs new file mode 100644 index 0000000000..ca9ff67bba --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/context.rs @@ -0,0 +1,144 @@ +use crate::abstractions::dma::DMA; +use crate::abstractions::{OSAbstractions, PlatformAbstractions}; +use crate::host::data_structures::host_controllers::xhci::ring::Ring; +use crate::host::data_structures::host_controllers::ControllerArc; +use crate::{err::*, USBSystemConfig}; +use alloc::alloc::Allocator; +use alloc::collections::{BTreeMap, BTreeSet}; +use alloc::sync::Arc; +use alloc::{boxed::Box, vec::Vec}; +use alloc::{format, vec}; +use core::borrow::BorrowMut; +use core::num; +use log::debug; +use spinlock::SpinNoIrq; +use xhci::context::Input64Byte; +pub use xhci::context::{Device, Device64Byte, DeviceHandler}; +const NUM_EPS: usize = 32; + +pub struct DeviceContextList +//SHOULD We Rearrange these code,and shatter these array into single device? +where + O: PlatformAbstractions, +{ + config: Arc>>, + pub dcbaa: DMA<[u64; 256], O::DMA>, + pub device_out_context_list: Vec>, + pub device_input_context_list: Vec>, + pub transfer_rings: Vec>>, +} + +impl DeviceContextList +where + O: PlatformAbstractions, +{ + pub fn new(max_slots: u8, config: Arc>>) -> Self { + let os = config.lock().os.clone(); + let a = os.dma_alloc(); + + let mut dcbaa = DMA::new([0u64; 256], 4096, a.clone()); + let mut out_context_list = Vec::with_capacity(max_slots as _); + let mut in_context_list = Vec::with_capacity(max_slots as _); + for i in 0..max_slots as usize { + let out_context = DMA::new(Device::new_64byte(), 4096, a.clone()).fill_zero(); + dcbaa[i] = out_context.addr() as u64; + out_context_list.push(out_context); + in_context_list.push(DMA::new(Input64Byte::new_64byte(), 4096, a.clone()).fill_zero()); + } + let mut transfer_rings = Vec::with_capacity(max_slots as _); + for _ in 0..transfer_rings.capacity() { + transfer_rings.push(Vec::new()); + } + + Self { + dcbaa, + device_out_context_list: out_context_list, + device_input_context_list: in_context_list, + transfer_rings, + config: config.clone(), + } + } + + pub fn dcbaap(&self) -> usize { + self.dcbaa.as_ptr() as _ + } + + pub fn new_slot( + &mut self, + slot: usize, + hub: usize, + port: usize, + num_ep: usize, // cannot lesser than 0, and consider about alignment, use usize + ) { + if slot > self.device_out_context_list.len() { + panic!("slot {} > max {}", slot, self.device_out_context_list.len()) + } + + let os = self.config.lock().os.clone(); + + let trs = (0..num_ep) + .into_iter() + .map(|i| Ring::new(os.clone(), 32, true).unwrap()) + .collect(); + + self.transfer_rings[slot] = trs; + } +} + +use tock_registers::interfaces::Writeable; +use tock_registers::register_structs; +use tock_registers::registers::{ReadOnly, ReadWrite, WriteOnly}; + +register_structs! { + ScratchpadBufferEntry{ + (0x000 => value_low: ReadWrite), + (0x004 => value_high: ReadWrite), + (0x008 => @END), + } +} + +impl ScratchpadBufferEntry { + pub fn set_addr(&mut self, addr: u64) { + self.value_low.set(addr as u32); + self.value_high.set((addr >> 32) as u32); + } +} + +pub struct ScratchpadBufferArray +where + O: OSAbstractions, +{ + pub entries: DMA<[ScratchpadBufferEntry], O::DMA>, + pub pages: Vec>, +} + +unsafe impl Sync for ScratchpadBufferArray {} + +impl ScratchpadBufferArray +where + O: OSAbstractions, +{ + pub fn new(entries: u32, os: O) -> Self { + let page_size = O::PAGE_SIZE; + let align = 64; + + let mut entries: DMA<[ScratchpadBufferEntry], O::DMA> = + DMA::zeroed(entries as usize, align, os.dma_alloc()); + + let pages = entries + .iter_mut() + .map(|entry| { + let dma = DMA::zeroed(page_size, align, os.dma_alloc()); + + assert_eq!(dma.addr() % page_size, 0); + entry.set_addr(dma.addr() as u64); + dma + }) + .collect(); + + Self { entries, pages } + } + pub fn register(&self) -> usize { + self.entries.addr() + } +} diff --git a/crates/driver_usb/src/host/data_structures/host_controllers/xhci/event_ring.rs b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/event_ring.rs new file mode 100644 index 0000000000..cfc7f1b11c --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/event_ring.rs @@ -0,0 +1,88 @@ +use core::sync::atomic::{fence, Ordering}; + +pub use super::ring::{Ring, TrbData}; +use crate::abstractions::dma::DMA; +use crate::abstractions::OSAbstractions; +use crate::err::*; +use log::debug; +use tock_registers::interfaces::Writeable; +use tock_registers::register_structs; +use tock_registers::registers::{ReadOnly, ReadWrite, WriteOnly}; +use xhci::extended_capabilities::hci_extended_power_management::Data; +use xhci::ring::trb::event::{CompletionCode, TransferEvent}; +use xhci::ring::trb::{self, event::Allowed}; + +register_structs! { + EventRingSte { + (0x000 => addr_low: ReadWrite), + (0x004 => addr_high: ReadWrite), + (0x008 => size: ReadWrite), + (0x00A => _reserved), + (0x010 => @END), + } +} + +pub struct EventRing +where + O: OSAbstractions, +{ + pub ring: Ring, + pub ste: DMA<[EventRingSte], O::DMA>, +} + +impl EventRing +where + O: OSAbstractions, +{ + pub fn new(os: O) -> Result { + let a = os.dma_alloc(); + let mut ring = EventRing { + ste: DMA::zeroed(1, 64, a), + ring: Ring::new(os, 256, false)?, + }; + ring.ring.cycle = true; + ring.ste[0].addr_low.set(ring.ring.register() as u32); + ring.ste[0] + .addr_high + .set((ring.ring.register() as u64 >> 32) as u32); + ring.ste[0].size.set(ring.ring.trbs.len() as u16); + + Ok(ring) + } + + /// 完成一次循环返回 true + pub fn next(&mut self) -> Option<(Allowed, bool)> { + let (data, flag) = self.ring.current_data(); + let data = unsafe { + let mut out = [0u32; 4]; + for i in 0..out.len() { + out[i] = data.as_ptr().offset(i as _).read_volatile(); + } + out + }; + + let mut allowed = Allowed::try_from(data).ok()?; + + if flag != allowed.cycle_bit() { + return None; + } + if let Allowed::TransferEvent(c) = allowed + && let Ok(CompletionCode::Invalid) = c.completion_code() + { + return None; + } + + fence(Ordering::SeqCst); + + let cycle = self.ring.inc_deque(); + Some((allowed, cycle)) + } + + pub fn erdp(&self) -> u64 { + self.ring.register() & 0xFFFF_FFFF_FFFF_FFF0 + } + pub fn erstba(&self) -> u64 { + let ptr = &self.ste[0]; + ptr as *const EventRingSte as usize as u64 + } +} diff --git a/crates/driver_usb/src/host/data_structures/host_controllers/xhci/mod.rs b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/mod.rs new file mode 100644 index 0000000000..bbb583d40a --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/mod.rs @@ -0,0 +1,1380 @@ +use alloc::{borrow::ToOwned, boxed::Box, sync::Arc, vec, vec::Vec}; +use axhal::time; +use context::{DeviceContextList, ScratchpadBufferArray}; +use core::{ + mem::{self, MaybeUninit}, + num::NonZeroUsize, + ops::DerefMut, + sync::atomic::{fence, Ordering}, +}; +use event_ring::EventRing; +use log::{debug, error, info, trace, warn}; +use ring::Ring; +use spinlock::SpinNoIrq; +use xhci::{ + accessor::Mapper, + context::{DeviceHandler, EndpointState, EndpointType, Input, InputHandler, SlotHandler}, + extended_capabilities::XhciSupportedProtocol, + ring::trb::{ + command::{self, ResetEndpoint}, + event::{self, CommandCompletion, CompletionCode, HostController}, + transfer::{self, Direction, Isoch, Normal, TransferType}, + }, + ExtendedCapability, +}; + +use crate::{ + abstractions::{dma::DMA, PlatformAbstractions}, + err::Error, + glue::{ + driver_independent_device_instance::DriverIndependentDeviceInstance, + ucb::{CompleteCode, TransferEventCompleteCode, UCB}, + }, + host::data_structures::MightBeInited, + usb::{ + descriptors::{ + desc_configuration, + topological_desc::{ + TopologicalUSBDescriptorConfiguration, TopologicalUSBDescriptorEndpoint, + TopologicalUSBDescriptorFunction, + }, + USBStandardDescriptorTypes, + }, + operation::{Configuration, Debugop, ExtraStep}, + trasnfer::{ + self, + control::{ + bRequest, bmRequestType, ControlTransfer, DataTransferType, Recipient, + StandardbRequest, + }, + }, + urb, + }, + USBSystemConfig, +}; + +use super::Controller; + +mod context; +mod event_ring; +mod ring; + +pub type RegistersBase = xhci::Registers; +pub type RegistersExtList = xhci::extended_capabilities::List; +pub type SupportedProtocol = XhciSupportedProtocol; + +const TAG: &str = "[XHCI]"; + +#[derive(Clone)] +pub struct MemMapper; +impl Mapper for MemMapper { + unsafe fn map(&mut self, phys_start: usize, bytes: usize) -> NonZeroUsize { + return NonZeroUsize::new_unchecked(phys_start); + } + fn unmap(&mut self, virt_start: usize, bytes: usize) {} +} +pub struct XHCI +where + O: PlatformAbstractions, +{ + config: Arc>>, + pub regs: RegistersBase, + pub ext_list: Option, + max_slots: u8, + max_ports: u8, + max_irqs: u16, + scratchpad_buf_arr: Option>, + cmd: Ring, + event: EventRing, + pub dev_ctx: DeviceContextList, +} + +impl XHCI +where + O: PlatformAbstractions, +{ + pub fn supported_protocol(&mut self, port: usize) -> Option { + debug!("[XHCI] Find port {} protocol", port); + + if let Some(ext_list) = &mut self.ext_list { + ext_list + .into_iter() + .filter_map(|one| { + if let Ok(ExtendedCapability::XhciSupportedProtocol(protcol)) = one { + return Some(protcol); + } + None + }) + .find(|p| { + let head = p.header.read_volatile(); + let port_range = head.compatible_port_offset() as usize + ..head.compatible_port_count() as usize; + port_range.contains(&port) + }) + } else { + None + } + } + + fn chip_hardware_reset(&mut self) -> &mut Self { + debug!("{TAG} Reset begin"); + debug!("{TAG} Stop"); + + self.regs.operational.usbcmd.update_volatile(|c| { + c.clear_run_stop(); + }); + debug!("{TAG} Until halt"); + while !self.regs.operational.usbsts.read_volatile().hc_halted() {} + debug!("{TAG} Halted"); + + let mut o = &mut self.regs.operational; + // debug!("xhci stat: {:?}", o.usbsts.read_volatile()); + + debug!("{TAG} Wait for ready..."); + while o.usbsts.read_volatile().controller_not_ready() {} + debug!("{TAG} Ready"); + + o.usbcmd.update_volatile(|f| { + f.set_host_controller_reset(); + }); + + while o.usbcmd.read_volatile().host_controller_reset() {} + + debug!("{TAG} Reset HC"); + + while self + .regs + .operational + .usbcmd + .read_volatile() + .host_controller_reset() + || self + .regs + .operational + .usbsts + .read_volatile() + .controller_not_ready() + {} + + info!("{TAG} XCHI reset ok"); + self + } + + fn set_max_device_slots(&mut self) -> &mut Self { + let max_slots = self.max_slots; + debug!("{TAG} Setting enabled slots to {}.", max_slots); + self.regs.operational.config.update_volatile(|r| { + r.set_max_device_slots_enabled(max_slots); + }); + self + } + + fn set_dcbaap(&mut self) -> &mut Self { + let dcbaap = self.dev_ctx.dcbaap(); + debug!("{TAG} Writing DCBAAP: {:X}", dcbaap); + self.regs.operational.dcbaap.update_volatile(|r| { + r.set(dcbaap as u64); + }); + self + } + + fn set_cmd_ring(&mut self) -> &mut Self { + let crcr = self.cmd.register(); + let cycle = self.cmd.cycle; + + let regs = &mut self.regs; + + debug!("{TAG} Writing CRCR: {:X}", crcr); + regs.operational.crcr.update_volatile(|r| { + r.set_command_ring_pointer(crcr); + if cycle { + r.set_ring_cycle_state(); + } else { + r.clear_ring_cycle_state(); + } + }); + + self + } + + fn start(&mut self) -> &mut Self { + let regs = &mut self.regs; + debug!("{TAG} Start run"); + regs.operational.usbcmd.update_volatile(|r| { + r.set_run_stop(); + }); + + while regs.operational.usbsts.read_volatile().hc_halted() {} + + info!("{TAG} Is running"); + + regs.doorbell.update_volatile_at(0, |r| { + r.set_doorbell_stream_id(0); + r.set_doorbell_target(0); + }); + + self + } + + fn init_ir(&mut self) -> &mut Self { + debug!("{TAG} Disable interrupts"); + let regs = &mut self.regs; + + regs.operational.usbcmd.update_volatile(|r| { + r.clear_interrupter_enable(); + }); + + let mut ir0 = regs.interrupter_register_set.interrupter_mut(0); + { + debug!("{TAG} Writing ERSTZ"); + ir0.erstsz.update_volatile(|r| r.set(1)); + + let erdp = self.event.erdp(); + debug!("{TAG} Writing ERDP: {:X}", erdp); + + ir0.erdp.update_volatile(|r| { + r.set_event_ring_dequeue_pointer(erdp); + }); + + let erstba = self.event.erstba(); + debug!("{TAG} Writing ERSTBA: {:X}", erstba); + + ir0.erstba.update_volatile(|r| { + r.set(erstba); + }); + ir0.imod.update_volatile(|im| { + im.set_interrupt_moderation_interval(0); + im.set_interrupt_moderation_counter(0); + }); + + debug!("{TAG} Enabling primary interrupter."); + ir0.iman.update_volatile(|im| { + im.set_interrupt_enable(); + }); + } + + // }; + + // self.setup_scratchpads(buf_count); + + self + } + + fn get_speed(&self, port: usize) -> u8 { + self.regs + .port_register_set + .read_volatile_at(port) + .portsc + .port_speed() + } + + fn parse_default_max_packet_size_from_port(&self, port: usize) -> u16 { + match self.get_speed(port) { + 1 | 3 => 64, + 2 => 8, + 4 => 512, + v => unimplemented!("PSI: {}", v), + } + } + + fn reset_cic(&mut self) -> &mut Self { + let regs = &mut self.regs; + let cic = regs + .capability + .hccparams2 + .read_volatile() + .configuration_information_capability(); + regs.operational.config.update_volatile(|r| { + if cic { + r.set_configuration_information_enable(); + } else { + r.clear_configuration_information_enable(); + } + }); + self + } + + fn reset_ports(&mut self) -> &mut Self { + let regs = &mut self.regs; + let port_len = regs.port_register_set.len(); + + for i in 0..port_len { + debug!("{TAG} Port {} start reset", i,); + regs.port_register_set.update_volatile_at(i, |port| { + port.portsc.set_0_port_enabled_disabled(); + port.portsc.set_port_reset(); + }); + + while regs + .port_register_set + .read_volatile_at(i) + .portsc + .port_reset() + {} + + debug!("{TAG} Port {} reset ok", i); + } + self + } + + fn setup_scratchpads(&mut self) -> &mut Self { + let scratchpad_buf_arr = { + let buf_count = { + let count = self + .regs + .capability + .hcsparams2 + .read_volatile() + .max_scratchpad_buffers(); + debug!("{TAG} Scratch buf count: {}", count); + count + }; + if buf_count == 0 { + error!("buf count=0,is it a error?"); + return self; + } + let scratchpad_buf_arr = + ScratchpadBufferArray::new(buf_count, self.config.lock().os.clone()); + + self.dev_ctx.dcbaa[0] = scratchpad_buf_arr.register() as u64; + + debug!( + "{TAG} Setting up {} scratchpads, at {:#0x}", + buf_count, + scratchpad_buf_arr.register() + ); + scratchpad_buf_arr + }; + + self.scratchpad_buf_arr = Some(scratchpad_buf_arr); + self + } + + fn test_cmd(&mut self) -> &mut Self { + //TODO:assert like this in runtime if build with debug mode? + debug!("{TAG} Test command ring"); + for _ in 0..3 { + let completion = self + .post_cmd(command::Allowed::Noop(command::Noop::new())) + .unwrap(); + } + debug!("{TAG} Command ring ok"); + self + } + + fn post_cmd(&mut self, mut trb: command::Allowed) -> crate::err::Result { + let addr = self.cmd.enque_command(trb); + + self.regs.doorbell.update_volatile_at(0, |r| { + r.set_doorbell_stream_id(0); + r.set_doorbell_target(0); + }); + + fence(Ordering::Release); + + let r = self.event_busy_wait_cmd(addr as _)?; + + /// update erdp + self.regs + .interrupter_register_set + .interrupter_mut(0) + .erdp + .update_volatile(|f| { + f.set_event_ring_dequeue_pointer(self.event.erdp()); + }); + + Ok(r) + } + + fn event_busy_wait_cmd(&mut self, addr: u64) -> crate::err::Result { + debug!("Wait result"); + loop { + if let Some((event, cycle)) = self.event.next() { + match event { + event::Allowed::CommandCompletion(c) => { + let mut code = CompletionCode::Invalid; + if let Ok(c) = c.completion_code() { + code = c; + } else { + continue; + } + trace!( + "[CMD] << {code:#?} @{:X} got result, cycle {}", + c.command_trb_pointer(), + c.cycle_bit() + ); + if c.command_trb_pointer() != addr { + continue; + } + + if let CompletionCode::Success = code { + return Ok(c); + } + return Err(Error::CMD(code)); + } + _ => warn!("event: {:?}", event), + } + } + } + } + + fn trace_dump_context(&self, slot_id: usize) { + let dev = &self.dev_ctx.device_out_context_list[slot_id]; + trace!( + "slot {} {:?}", + slot_id, + DeviceHandler::slot(&**dev).slot_state() + ); + trace!("device context state:{:#?}", &**dev) + } + + fn append_port_to_route_string(route_string: u32, port_id: usize) -> u32 { + let mut route_string = route_string; + for tier in 0..5 { + if route_string & (0x0f << (tier * 4)) == 0 { + if tier < 5 { + route_string |= (port_id as u32) << (tier * 4); + return route_string; + } + } + } + + route_string + } + + fn ep_ring_mut(&mut self, device_slot_id: usize, dci: u8) -> &mut Ring { + trace!("fetch transfer ring at slot{}-dci{}", device_slot_id, dci); + &mut self.dev_ctx.transfer_rings[device_slot_id][dci as usize - 1] + } + + fn update_erdp(&mut self) { + self.regs + .interrupter_register_set + .interrupter_mut(0) + .erdp + .update_volatile(|f| { + f.set_event_ring_dequeue_pointer(self.event.erdp()); + }); + } + + fn event_busy_wait_transfer(&mut self, addr: u64) -> crate::err::Result { + trace!("Wait result @{addr:#X}"); + loop { + // sleep(Duration::from_millis(2)); + if let Some((event, cycle)) = self.event.next() { + self.update_erdp(); + + match event { + event::Allowed::TransferEvent(c) => { + let code = c.completion_code().unwrap(); + trace!( + "[Transfer] << {code:#?} @{:#X} got result{}, cycle {}, len {}", + c.trb_pointer(), + code as usize, + c.cycle_bit(), + c.trb_transfer_length() + ); + + // if c.trb_pointer() != addr { + // debug!(" @{:#X} != @{:#X}", c.trb_pointer(), addr); + // // return Err(Error::Pip); + // continue; + // } + trace!("code:{:?},pointer:{:x}", code, c.trb_pointer()); + if CompletionCode::Success == code || CompletionCode::ShortPacket == code { + return Ok(c); + } + debug!("error!"); + return Err(Error::CMD(code)); + } + _ => warn!("event: {:?}", event), + } + } + } + } + + fn switch_interface( + &mut self, + device_slot_id: usize, + interface: usize, + alternative: usize, + ) -> crate::err::Result> { + self.control_transfer( + device_slot_id, + ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Standard, + Recipient::Interface, + ), + request: bRequest::Generic(StandardbRequest::SetInterface), + index: interface as _, + value: alternative as _, + data: None, + }, + ) + } + + fn reset_endpoint(&mut self, device_slot_id: usize, dci: usize) -> crate::err::Result> { + let command_completion = self + .post_cmd(command::Allowed::ResetEndpoint( + *ResetEndpoint::new() + .set_endpoint_id(dci as _) + .set_slot_id(device_slot_id as _), + )) + .unwrap(); + + self.trace_dump_context(device_slot_id); + match command_completion.completion_code() { + Ok(ok) => match ok { + CompletionCode::Success => Ok(UCB::::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))), + other => panic!("err:{:?}", other), + }, + Err(err) => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Unknown(err), + ))), + } + } + + fn setup_device( + &mut self, + device_slot_id: usize, + configure: &TopologicalUSBDescriptorConfiguration, + ) -> crate::err::Result> { + /** + A device can support multiple configurations. Within each configuration can be multiple + interfaces, each possibly having alternate settings. These interfaces can pertain to different + functions that co-reside in the same composite device. Several independent video functions can + exist in the same device. Interfaces that belong to the same video function are grouped into a + Video Interface Collection described by an Interface Association Descriptor. If the device + contains multiple independent video functions, there must be multiple Video Interface + Collections (and hence multiple Interface Association Descriptors), each providing full access to + their associated video function. + */ + configure.child.iter().for_each(|func| match func { + TopologicalUSBDescriptorFunction::InterfaceAssociation(assoc) => { + // todo!("enumrate complex device!") + + // let (interface0, attributes, endpoints) = + assoc + .1 + .iter() + .flat_map(|f| match f { + TopologicalUSBDescriptorFunction::InterfaceAssociation(_) => { + panic!("anyone could help this guy????") + } + TopologicalUSBDescriptorFunction::Interface(interface) => interface, + }) + .for_each(|(_, _, endpoints)| { + { + let input = + self.dev_ctx.device_input_context_list[device_slot_id].deref_mut(); + + let entries = endpoints + .iter() + .filter_map(|endpoint| { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = endpoint + { + Some(ep) + } else { + None + } + }) + .map(|endpoint| endpoint.doorbell_value_aka_dci()) + .max() + .unwrap_or(1) + .max(input.device().slot().context_entries() as u32); + + input + .device_mut() + .slot_mut() + .set_context_entries(entries as u8); + } + + // trace!("endpoints:{:#?}", endpoints); + + for item in endpoints { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = item { + trace!("configuring {:#?}", ep); + let dci = ep.doorbell_value_aka_dci() as usize; + let max_packet_size = ep.max_packet_size; + let ring_addr = + self.ep_ring_mut(device_slot_id, dci as _).register(); + + let input = self.dev_ctx.device_input_context_list[device_slot_id] + .deref_mut(); + let control_mut = input.control_mut(); + debug!("init ep {} {:?}", dci, ep.endpoint_type()); + control_mut.set_add_context_flag(dci); + let ep_mut = input.device_mut().endpoint_mut(dci); + ep_mut.set_interval(3); + ep_mut.set_endpoint_type(ep.endpoint_type()); + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut.set_max_packet_size(max_packet_size); + ep_mut.set_error_count(3); + ep_mut.set_dequeue_cycle_state(); + let endpoint_type = ep.endpoint_type(); + match endpoint_type { + EndpointType::Control => {} + EndpointType::BulkOut | EndpointType::BulkIn => { + ep_mut.set_max_burst_size(0); + ep_mut.set_max_primary_streams(0); + } + EndpointType::IsochOut + | EndpointType::IsochIn + | EndpointType::InterruptOut + | EndpointType::InterruptIn => { + //init for isoch/interrupt + ep_mut.set_max_packet_size(max_packet_size & 0x7ff); //refer xhci page 162 + ep_mut.set_max_burst_size( + ((max_packet_size & 0x1800) >> 11).try_into().unwrap(), + ); + ep_mut.set_mult(0); //always 0 for interrupt + + if let EndpointType::IsochOut | EndpointType::IsochIn = + endpoint_type + { + ep_mut.set_error_count(0); + } + + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut + .set_max_endpoint_service_time_interval_payload_low(4); + //best guess? + } + EndpointType::NotValid => { + unreachable!("Not Valid Endpoint should not exist.") + } + } + } + } + }); + + let input_addr = { + let input = self.dev_ctx.device_input_context_list[device_slot_id].deref_mut(); + let control_mut = input.control_mut(); + control_mut.set_add_context_flag(0); + control_mut.set_configuration_value(configure.data.config_val()); + + control_mut.set_interface_number(0); // + control_mut.set_alternate_setting(0); //always exist + (input as *const Input<16>).addr() as u64 + }; + + let command_completion = self + .post_cmd(command::Allowed::ConfigureEndpoint( + *command::ConfigureEndpoint::default() + .set_slot_id(device_slot_id as _) + .set_input_context_pointer(input_addr), + )) + .unwrap(); + + self.trace_dump_context(device_slot_id); + match command_completion.completion_code() { + Ok(ok) => match ok { + CompletionCode::Success => { + UCB::::new(CompleteCode::Event(TransferEventCompleteCode::Success)) + } + other => panic!("err:{:?}", other), + }, + Err(err) => { + UCB::new(CompleteCode::Event(TransferEventCompleteCode::Unknown(err))) + } + }; + } + TopologicalUSBDescriptorFunction::Interface(interfaces) => { + let (interface0, attributes, endpoints) = interfaces.first().unwrap(); + let input_addr = { + { + let input = + self.dev_ctx.device_input_context_list[device_slot_id].deref_mut(); + { + let control_mut = input.control_mut(); + control_mut.set_add_context_flag(0); + control_mut.set_configuration_value(configure.data.config_val()); + + control_mut.set_interface_number(interface0.interface_number); + control_mut.set_alternate_setting(interface0.alternate_setting); + } + + let entries = endpoints + .iter() + .filter_map(|endpoint| { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = endpoint { + Some(ep) + } else { + None + } + }) + .map(|endpoint| endpoint.doorbell_value_aka_dci()) + .max() + .unwrap_or(1); + + input + .device_mut() + .slot_mut() + .set_context_entries(entries as u8); + } + + // debug!("endpoints:{:#?}", interface.endpoints); + + for item in endpoints { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = item { + let dci = ep.doorbell_value_aka_dci() as usize; + let max_packet_size = ep.max_packet_size; + let ring_addr = self.ep_ring_mut(device_slot_id, dci as _).register(); + + let input = + self.dev_ctx.device_input_context_list[device_slot_id].deref_mut(); + let control_mut = input.control_mut(); + debug!("init ep {} {:?}", dci, ep.endpoint_type()); + control_mut.set_add_context_flag(dci); + let ep_mut = input.device_mut().endpoint_mut(dci); + ep_mut.set_interval(3); + ep_mut.set_endpoint_type(ep.endpoint_type()); + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut.set_max_packet_size(max_packet_size); + ep_mut.set_error_count(3); + ep_mut.set_dequeue_cycle_state(); + let endpoint_type = ep.endpoint_type(); + match endpoint_type { + EndpointType::Control => {} + EndpointType::BulkOut | EndpointType::BulkIn => { + ep_mut.set_max_burst_size(0); + ep_mut.set_max_primary_streams(0); + } + EndpointType::IsochOut + | EndpointType::IsochIn + | EndpointType::InterruptOut + | EndpointType::InterruptIn => { + //init for isoch/interrupt + ep_mut.set_max_packet_size(max_packet_size & 0x7ff); //refer xhci page 162 + ep_mut.set_max_burst_size( + ((max_packet_size & 0x1800) >> 11).try_into().unwrap(), + ); + ep_mut.set_mult(0); //always 0 for interrupt + + if let EndpointType::IsochOut | EndpointType::IsochIn = + endpoint_type + { + ep_mut.set_error_count(0); + } + + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut.set_max_endpoint_service_time_interval_payload_low(4); + //best guess? + } + EndpointType::NotValid => { + unreachable!("Not Valid Endpoint should not exist.") + } + } + } + } + + let input = self.dev_ctx.device_input_context_list[device_slot_id].deref_mut(); + (input as *const Input<16>).addr() as u64 + }; + + let command_completion = self + .post_cmd(command::Allowed::ConfigureEndpoint( + *command::ConfigureEndpoint::default() + .set_slot_id(device_slot_id as _) + .set_input_context_pointer(input_addr), + )) + .unwrap(); + + self.trace_dump_context(device_slot_id); + match command_completion.completion_code() { + Ok(ok) => match ok { + CompletionCode::Success => { + UCB::::new(CompleteCode::Event(TransferEventCompleteCode::Success)) + } + other => panic!("err:{:?}", other), + }, + Err(err) => { + UCB::new(CompleteCode::Event(TransferEventCompleteCode::Unknown(err))) + } + }; + } + }); + //TODO: Improve + Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))) + } + + fn prepare_transfer_normal(&mut self, device_slot_id: usize, dci: u8) { + //in our code , the init state of transfer ring always has ccs = 0, so we use ccs =1 to fill transfer ring + let mut normal = transfer::Normal::default(); + normal.set_cycle_bit(); + let ring = self.ep_ring_mut(device_slot_id, dci); + ring.enque_trbs(vec![normal.into_raw(); 31]); //the 32 is link trb + } +} + +impl Controller for XHCI +where + O: PlatformAbstractions, +{ + fn new(config: Arc>>) -> Self + where + Self: Sized, + { + let mmio_base = config.lock().base_addr.clone().into(); + unsafe { + let regs = RegistersBase::new(mmio_base, MemMapper); + let ext_list = + RegistersExtList::new(mmio_base, regs.capability.hccparams1.read(), MemMapper); + + // TODO: pcie 未配置,读不出来 + // let version = self.core_mut().regs.capability.hciversion.read_volatile(); + // info!("xhci version: {:x}", version.get()); + let hcsp1 = regs.capability.hcsparams1.read_volatile(); + let max_slots = hcsp1.number_of_device_slots(); + let max_ports = hcsp1.number_of_ports(); + let max_irqs = hcsp1.number_of_interrupts(); + let page_size = regs.operational.pagesize.read_volatile().get(); + debug!( + "{TAG} Max_slots: {}, max_ports: {}, max_irqs: {}, page size: {}", + max_slots, max_ports, max_irqs, page_size + ); + + let dev_ctx = DeviceContextList::new(max_slots, config.clone()); + + // Create the command ring with 4096 / 16 (TRB size) entries, so that it uses all of the + // DMA allocation (which is at least a 4k page). + let entries_per_page = O::PAGE_SIZE / mem::size_of::(); + let cmd = Ring::new(config.lock().os.clone(), entries_per_page, true).unwrap(); + let event = EventRing::new(config.lock().os.clone()).unwrap(); + + debug!("{TAG} ring size {}", cmd.len()); + + Self { + regs, + ext_list, + config: config.clone(), + max_slots: max_slots, + max_ports: max_ports, + max_irqs: max_irqs, + scratchpad_buf_arr: None, + cmd: cmd, + event: event, + dev_ctx: dev_ctx, + } + } + } + + fn init(&mut self) { + self.chip_hardware_reset() + .set_max_device_slots() + .set_dcbaap() + .set_cmd_ring() + .init_ir() + .setup_scratchpads() + .start() + .test_cmd() + .reset_ports(); + } + + fn probe(&mut self) -> Vec { + let mut founded = Vec::new(); + + { + let mut port_id_list = Vec::new(); + let port_len = self.regs.port_register_set.len(); + for i in 0..port_len { + let portsc = &self.regs.port_register_set.read_volatile_at(i).portsc; + info!( + "{TAG} Port {}: Enabled: {}, Connected: {}, Speed {}, Power {}", + i, + portsc.port_enabled_disabled(), + portsc.current_connect_status(), + portsc.port_speed(), + portsc.port_power() + ); + + if !portsc.port_enabled_disabled() { + continue; + } + + port_id_list.push(i); + } + + for port_idx in port_id_list { + let port_id = port_idx + 1; + //↓ + let slot_id = self.device_slot_assignment(); + self.dev_ctx.new_slot(slot_id as usize, 0, port_id, 32); //TODO: we still need to imple the non root hub + debug!("assign complete!"); + //↓ + self.address_device(slot_id, port_id); + self.trace_dump_context(slot_id); + //↓ + let packet_size0 = self.control_fetch_control_point_packet_size(slot_id); + trace!("packet_size0: {}", packet_size0); + //↓ + self.set_ep0_packet_size(slot_id, packet_size0 as _); + founded.push(slot_id) + } + } + + founded + } + + fn control_transfer( + &mut self, + dev_slot_id: usize, + urb_req: ControlTransfer, + ) -> crate::err::Result> { + let direction = urb_req.request_type.direction.clone(); + let buffer = urb_req.data; + + let mut len = 0; + let data = if let Some((addr, length)) = buffer { + let mut data = transfer::DataStage::default(); + len = length; + data.set_data_buffer_pointer(addr as u64) + .set_trb_transfer_length(len as _) + .set_direction(direction); + Some(data) + } else { + None + }; + + let setup = *transfer::SetupStage::default() + .set_request_type(urb_req.request_type.into()) + .set_request(match urb_req.request { + trasnfer::control::bRequest::Generic(generic) => generic as u8, + trasnfer::control::bRequest::DriverSpec(spec) => spec, + }) + .set_value(urb_req.value) + .set_index(urb_req.index) + .set_transfer_type({ + if buffer.is_some() { + match direction { + Direction::In => TransferType::In, + Direction::Out => TransferType::Out, + } + } else { + TransferType::No + } + }) + .set_length(len as u16); + trace!("{:#?}", setup); + + let mut status = *transfer::StatusStage::default().set_interrupt_on_completion(); + + //=====post!======= + let mut trbs: Vec = Vec::new(); + + trbs.push(setup.into()); + if let Some(data) = data { + trbs.push(data.into()); + } + trbs.push(status.into()); + + let mut trb_pointers = Vec::new(); + + { + let ring = self.ep_ring_mut(dev_slot_id, 1); + for trb in trbs { + trb_pointers.push(ring.enque_transfer(trb)); + } + } + + if trb_pointers.len() == 2 { + trace!( + "[Transfer] >> setup@{:#X}, status@{:#X}", + trb_pointers[0], + trb_pointers[1] + ); + } else { + trace!( + "[Transfer] >> setup@{:#X}, data@{:#X}, status@{:#X}", + trb_pointers[0], + trb_pointers[1], + trb_pointers[2] + ); + } + + fence(Ordering::Release); + self.regs.doorbell.update_volatile_at(dev_slot_id, |r| { + r.set_doorbell_target(1); + }); + + match self.event_busy_wait_transfer(*trb_pointers.last().unwrap() as _) { + Ok(complete) => match complete.completion_code() { + Ok(complete) => match complete { + CompletionCode::Success => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))), + err => panic!("{:?}", err), + }, + Err(fail) => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Unknown(fail), + ))), + }, + Err(Error::CMD(err)) if let CompletionCode::StallError = err => Ok(UCB::new( + CompleteCode::Event(TransferEventCompleteCode::Stall), + )), + any => panic!("impossible:{:?}", any), + } + } + + fn configure_device( + &mut self, + dev_slot_id: usize, + urb_req: Configuration, + dev: Option<&mut DriverIndependentDeviceInstance>, + ) -> crate::err::Result> { + match urb_req { + Configuration::SetupDevice(config) => self.setup_device(dev_slot_id, &config), + Configuration::SwitchInterface(interface, alternative) => { + let switch_interface = self.switch_interface(dev_slot_id, interface, alternative); + if switch_interface.is_ok() && dev.is_some() { + let dev = dev.unwrap(); + dev.interface_val = interface; + dev.current_alternative_interface_value = alternative; + } + switch_interface + } + Configuration::SwitchConfig(_, _) => todo!(), + Configuration::ResetEndpoint(ep) => self.reset_endpoint(dev_slot_id, ep), + } + } + + fn device_slot_assignment(&mut self) -> usize { + // enable slot + let result = self + .post_cmd(command::Allowed::EnableSlot( + *command::EnableSlot::default().set_slot_type({ + { + // TODO: PCI未初始化,读不出来 + // let mut regs = self.regs.lock(); + // match regs.supported_protocol(port) { + // Some(p) => p.header.read_volatile().protocol_slot_type(), + // None => { + // warn!( + // "{TAG} Failed to find supported protocol information for port {}", + // port + // ); + // 0 + // } + // } + 0 + } + }), + )) + .unwrap(); + + let slot_id = result.slot_id(); + trace!("assigned slot id: {slot_id}"); + slot_id as usize + } + + fn address_device(&mut self, slot_id: usize, port_id: usize) { + let port_idx = port_id - 1; + let port_speed = self.get_speed(port_idx); + let max_packet_size = self.parse_default_max_packet_size_from_port(port_idx); + let dci = 1; + + let transfer_ring_0_addr = self.ep_ring_mut(slot_id, dci).register(); + let ring_cycle_bit = self.ep_ring_mut(slot_id, dci).cycle; + let context_addr = { + let context_mut = self + .dev_ctx + .device_input_context_list + .get_mut(slot_id) + .unwrap() + .deref_mut(); + + let control_context = context_mut.control_mut(); + control_context.set_add_context_flag(0); + control_context.set_add_context_flag(1); + for i in 2..32 { + control_context.clear_drop_context_flag(i); + } + + let slot_context = context_mut.device_mut().slot_mut(); + slot_context.clear_multi_tt(); + slot_context.clear_hub(); + slot_context.set_route_string(Self::append_port_to_route_string(0, port_id)); // for now, not support more hub ,so hardcode as 0.//TODO: generate route string + slot_context.set_context_entries(1); + slot_context.set_max_exit_latency(0); + slot_context.set_root_hub_port_number(port_id as _); //todo: to use port number + slot_context.set_number_of_ports(0); + slot_context.set_parent_hub_slot_id(0); + slot_context.set_tt_think_time(0); + slot_context.set_interrupter_target(0); + slot_context.set_speed(port_speed); + + let endpoint_0 = context_mut.device_mut().endpoint_mut(dci as _); + endpoint_0.set_endpoint_type(xhci::context::EndpointType::Control); + endpoint_0.set_max_packet_size(max_packet_size); + endpoint_0.set_max_burst_size(0); + endpoint_0.set_error_count(3); + endpoint_0.set_tr_dequeue_pointer(transfer_ring_0_addr); + if ring_cycle_bit { + endpoint_0.set_dequeue_cycle_state(); + } else { + endpoint_0.clear_dequeue_cycle_state(); + } + endpoint_0.set_interval(0); + endpoint_0.set_max_primary_streams(0); + endpoint_0.set_mult(0); + endpoint_0.set_error_count(3); + + (context_mut as *const Input<16>).addr() as u64 + }; + + fence(Ordering::Release); + + let result = self + .post_cmd(command::Allowed::AddressDevice( + *command::AddressDevice::new() + .set_slot_id(slot_id as _) + .set_input_context_pointer(context_addr), + )) + .unwrap(); + + trace!("address slot [{}] ok", slot_id); + } + + fn control_fetch_control_point_packet_size(&mut self, slot_id: usize) -> u8 { + trace!("control_fetch_control_point_packet_size"); + let mut buffer = DMA::new_vec(0u8, 8, 64, self.config.lock().os.dma_alloc()); + self.control_transfer( + slot_id, + ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Standard, + Recipient::Device, + ), + request: StandardbRequest::GetDescriptor.into(), + index: 0, + value: crate::usb::descriptors::construct_control_transfer_type( + USBStandardDescriptorTypes::Device as u8, + 0, + ) + .bits(), + data: Some((buffer.addr() as usize, buffer.length_for_bytes())), + }, + ) + .unwrap(); + + let mut data = [0u8; 8]; + data[..8].copy_from_slice(&buffer); + trace!("got {:?}", data); + data.last() + .and_then(|len| Some(if *len == 0 { 8u8 } else { *len })) + .unwrap() + } + + fn set_ep0_packet_size(&mut self, dev_slot_id: usize, max_packet_size: u16) { + let addr = { + let input = self.dev_ctx.device_input_context_list[dev_slot_id as usize].deref_mut(); + input + .device_mut() + .endpoint_mut(1) //dci=1: endpoint 0 + .set_max_packet_size(max_packet_size); + + debug!( + "CMD: evaluating context for set endpoint0 packet size {}", + max_packet_size + ); + (input as *mut Input<16>).addr() as u64 + }; + self.post_cmd(command::Allowed::EvaluateContext( + *command::EvaluateContext::default() + .set_slot_id(dev_slot_id as _) + .set_input_context_pointer(addr), + )) + .unwrap(); + } + + fn bulk_transfer( + &mut self, + dev_slot_id: usize, + urb_req: trasnfer::bulk::BulkTransfer, + ) -> crate::err::Result> { + let (addr, len) = urb_req.buffer_addr_len; + let enqued_transfer = self + .ep_ring_mut(dev_slot_id, urb_req.endpoint_id as _) + .enque_transfer(transfer::Allowed::Normal( + *Normal::new() + .set_data_buffer_pointer(addr as _) + .set_trb_transfer_length(len as _) + .set_interrupter_target(0) + .set_interrupt_on_short_packet() + .set_interrupt_on_completion(), + )); + self.regs.doorbell.update_volatile_at(dev_slot_id, |r| { + r.set_doorbell_target(urb_req.endpoint_id as _); + }); + + let transfer_event = self.event_busy_wait_transfer(enqued_transfer as _).unwrap(); + match transfer_event.completion_code() { + Ok(complete) => match complete { + CompletionCode::Success | CompletionCode::ShortPacket => { + trace!("ok! return a success ucb!"); + Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))) + } + err => panic!("{:?}", err), + }, + Err(fail) => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Unknown(fail), + ))), + } + } + + fn interrupt_transfer( + &mut self, + dev_slot_id: usize, + urb_req: trasnfer::interrupt::InterruptTransfer, + ) -> crate::err::Result> { + let (addr, len) = urb_req.buffer_addr_len; + let enqued_transfer = self + .ep_ring_mut(dev_slot_id, urb_req.endpoint_id as _) + .enque_transfer(transfer::Allowed::Normal( + *Normal::new() + .set_data_buffer_pointer(addr as _) + .set_trb_transfer_length(len as _) + .set_interrupter_target(0) + .set_interrupt_on_short_packet() + .set_interrupt_on_completion(), + )); + self.regs.doorbell.update_volatile_at(dev_slot_id, |r| { + r.set_doorbell_target(urb_req.endpoint_id as _); + }); + + let transfer_event = self.event_busy_wait_transfer(enqued_transfer as _).unwrap(); + match transfer_event.completion_code() { + Ok(complete) => match complete { + CompletionCode::Success | CompletionCode::ShortPacket => { + trace!("ok! return a success ucb!"); + Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))) + } + err => panic!("{:?}", err), + }, + Err(fail) => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Unknown(fail), + ))), + } + } + + fn extra_step(&mut self, dev_slot_id: usize, urb_req: ExtraStep) -> crate::err::Result> { + match urb_req { + ExtraStep::PrepareForTransfer(dci) => { + if dci > 1 { + self.prepare_transfer_normal(dev_slot_id, dci as u8); + Ok(UCB::::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))) + } else { + Err(Error::DontDoThatOnControlPipe) + } + } + } + } + + fn isoch_transfer( + &mut self, + dev_slot_id: usize, + urb_req: trasnfer::isoch::IsochTransfer, + ) -> crate::err::Result> { + let mut request_times = urb_req.request_times; + let (buffer_addr, total_len) = urb_req.buffer_addr_len; + let isoch_id = urb_req.endpoint_id; + let mut packet_size = urb_req.packet_size; + let mut remain = None; + + trace!("packet size:{packet_size},request_times:{request_times},total_len:{total_len}"); + assert!(packet_size * request_times <= total_len); + + let max_packet_size = self + .dev_ctx + .device_out_context_list + .get(dev_slot_id) + .unwrap() + .endpoint(urb_req.endpoint_id) + .max_packet_size() as usize; + if max_packet_size < packet_size { + let total = packet_size * request_times; + remain = Some((total % max_packet_size)); + request_times = total / max_packet_size; + packet_size = max_packet_size; + } + + assert!(request_times < 32 || (request_times < 31 && remain.is_some())); //HARDCODE ring size is 32, should not over flap previous enqueued trb. + + if remain.is_none() { + request_times -= 1; + remain = Some(packet_size) + } + + let mut collect = (0..request_times) + .map(|i| i * packet_size + buffer_addr) + .enumerate() + .map(|(i, addr)| { + transfer::Allowed::Isoch({ + let mut isoch = Isoch::new(); + isoch + .set_start_isoch_asap() + .set_data_buffer_pointer(addr as _) + .set_trb_transfer_length(packet_size as _) + .set_td_size_or_tbc((request_times - 1 - i) as _); + isoch + }) + }) + .collect::>(); + collect.push(transfer::Allowed::Isoch( + *Isoch::new() + .set_start_isoch_asap() + .set_data_buffer_pointer((buffer_addr + request_times * packet_size) as _) + .set_trb_transfer_length(remain.unwrap() as _) + .set_td_size_or_tbc(0) + .set_interrupt_on_completion(), + )); + + let enqued_trbs = self + .ep_ring_mut(dev_slot_id, isoch_id as _) + .enque_trbs(collect.iter().map(|a| a.into_raw()).collect()); + + let transfer_event = self.event_busy_wait_transfer(enqued_trbs as _).unwrap(); + + match transfer_event.completion_code() { + Ok(complete) => match complete { + CompletionCode::Success | CompletionCode::ShortPacket => { + trace!("ok! return a success ucb!"); + Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Success, + ))) + } + err => panic!("{:?}", err), + }, + Err(fail) => Ok(UCB::new(CompleteCode::Event( + TransferEventCompleteCode::Unknown(fail), + ))), + } + } + + fn debug_op(&mut self, dev_slot_id: usize, debug_op: Debugop) -> crate::err::Result> { + match debug_op { + Debugop::DumpDevice => { + trace!( + "debug dump device:{:#?}", + &*self.dev_ctx.device_out_context_list[dev_slot_id] + ); + } + } + + Ok(UCB::new(CompleteCode::Debug)) + } +} diff --git a/crates/driver_usb/src/host/data_structures/host_controllers/xhci/ring.rs b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/ring.rs new file mode 100644 index 0000000000..4c1356e379 --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/host_controllers/xhci/ring.rs @@ -0,0 +1,155 @@ +use core::fmt; +use core::fmt::Debug; +use core::mem; +use core::ptr::slice_from_raw_parts; + +use crate::abstractions::dma::DMA; +use crate::abstractions::OSAbstractions; +use crate::err::*; +use alloc::boxed::Box; +use alloc::slice; +use alloc::vec; +use alloc::vec::Vec; +use axhal::cpu::this_cpu_id; +use log::debug; +use log::trace; +pub use xhci::ring::trb; +use xhci::ring::trb::command; +use xhci::ring::trb::event; +use xhci::ring::trb::transfer; +use xhci::ring::trb::Link; +const TRB_LEN: usize = 4; +pub type TrbData = [u32; TRB_LEN]; + +pub struct Ring { + link: bool, + pub trbs: DMA<[TrbData], O::DMA>, + pub i: usize, + pub cycle: bool, +} + +impl Ring { + pub fn new(os: O, len: usize, link: bool) -> Result { + let a = os.dma_alloc(); + let mut trbs = DMA::new_vec([0; TRB_LEN], len, 64, a); + Ok(Self { + trbs, + i: 0, + cycle: link, + link, + }) + } + pub fn len(&self) -> usize { + self.trbs.len() + } + + fn get_trb(&self) -> &TrbData { + unsafe { &self.trbs[self.i] } + } + + pub fn register(&self) -> u64 { + self.get_trb().as_ptr() as usize as u64 + } + + pub fn enque_command(&mut self, mut trb: command::Allowed) -> usize { + if self.cycle { + trb.set_cycle_bit(); + } else { + trb.clear_cycle_bit(); + } + let addr = self.enque_trb(trb.clone().into_raw()); + trace!("[CMD] >> {:?} @{:X}", trb, addr); + addr + } + + pub fn enque_transfer(&mut self, mut trb: transfer::Allowed) -> usize { + if self.cycle { + trb.set_cycle_bit(); + } else { + trb.clear_cycle_bit(); + } + let addr = self.enque_trb(trb.clone().into_raw()); + addr + } + + pub fn enque_trb(&mut self, mut trb: TrbData) -> usize { + self.trbs[self.i].copy_from_slice(&trb); + let addr = self.trbs[self.i].as_ptr() as usize; + trace!( + "enqueued {} @{:#X}\n{:x}\n{:x}\n{:x}\n{:x}\n------------------------------------------------", + self.i, addr, trb[0], trb[1], trb[2], trb[3] + ); + self.next_index(); + addr + } + + pub fn enque_trbs(&mut self, trb: Vec) -> usize { + let mut last = 0; + for ele in trb { + last = self.enque_trb(ele); + } + last + } + + fn next_index(&mut self) -> usize { + self.i += 1; + let mut need_link = false; + let len = self.len(); + + // link模式下,最后一个是Link + if self.link && self.i >= len - 1 { + self.i = 0; + need_link = true; + trace!("flip and link!") + } else if self.i >= len { + self.i = 0; + } + + if need_link { + trace!("link!"); + let address = self.trbs[0].as_ptr() as usize; + let mut link = Link::new(); + link.set_ring_segment_pointer(address as u64) + .set_toggle_cycle(); + + if self.cycle { + link.set_cycle_bit(); + } else { + link.clear_cycle_bit(); + } + let trb = command::Allowed::Link(link); + let link_trb = trb.into_raw(); + let mut this_trb = &mut self.trbs[len - 1]; + this_trb.copy_from_slice(&link_trb); + + self.cycle = !self.cycle; + } + + self.i + } + + /// 完成一次循环返回true + pub fn inc_deque(&mut self) -> bool { + self.i += 1; + let mut is_cycle = false; + let len = self.len(); + if self.link { + } else { + if self.i >= len { + self.i = 0; + self.cycle = !self.cycle; + is_cycle = true; + } + } + + is_cycle + } + + pub fn current_data(&mut self) -> (&TrbData, bool) { + (&self.trbs[self.i], self.cycle) + } + + pub fn get_len(&self) -> usize { + self.trbs.len() + } +} diff --git a/crates/driver_usb/src/host/data_structures/mod.rs b/crates/driver_usb/src/host/data_structures/mod.rs new file mode 100644 index 0000000000..569a679b96 --- /dev/null +++ b/crates/driver_usb/src/host/data_structures/mod.rs @@ -0,0 +1,21 @@ +use core::{fmt::Debug, mem::MaybeUninit}; + +pub mod host_controllers; + +#[derive(Clone, Debug)] +pub enum MightBeInited +where + T: Clone, +{ + Inited(T), + Uninit, +} + +impl Default for MightBeInited +where + T: Clone + Debug, +{ + fn default() -> Self { + Self::Uninit + } +} diff --git a/crates/driver_usb/src/host/mod.rs b/crates/driver_usb/src/host/mod.rs new file mode 100644 index 0000000000..2839454f60 --- /dev/null +++ b/crates/driver_usb/src/host/mod.rs @@ -0,0 +1,154 @@ +use alloc::{boxed::Box, collections::binary_heap::Iter, sync::Arc, vec::Vec}; +use data_structures::host_controllers::{xhci::XHCI, Controller, ControllerArc}; +use log::trace; +use spinlock::SpinNoIrq; +use xhci::ring::trb::event; + +use crate::{ + abstractions::PlatformAbstractions, + err, + glue::{driver_independent_device_instance::DriverIndependentDeviceInstance, ucb::UCB}, + usb::{self, operation::Configuration, trasnfer::{bulk::BulkTransfer, control::ControlTransfer}, urb::URB}, + USBSystemConfig, +}; + +pub mod data_structures; + +impl USBSystemConfig +where + O: PlatformAbstractions, +{ + pub fn new(mmio_base_addr: usize, irq_num: u32, irq_priority: u32, os_dep: O) -> Self { + let base_addr = O::VirtAddr::from(mmio_base_addr); + Self { + base_addr, + irq_num, + irq_priority, + os: os_dep, + } + } +} + +#[derive(Clone)] +pub struct USBHostSystem +where + O: PlatformAbstractions, +{ + config: Arc>>, + controller: ControllerArc, +} + +impl USBHostSystem +where + O: PlatformAbstractions + 'static, +{ + pub fn new(config: Arc>>) -> crate::err::Result { + let controller = Arc::new(SpinNoIrq::new({ + let xhciregisters: Box<(dyn Controller + 'static)> = { + if cfg!(feature = "xhci") { + Box::new(XHCI::new(config.clone())) + } else { + panic!("no host controller defined") + } + }; + xhciregisters + })); + Ok(Self { config, controller }) + } + + pub fn init(&self) { + self.controller.lock().init(); + trace!("controller init complete"); + } + + pub fn probe(&self, consumer: F) + where + F: FnMut(DriverIndependentDeviceInstance), + { + let mut probe = self.controller.lock().probe(); + probe + .iter() + .map(|slot_id| { + DriverIndependentDeviceInstance::new(slot_id.clone(), self.controller.clone()) + }) + .for_each(consumer); + } + + pub fn control_transfer( + &mut self, + dev_slot_id: usize, + urb_req: ControlTransfer, + ) -> crate::err::Result> { + self.controller + .lock() + .control_transfer(dev_slot_id, urb_req) + } + + pub fn configure_device( + &mut self, + dev_slot_id: usize, + urb_req: Configuration, + dev: Option<&mut DriverIndependentDeviceInstance>, + ) -> crate::err::Result> { + self.controller + .lock() + .configure_device(dev_slot_id, urb_req, dev) + } + + pub fn urb_request( + &mut self, + request: URB, + dev: &mut Vec>, + ) -> crate::err::Result> { + match request.operation { + usb::urb::RequestedOperation::Control(control) => { + trace!("request transfer!"); + self.control_transfer(request.device_slot_id, control) + } + usb::urb::RequestedOperation::Bulk(bulk_transfer) => self + .controller + .lock() + .bulk_transfer(request.device_slot_id, bulk_transfer), + usb::urb::RequestedOperation::Interrupt(interrupt_transfer) => self + .controller + .lock() + .interrupt_transfer(request.device_slot_id, interrupt_transfer), + usb::urb::RequestedOperation::Isoch(isoch_transfer) => self + .controller + .lock() + .isoch_transfer(request.device_slot_id, isoch_transfer), + usb::urb::RequestedOperation::ConfigureDevice(configure) => { + self.controller.lock().configure_device( + request.device_slot_id, + configure, + dev.get_mut(request.device_slot_id - 1), + ) + } + usb::urb::RequestedOperation::ExtraStep(step) => self + .controller + .lock() + .extra_step(request.device_slot_id, step), + usb::urb::RequestedOperation::Debug(deb) => { + self.controller.lock().debug_op(request.device_slot_id, deb) + } + } + } + + pub fn tock( + &mut self, + todo_list_list: Vec>>, + dev: &mut Vec>, + ) { + trace!("tock! check deadlock!"); + todo_list_list.iter().for_each(|list| { + list.iter().for_each(|todo| { + if let Ok(ok) = self.urb_request(todo.clone(), dev) + && let Some(sender) = &todo.sender + { + trace!("tock! check deadlock! 2"); + sender.lock().receive_complete_event(ok); + }; + }) + }) + } +} diff --git a/crates/driver_usb/src/host/usb/descriptors/mod.rs b/crates/driver_usb/src/host/usb/descriptors/mod.rs new file mode 100644 index 0000000000..2745f7f321 --- /dev/null +++ b/crates/driver_usb/src/host/usb/descriptors/mod.rs @@ -0,0 +1,160 @@ +use core::{any::Any, ptr}; + +use alloc::{collections::BTreeMap, vec::Vec}; +use axalloc::GlobalNoCacheAllocator; +use desc_configuration::Configuration; +use desc_device::Device; +use desc_endpoint::Endpoint; +use desc_hid::Hid; +use desc_interface::Interface; +use desc_str::Str; +use desc_InterfaceAssociation::InterfaceAssociation; +use log::debug; +use num_derive::{FromPrimitive, ToPrimitive}; +use num_traits::{FromPrimitive, ToPrimitive}; + +use crate::{dma::DMA, OsDep}; + +pub mod desc_configuration; +pub mod desc_device; +pub mod desc_endpoint; +pub mod desc_hid; +pub mod desc_interface; +pub mod desc_str; +pub mod desc_InterfaceAssociation; + +#[derive(Copy, Clone, Debug)] +pub(crate) enum Descriptor { + Device(Device), + Configuration(Configuration), + Str(Str), + Interface(Interface), + Endpoint(Endpoint), + Hid(Hid), + InterfaceAssociation(InterfaceAssociation), +} + +#[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug)] +#[allow(non_camel_case_types)] +pub(crate) enum DescriptorType { + //USB 1.1: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + Device = 1, + Configuration = 2, + String = 3, + Interface = 4, + Endpoint = 5, + // USB 2.0: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + DeviceQualifier = 6, + OtherSpeedConfiguration = 7, + InterfacePower1 = 8, + Hid = 0x21, + HIDReport = 0x22, + HIDPhysical = 0x23, + // USB 3.0+: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + OTG = 0x09, + Debug = 0x0a, + InterfaceAssociation = 0x0b, + Bos = 0x0f, + DeviceCapability = 0x10, + SuperSpeedEndpointCompanion = 0x30, + SuperSpeedPlusIsochEndpointCompanion = 0x31, +} + +#[derive(Debug)] +pub(crate) enum Error { + UnrecognizedType(u8), +} + +pub(crate) struct RawDescriptorParser { + raw: DMA<[u8], O::DMA>, + current: usize, + len: usize, +} + +pub(crate) struct DescriptionTypeIndexPairForControlTransfer { + ty: DescriptorType, + i: u8, +} + +impl Descriptor { + pub(crate) fn from_slice(raw: &[u8]) -> Result { + assert_eq!(raw.len(), raw[0].into()); + match FromPrimitive::from_u8(raw[1]) { + Some(t) => { + let raw: *const [u8] = raw; + match t { + // SAFETY: This operation is safe because the length of `raw` is equivalent to the + // one of the descriptor. + DescriptorType::Device => Ok(Self::Device(unsafe { ptr::read(raw.cast()) })), + DescriptorType::Configuration => { + Ok(Self::Configuration(unsafe { ptr::read(raw.cast()) })) + } + DescriptorType::String => Ok(Self::Str(unsafe { ptr::read(raw.cast()) })), + DescriptorType::Interface => { + Ok(Self::Interface(unsafe { ptr::read(raw.cast()) })) + } + DescriptorType::Endpoint => { + Ok(Self::Endpoint(unsafe { ptr::read(raw.cast()) })) + } + DescriptorType::Hid => Ok(Self::Hid(unsafe { ptr::read(raw.cast()) })), + DescriptorType::InterfaceAssociation => { + Ok(Self::InterfaceAssociation(unsafe{ptr::read(raw.cast())})) + } + other => unimplemented!("please implement descriptor type:{:?}", other), + } + } + None => Err(Error::UnrecognizedType(raw[1])), + } + } +} + +impl RawDescriptorParser +where + O: OsDep, +{ + pub fn new(raw: DMA<[u8], O::DMA>) -> Self { + let len = raw.len(); + + Self { + raw, + current: 0, + len, + } + } + + pub fn parse(&mut self, empty_vec: &mut Vec) { + while self.current < self.len && self.raw[self.current] > 0 { + match self.parse_first_descriptor() { + Ok(t) => empty_vec.push(t), + Err(e) => debug!("Unrecognized USB descriptor: {:?}", e), + } + } + } + + fn parse_first_descriptor(&mut self) -> Result { + let raw = self.cut_raw_descriptor(); + Descriptor::from_slice(&raw) + } + + fn cut_raw_descriptor(&mut self) -> Vec { + let len: usize = self.raw[self.current].into(); + let v = self.raw[self.current..(self.current + len)].to_vec(); + self.current += len; + v + } +} + +impl DescriptorType { + pub(crate) fn forLowBit( + self, + index: u8, + ) -> DescriptionTypeIndexPairForControlTransfer { + DescriptionTypeIndexPairForControlTransfer { ty: self, i: index } + } +} + +impl DescriptionTypeIndexPairForControlTransfer { + pub(crate) fn bits(self) -> u16 { + (self.ty as u16) << 8 | u16::from(self.i) + } +} diff --git a/crates/driver_usb/src/host/xhci/mod.rs b/crates/driver_usb/src/host/xhci/mod.rs new file mode 100644 index 0000000000..84b84c1744 --- /dev/null +++ b/crates/driver_usb/src/host/xhci/mod.rs @@ -0,0 +1,1073 @@ +use crate::{dma::DMA, err::*, OsDep}; +use alloc::{ + borrow::ToOwned, + boxed::Box, + format, + rc::Rc, + vec::{self, Vec}, +}; +use axalloc::global_no_cache_allocator; +use axhal::{cpu::this_cpu_is_bsp, irq::IrqHandler, paging::PageSize, time::{busy_wait_until,busy_wait}}; +use core::{ + alloc::Allocator, + borrow::{Borrow, BorrowMut}, + cell::RefCell, + f64::consts::E, + num::NonZeroUsize, + ops::{Deref, DerefMut}, + sync::atomic::{fence, Ordering}, time::Duration, +}; +use core::{ + cell::{Ref, RefMut}, + iter::Cycle, +}; +use log::*; +use num_traits::FromPrimitive; +use spinlock::SpinNoIrq; +use xhci::{ + context::{EndpointState, EndpointType, Input, InputHandler, Slot, Slot64Byte}, + extended_capabilities::debug::Status, + registers::PortRegisterSet, + ring::trb::{ + command::{ + self, AddressDevice, Allowed, ConfigureEndpoint, EnableSlot, EvaluateContext, Noop, + }, + event::{CommandCompletion, CompletionCode, TransferEvent}, + transfer::{self, DataStage, SetupStage, StatusStage, TransferType}, + }, +}; +use xhci_device::{DescriptorConfiguration, DescriptorInterface, DeviceAttached}; + +pub use xhci::ring::trb::transfer::Direction; +mod registers; +use registers::*; +mod context; +mod event; +pub(crate) mod ring; +pub(crate) mod xhci_device; +use self::{context::*, event::EventRing, ring::Ring}; +use super::{ + usb::{ + self, + descriptors::{self, desc_device, Descriptor, DescriptorType, RawDescriptorParser}, + }, + Controller, USBHostConfig, +}; +use crate::host::device::*; +use alloc::sync::Arc; +use core::mem; +const ARM_IRQ_PCIE_HOST_INTA: usize = 143 + 32; +const XHCI_CONFIG_MAX_EVENTS_PER_INTR: usize = 16; +const TAG: &str = "[XHCI]"; + +// pub static mut drivers: Option>> = None; + +pub struct Xhci +where + O: OsDep, +{ + pub(super) config: USBHostConfig, + max_slots: u8, + max_ports: u8, + max_irqs: u16, + scratchpad_buf_arr: Option>, + cmd: Ring, + event: EventRing, + regs: Registers, + pub dev_ctx: DeviceContextList, +} + +impl Controller for Xhci +where + O: OsDep, +{ + fn new(config: USBHostConfig) -> Result + where + Self: Sized, + { + let mmio_base = config.base_addr; + debug!("{TAG} Base addr: {:?}", mmio_base); + let mut regs = Registers::new_registers(mmio_base); + + // TODO: pcie 未配置,读不出来 + // let version = self.core_mut().regs.capability.hciversion.read_volatile(); + // info!("xhci version: {:x}", version.get()); + let hcsp1 = regs.regs.capability.hcsparams1.read_volatile(); + let max_slots = hcsp1.number_of_device_slots(); + let max_ports = hcsp1.number_of_ports(); + let max_irqs = hcsp1.number_of_interrupts(); + let page_size = regs.regs.operational.pagesize.read_volatile().get(); + debug!( + "{TAG} Max_slots: {}, max_ports: {}, max_irqs: {}, page size: {}", + max_slots, max_ports, max_irqs, page_size + ); + + let dev_ctx = DeviceContextList::new(max_slots, config.os.clone()); + + // Create the command ring with 4096 / 16 (TRB size) entries, so that it uses all of the + // DMA allocation (which is at least a 4k page). + let entries_per_page = O::PAGE_SIZE / mem::size_of::(); + let cmd = Ring::new(config.os.clone(), entries_per_page, true)?; + let event = EventRing::new(config.os.clone())?; + + debug!("{TAG} ring size {}", cmd.len()); + + let mut s = Self { + config, + max_slots, + max_irqs, + max_ports, + scratchpad_buf_arr: None, + cmd, + event, + regs, + dev_ctx, + }; + s.init()?; + info!("{TAG} Init success"); + Ok(s) + } + + fn poll( + &mut self, + arc: Arc>>>, + ) -> Result>> { + let mut port_id_list = Vec::new(); + let port_len = self.regs().port_register_set.len(); + for i in 0..port_len { + let portsc = &self.regs_mut().port_register_set.read_volatile_at(i).portsc; + info!( + "{TAG} Port {}: Enabled: {}, Connected: {}, Speed {}, Power {}", + i, + portsc.port_enabled_disabled(), + portsc.current_connect_status(), + portsc.port_speed(), + portsc.port_power() + ); + + if !portsc.port_enabled_disabled() { + continue; + } + + port_id_list.push(i); + } + let mut device_list = Vec::new(); + for port_idx in port_id_list { + let port_id = port_idx + 1; + let slot = self.device_slot_assignment()?; + let mut device = self.dev_ctx.new_slot( + slot as usize, + 0, + port_id, + 32, + self.config.os.clone(), + arc.clone(), + )?; + debug!("assign complete!"); + self.address_device(&device)?; + + self.print_context(&device); + + let packet_size0 = self.fetch_package_size0(&device)?; + + debug!("packet_size0: {}", packet_size0); + + self.set_ep0_packet_size(&device, packet_size0); + let desc = self.fetch_device_desc(&device)?; + let vid = desc.vendor; + let pid = desc.product_id; + debug!("desc's buffer is:{:?}",desc); + info!("device found, pid: {pid:#X}, vid: {vid:#X}"); + + device.device_desc = desc; + + for i in 0..device.device_desc.num_configurations { + let config = self.fetch_config_desc(&device, i)?; + debug!("{:#?}", config); + device.configs.push(config) + } + + self.set_configuration(&device, 0)?; + debug!("====================================="); + device_list.push(device); + } + Ok(device_list) + } + + fn post_cmd(&mut self, mut trb: command::Allowed) -> Result { + let addr = self.cmd.enque_command(trb); + + self.regs_mut().doorbell.update_volatile_at(0, |r| { + r.set_doorbell_stream_id(0); + r.set_doorbell_target(0); + }); + + fence(Ordering::Release); + + let r = self.event_busy_wait_cmd(addr as _)?; + + /// update erdp + self.regs_mut() + .interrupter_register_set + .interrupter_mut(0) + .erdp + .update_volatile(|f| { + f.set_event_ring_dequeue_pointer(self.event.erdp()); + }); + + Ok(r) + } + fn post_transfer( + &mut self, + setup: SetupStage, + data: Option, + status: StatusStage, + device: &DeviceAttached, + dci: u8, + ) -> Result { + let mut trbs: Vec = Vec::new(); + trbs.push(setup.into()); + if let Some(data) = data { + trbs.push(data.into()); + } + trbs.push(status.into()); + let mut trb_pointers = Vec::new(); + { + let ring = self.ep_ring_mut(device, dci); + + for trb in &mut trbs { + if ring.cycle { + trb.set_cycle_bit(); + } else { + trb.clear_cycle_bit(); + } + + trb_pointers.push(ring.enque_trb(trb.into_raw())); + } + } + if trb_pointers.len() == 2 { + debug!( + "[Transfer] >> setup@{:#X}, status@{:#X}", + trb_pointers[0], trb_pointers[1] + ); + } else { + debug!( + "[Transfer] >> setup@{:#X}, data@{:#X}, status@{:#X}", + trb_pointers[0], trb_pointers[1], trb_pointers[2] + ); + } + + fence(Ordering::Release); + self.regs_mut() + .doorbell + .update_volatile_at(device.slot_id, |r| { + r.set_doorbell_target(dci); + }); + + let r = self.event_busy_wait_transfer(*trb_pointers.last().unwrap() as _)?; + Ok(()) + } + + fn post_transfer_normal( + &mut self, + data: &mut [u8], + device: &DeviceAttached, + dci: u8, + ) -> Result { + let len = data.len(); + let mut buffer = DMA::new_vec(0u8, len, O::PAGE_SIZE, self.config.os.dma_alloc()); + buffer.copy_from_slice(data); + let mut request = transfer::Normal::default(); + request + .set_data_buffer_pointer(buffer.addr() as u64) + .set_trb_transfer_length(len as _) + .set_interrupt_on_completion(); + + let ring = self.ep_ring_mut(device, dci); + let addr = ring.enque_trb(transfer::Allowed::Normal(request).into_raw()); + + fence(Ordering::Release); + + self.regs_mut() + .doorbell + .update_volatile_at(device.slot_id, |r| { + r.set_doorbell_target(dci); + }); + + self.event_busy_wait_transfer(addr as _)?; + + data.copy_from_slice(&buffer); + + Ok(()) + } +} + +impl Xhci +where + O: OsDep, +{ + fn init(&mut self) -> Result { + self.chip_hardware_reset()?; + self.set_max_device_slots()?; + self.set_dcbaap()?; + self.set_cmd_ring()?; + self.init_ir()?; + + self.setup_scratchpads(); + self.start()?; + + self.test_cmd()?; + self.reset_ports(); + Ok(()) + } + + fn test_cmd(&mut self) -> Result { + debug!("{TAG} Test command ring"); + for _ in 0..3 { + let completion = self.post_cmd(Allowed::Noop(Noop::new()))?; + } + debug!("{TAG} Command ring ok"); + Ok(()) + } + fn check_slot(&self, slot: u8) -> Result { + if slot > self.max_slots { + return Err(Error::Param(format!( + "slot {} > max {}", + slot, self.max_slots + ))); + } + Ok(()) + } + + fn print_context(&self, device: &DeviceAttached) { + let dev = &self.dev_ctx.device_out_context_list[device.slot_id]; + debug!("slot {} {:?}", device.slot_id, dev.slot().slot_state()); + for i in 1..32 { + if let EndpointState::Disabled = dev.endpoint(i).endpoint_state() { + continue; + } + debug!(" ep dci {}: {:?}", i, dev.endpoint(i).endpoint_state()); + } + } + fn device_slot_assignment(&mut self) -> Result { + // enable slot + let mut cmd = EnableSlot::new(); + let slot_type = { + // TODO: PCI未初始化,读不出来 + // let mut regs = self.regs.lock(); + // match regs.supported_protocol(port) { + // Some(p) => p.header.read_volatile().protocol_slot_type(), + // None => { + // warn!( + // "{TAG} Failed to find supported protocol information for port {}", + // port + // ); + // 0 + // } + // } + 0 + }; + cmd.set_slot_type(slot_type); + + let cmd = Allowed::EnableSlot(EnableSlot::new()); + + let result = self.post_cmd(cmd)?; + + let slot_id = result.slot_id(); + debug!("new slot id: {slot_id}"); + // self.dev_ctx.new_slot(slot_id as usize, 0, port_idx, 16).unwrap(); //assume 16 + Ok(slot_id) + } + + fn append_port_to_route_string(route_string: u32, port_id: usize) -> u32 { + let mut route_string = route_string; + for tier in 0..5 { + if route_string & (0x0f << (tier * 4)) == 0 { + if tier < 5 { + route_string |= (port_id as u32) << (tier * 4); + return route_string; + } + } + } + + route_string + } + + pub fn address_device(&mut self, device: &DeviceAttached) -> Result { + let slot_id = device.slot_id; + let port_idx = device.port_id - 1; + let port_speed = self.get_speed(port_idx); + let max_packet_size = self.get_default_max_packet_size(port_idx); + let dci = 1; + + let transfer_ring_0_addr = self.ep_ring_mut(device, dci).register(); + let ring_cycle_bit = self.ep_ring_mut(device, dci).cycle; + let context_addr = { + let context_mut = self + .dev_ctx + .device_input_context_list + .get_mut(slot_id) + .unwrap() + .deref_mut(); + + let control_context = context_mut.control_mut(); + control_context.set_add_context_flag(0); + control_context.set_add_context_flag(1); + for i in 2..32 { + control_context.clear_drop_context_flag(i); + } + + let slot_context = context_mut.device_mut().slot_mut(); + slot_context.clear_multi_tt(); + slot_context.clear_hub(); + slot_context.set_route_string(Self::append_port_to_route_string(0, device.port_id)); // for now, not support more hub ,so hardcode as 0.//TODO: generate route string + slot_context.set_context_entries(1); + slot_context.set_max_exit_latency(0); + slot_context.set_root_hub_port_number(device.port_id as _); //todo: to use port number + slot_context.set_number_of_ports(0); + slot_context.set_parent_hub_slot_id(0); + slot_context.set_tt_think_time(0); + slot_context.set_interrupter_target(0); + slot_context.set_speed(port_speed); + + let endpoint_0 = context_mut.device_mut().endpoint_mut(dci as _); + endpoint_0.set_endpoint_type(xhci::context::EndpointType::Control); + endpoint_0.set_max_packet_size(max_packet_size); + endpoint_0.set_max_burst_size(0); + endpoint_0.set_error_count(3); + endpoint_0.set_tr_dequeue_pointer(transfer_ring_0_addr); + if ring_cycle_bit { + endpoint_0.set_dequeue_cycle_state(); + } else { + endpoint_0.clear_dequeue_cycle_state(); + } + endpoint_0.set_interval(0); + endpoint_0.set_max_primary_streams(0); + endpoint_0.set_mult(0); + endpoint_0.set_error_count(3); + + (context_mut as *const Input<16>).addr() as u64 + }; + + fence(Ordering::Release); + + let result = self.post_cmd(Allowed::AddressDevice( + *AddressDevice::new() + .set_slot_id(slot_id as _) + .set_input_context_pointer(context_addr), + ))?; + + debug!("address slot [{}] ok", slot_id); + + Ok(()) + } + fn setup_scratchpads(&mut self) { + let scratchpad_buf_arr = { + let buf_count = { + let count = self + .regs() + .capability + .hcsparams2 + .read_volatile() + .max_scratchpad_buffers(); + debug!("{TAG} Scratch buf count: {}", count); + count + }; + if buf_count == 0 { + return; + } + let scratchpad_buf_arr = ScratchpadBufferArray::new(buf_count, self.config.os.clone()); + + self.dev_ctx.dcbaa[0] = scratchpad_buf_arr.register() as u64; + + debug!( + "{TAG} Setting up {} scratchpads, at {:#0x}", + buf_count, + scratchpad_buf_arr.register() + ); + scratchpad_buf_arr + }; + + self.scratchpad_buf_arr = Some(scratchpad_buf_arr); + } + + fn ep_ring_mut(&mut self, device: &DeviceAttached, dci: u8) -> &mut Ring { + &mut self.dev_ctx.transfer_rings[device.slot_id][dci as usize - 1] + } + fn ep_ring(&self, device: &DeviceAttached, dci: u8) -> &Ring { + &self.dev_ctx.transfer_rings[device.slot_id][dci as usize - 1] + } + fn control_transfer( + &mut self, + dev: &DeviceAttached, + dci: u8, + buffer: Option<&DMA>, + request_type: u8, + request: u8, + value: u16, + index: u16, + direction: Direction, + ) -> Result { + let transfer_type = if buffer.is_some() { + match direction { + Direction::Out => TransferType::Out, + Direction::In => TransferType::In, + } + } else { + TransferType::No + }; + + let mut len = 0; + let data = if let Some(buffer) = buffer { + let mut data = transfer::DataStage::default(); + len = buffer.length_for_bytes(); + data.set_data_buffer_pointer(buffer.addr() as u64) + .set_trb_transfer_length(len as _) + .set_direction(direction); + Some(data) + } else { + None + }; + let mut setup = transfer::SetupStage::default(); + setup + .set_request_type(request_type) + .set_request(request) + .set_value(value) + .set_index(index) + .set_length(len as _) + .set_transfer_type(transfer_type); + + debug!("{:#?}", setup); + + let mut status = transfer::StatusStage::default(); + + status.set_interrupt_on_completion(); + + self.post_transfer(setup, data, status, dev, dci)?; + + Ok(()) + } + + fn update_erdp(&mut self) { + self.regs_mut() + .interrupter_register_set + .interrupter_mut(0) + .erdp + .update_volatile(|f| { + f.set_event_ring_dequeue_pointer(self.event.erdp()); + }); + } + + fn event_busy_wait_transfer(&mut self, addr: u64) -> Result { + debug!("Wait result @{addr:#X}"); + loop { + busy_wait(Duration::from_millis(10)); + if let Some((event, cycle)) = self.event.next() { + self.update_erdp(); + + match event { + xhci::ring::trb::event::Allowed::TransferEvent(c) => { + let code = c.completion_code().unwrap(); + debug!( + "[Transfer] << {code:#?} @{:#X} got result, cycle {}, len {}", + c.trb_pointer(), + c.cycle_bit(), + c.trb_transfer_length() + ); + debug!("trb is:{:?}",c); + if c.trb_pointer() != addr { + debug!(" @{:#X} != @{:#X}", c.trb_pointer(), addr); + // return Err(Error::Pip); + continue; + } + if CompletionCode::Success == code || CompletionCode::ShortPacket == code { + return Ok(c); + } + return Err(Error::CMD(code)); + } + _ => warn!("event: {:?}", event), + } + } + } + } + fn event_busy_wait_cmd(&mut self, addr: u64) -> Result { + debug!("Wait result"); + loop { + if let Some((event, cycle)) = self.event.next() { + match event { + xhci::ring::trb::event::Allowed::CommandCompletion(c) => { + let mut code = CompletionCode::Invalid; + if let Ok(c) = c.completion_code() { + code = c; + } else { + continue; + } + debug!( + "[CMD] << {code:#?} @{:X} got result, cycle {}", + c.command_trb_pointer(), + c.cycle_bit() + ); + if c.command_trb_pointer() != addr { + continue; + } + + if let CompletionCode::Success = code { + return Ok(c); + } + return Err(Error::CMD(code)); + } + _ => warn!("event: {:?}", event), + } + } + } + } + + fn regs(&self) -> &RegistersBase { + &self.regs.regs + } + + fn regs_mut(&mut self) -> &mut RegistersBase { + &mut self.regs.regs + } + + fn chip_hardware_reset(&mut self) -> Result { + debug!("{TAG} Reset begin"); + debug!("{TAG} Stop"); + + self.regs_mut().operational.usbcmd.update_volatile(|c| { + c.clear_run_stop(); + }); + debug!("{TAG} Until halt"); + while !self.regs().operational.usbsts.read_volatile().hc_halted() {} + debug!("{TAG} Halted"); + + let mut o = &mut self.regs_mut().operational; + // debug!("xhci stat: {:?}", o.usbsts.read_volatile()); + + debug!("{TAG} Wait for ready..."); + while o.usbsts.read_volatile().controller_not_ready() {} + debug!("{TAG} Ready"); + + o.usbcmd.update_volatile(|f| { + f.set_host_controller_reset(); + }); + + while o.usbcmd.read_volatile().host_controller_reset() {} + + debug!("{TAG} Reset HC"); + + while self + .regs() + .operational + .usbcmd + .read_volatile() + .host_controller_reset() + || self + .regs() + .operational + .usbsts + .read_volatile() + .controller_not_ready() + {} + + info!("{TAG} XCHI reset ok"); + Ok(()) + } + + fn set_max_device_slots(&mut self) -> Result { + let max_slots = self.max_slots; + debug!("{TAG} Setting enabled slots to {}.", max_slots); + self.regs_mut().operational.config.update_volatile(|r| { + r.set_max_device_slots_enabled(max_slots); + }); + Ok(()) + } + + fn set_dcbaap(&mut self) -> Result { + let dcbaap = self.dev_ctx.dcbaap(); + debug!("{TAG} Writing DCBAAP: {:X}", dcbaap); + self.regs_mut().operational.dcbaap.update_volatile(|r| { + r.set(dcbaap as u64); + }); + Ok(()) + } + + fn set_cmd_ring(&mut self) -> Result { + let crcr = self.cmd.register(); + let cycle = self.cmd.cycle; + + let regs = self.regs_mut(); + + debug!("{TAG} Writing CRCR: {:X}", crcr); + regs.operational.crcr.update_volatile(|r| { + r.set_command_ring_pointer(crcr); + if cycle { + r.set_ring_cycle_state(); + } else { + r.clear_ring_cycle_state(); + } + }); + + Ok(()) + } + + fn start(&mut self) -> Result { + let regs = self.regs_mut(); + debug!("{TAG} Start run"); + regs.operational.usbcmd.update_volatile(|r| { + r.set_run_stop(); + }); + + while regs.operational.usbsts.read_volatile().hc_halted() {} + + info!("{TAG} Is running"); + + regs.doorbell.update_volatile_at(0, |r| { + r.set_doorbell_stream_id(0); + r.set_doorbell_target(0); + }); + + Ok(()) + } + + fn init_ir(&mut self) -> Result { + debug!("{TAG} Disable interrupts"); + let regs = &mut self.regs.regs; + + regs.operational.usbcmd.update_volatile(|r| { + r.clear_interrupter_enable(); + }); + + let mut ir0 = regs.interrupter_register_set.interrupter_mut(0); + { + debug!("{TAG} Writing ERSTZ"); + ir0.erstsz.update_volatile(|r| r.set(1)); + + let erdp = self.event.erdp(); + debug!("{TAG} Writing ERDP: {:X}", erdp); + + ir0.erdp.update_volatile(|r| { + r.set_event_ring_dequeue_pointer(erdp); + }); + + let erstba = self.event.erstba(); + debug!("{TAG} Writing ERSTBA: {:X}", erstba); + + ir0.erstba.update_volatile(|r| { + r.set(erstba); + }); + ir0.imod.update_volatile(|im| { + im.set_interrupt_moderation_interval(0); + im.set_interrupt_moderation_counter(0); + }); + + debug!("{TAG} Enabling primary interrupter."); + ir0.iman.update_volatile(|im| { + im.set_interrupt_enable(); + }); + } + + // }; + + // self.setup_scratchpads(buf_count); + + Ok(()) + } + + fn get_speed(&self, port: usize) -> u8 { + self.regs() + .port_register_set + .read_volatile_at(port) + .portsc + .port_speed() + } + + fn get_default_max_packet_size(&self, port: usize) -> u16 { + match self.get_speed(port) { + 1 | 3 => 64, + 2 => 8, + 4 => 512, + v => unimplemented!("PSI: {}", v), + } + } + + fn reset_cic(&mut self) { + let regs = self.regs_mut(); + let cic = regs + .capability + .hccparams2 + .read_volatile() + .configuration_information_capability(); + regs.operational.config.update_volatile(|r| { + if cic { + r.set_configuration_information_enable(); + } else { + r.clear_configuration_information_enable(); + } + }); + } + + fn reset_ports(&mut self) { + let regs = self.regs_mut(); + let port_len = regs.port_register_set.len(); + + for i in 0..port_len { + debug!("{TAG} Port {} start reset", i,); + regs.port_register_set.update_volatile_at(i, |port| { + port.portsc.set_0_port_enabled_disabled(); + port.portsc.set_port_reset(); + }); + + while regs + .port_register_set + .read_volatile_at(i) + .portsc + .port_reset() + {} + + debug!("{TAG} Port {} reset ok", i); + } + } + + fn fetch_device_desc( + &mut self, + dev: &DeviceAttached, + ) -> Result { + let mut buffer = DMA::new_singleton_page4k( + descriptors::desc_device::Device::default(), + self.config.os.dma_alloc(), + ); + self.control_transfer( + dev, + 1, + Some(&mut buffer), + 0x80, + 6, + DescriptorType::Device.forLowBit(0).bits(), + 0, + Direction::In, + )?; + + Ok(buffer.clone()) + } + fn fetch_package_size0(&mut self, dev: &DeviceAttached) -> Result { + let mut buffer = DMA::new_vec(0u8, 8, 64, self.config.os.dma_alloc()); + self.control_transfer( + dev, + 1, + Some(&mut buffer), + 0x80, + 6, + DescriptorType::Device.forLowBit(0).bits(), + 0, + Direction::In, + )?; + let mut data = [0u8; 18]; + data[..8].copy_from_slice(&buffer); + + if let Ok(descriptors::Descriptor::Device(dev)) = descriptors::Descriptor::from_slice(&data) + { + return Ok(dev.max_packet_size()); + } + Ok(8) + } + fn fetch_config_desc( + &mut self, + dev: &DeviceAttached, + index: u8, + ) -> Result { + let mut buffer = DMA::new_vec( + 0u8, + PageSize::Size4K.into(), + PageSize::Size4K.into(), + self.config.os.dma_alloc(), + ); + self.control_transfer( + dev, + 1, + Some(&mut buffer), + 0x80, + 6, + DescriptorType::Configuration.forLowBit(index).bits(), + 0, + Direction::In, + )?; + + let mut config = None; + let mut offset = 0; + + while offset < buffer.length_for_bytes() { + let len = buffer[offset] as usize; + if len == 0 { + break; + } + + let raw = &buffer[offset..offset + len]; + offset += len; + if let Ok(desc) = Descriptor::from_slice(raw) { + match desc { + Descriptor::Configuration(c) => { + if config.is_some() { + break; + } + config = Some(DescriptorConfiguration { + data: c, + interfaces: Vec::new(), + }) + } + Descriptor::Interface(i) => { + if let Some(config) = &mut config { + config.interfaces.push(DescriptorInterface { + data: i, + endpoints: Vec::new(), + }) + } + } + Descriptor::Endpoint(e) => { + if let Some(config) = &mut config { + if let Some(interface) = config.interfaces.last_mut() { + interface.endpoints.push(e); + } + } + } + _ => debug!("{:#?}", desc), + } + } else { + break; + } + } + + match config { + Some(config) => Ok(config), + None => Err(Error::Unknown(format!("config not found"))), + } + } + + fn set_ep0_packet_size(&mut self, dev: &DeviceAttached, max_packet_size: u16) -> Result { + let addr = { + let input = self.dev_ctx.device_input_context_list[dev.port_id as usize].deref_mut(); + input + .device_mut() + .endpoint_mut(1) //dci=1: endpoint 0 + .set_max_packet_size(max_packet_size); + + debug!( + "CMD: evaluating context for set endpoint0 packet size {}", + max_packet_size + ); + (input as *mut Input<16>).addr() as u64 + }; + self.post_cmd(Allowed::EvaluateContext( + *EvaluateContext::default() + .set_slot_id(dev.slot_id as _) + .set_input_context_pointer(addr), + ))?; + + Ok(()) + } + + fn set_configuration(&mut self, device: &DeviceAttached, config_idx: usize) -> Result { + let config = &device.configs[config_idx]; + let config_val = config.data.config_val(); + let interface = device.current_interface(); + let input_addr = { + { + let input = self.dev_ctx.device_input_context_list[device.slot_id].deref_mut(); + { + let control_mut = input.control_mut(); + control_mut.set_add_context_flag(0); + control_mut.set_configuration_value(config_val); + + control_mut.set_interface_number(interface.data.interface_number); + control_mut.set_alternate_setting(interface.data.alternate_setting); + } + let mut entries = 1; + if let Some(config) = device.configs.last() { + if let Some(interface) = config.interfaces.last() { + if let Some(ep) = interface.endpoints.last() { + entries = ep.doorbell_value_aka_dci(); + } + } + } + + input + .device_mut() + .slot_mut() + .set_context_entries(entries as u8); + } + for ep in &interface.endpoints { + let dci = ep.doorbell_value_aka_dci() as usize; + let max_packet_size = ep.max_packet_size; + let ring_addr = self.ep_ring(device, dci as _).register(); + + let input = self.dev_ctx.device_input_context_list[device.slot_id].deref_mut(); + let control_mut = input.control_mut(); + debug!("init ep {} {:?}", dci, ep.endpoint_type()); + control_mut.set_add_context_flag(dci); + let ep_mut = input.device_mut().endpoint_mut(dci); + ep_mut.set_interval(3); + ep_mut.set_endpoint_type(ep.endpoint_type()); + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut.set_max_packet_size(max_packet_size); + ep_mut.set_error_count(3); + ep_mut.set_dequeue_cycle_state(); + let endpoint_type = ep.endpoint_type(); + match endpoint_type { + EndpointType::Control => {} + EndpointType::BulkOut | EndpointType::BulkIn => { + ep_mut.set_max_burst_size(0); + ep_mut.set_max_primary_streams(0); + } + EndpointType::IsochOut + | EndpointType::IsochIn + | EndpointType::InterruptOut + | EndpointType::InterruptIn => { + //init for isoch/interrupt + ep_mut.set_max_packet_size(max_packet_size & 0x7ff); //refer xhci page 162 + ep_mut.set_max_burst_size( + ((max_packet_size & 0x1800) >> 11).try_into().unwrap(), + ); + ep_mut.set_mult(0); //always 0 for interrupt + + if let EndpointType::IsochOut | EndpointType::IsochIn = endpoint_type { + ep_mut.set_error_count(0); + } + + ep_mut.set_tr_dequeue_pointer(ring_addr); + ep_mut.set_max_endpoint_service_time_interval_payload_low(4); + //best guess? + } + EndpointType::NotValid => unreachable!("Not Valid Endpoint should not exist."), + } + } + + let input = self.dev_ctx.device_input_context_list[device.slot_id].deref_mut(); + (input as *const Input<16>).addr() as u64 + }; + + self.post_cmd(Allowed::ConfigureEndpoint( + *ConfigureEndpoint::default() + .set_slot_id(device.slot_id as _) + .set_input_context_pointer(input_addr), + ))?; + + self.print_context(&device); + + // debug!("set config {}", config_val); + // self.control_transfer::(device, 1, None, 0, 0x09, config_val as _, 0, Direction::Out)?; + + // debug!("set interface {}", interface.data.interface); + // self.control_transfer::( + // device, + // 1, + // None, + // 1, + // 0x09, + // interface.data.alternate_setting as _, + // interface.data.interface_number as _, + // Direction::Out, + // )?; + + Ok(()) + } +} diff --git a/crates/driver_usb/src/lib.rs b/crates/driver_usb/src/lib.rs new file mode 100644 index 0000000000..eddc4a8153 --- /dev/null +++ b/crates/driver_usb/src/lib.rs @@ -0,0 +1,309 @@ +#![no_std] +#![feature(allocator_api)] +#![feature(strict_provenance)] +#![allow(warnings)] +#![feature(auto_traits)] +#![feature(btreemap_alloc)] +#![feature(if_let_guard)] +#![feature(get_many_mut)] +#![feature(let_chains)] +#![feature(cfg_match)] +#![feature(iter_collect_into)] +#![feature(const_trait_impl)] + +use core::{mem::MaybeUninit, usize}; + +use abstractions::{dma::DMA, PlatformAbstractions}; +use alloc::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + sync::Arc, + vec::Vec, +}; +use glue::driver_independent_device_instance::DriverIndependentDeviceInstance; +use host::{data_structures::MightBeInited, USBHostSystem}; +use log::{error, trace}; +use spinlock::SpinNoIrq; +use usb::{ + descriptors::{ + construct_control_transfer_type, parser::RawDescriptorParser, + topological_desc::TopologicalUSBDescriptorRoot, USBStandardDescriptorTypes, + }, + operation, + trasnfer::control::{bmRequestType, ControlTransfer, DataTransferType, StandardbRequest}, + urb::{RequestedOperation, URB}, + USBDriverSystem, +}; +use xhci::ring::trb::transfer::{Direction, TransferType}; + +extern crate alloc; + +pub mod abstractions; +pub mod err; +pub mod glue; +pub mod host; +pub mod usb; + +#[derive(Clone, Debug)] +pub struct USBSystemConfig +where + O: PlatformAbstractions, +{ + pub(crate) base_addr: O::VirtAddr, + pub(crate) irq_num: u32, + pub(crate) irq_priority: u32, + pub(crate) os: O, +} + +pub struct USBSystem<'a, O> +where + O: PlatformAbstractions, +{ + platform_abstractions: O, + config: Arc>>, + host_driver_layer: USBHostSystem, + usb_driver_layer: USBDriverSystem<'a, O>, + driver_independent_devices: Vec>, +} + +impl<'a, O> USBSystem<'a, O> +where + O: PlatformAbstractions + 'static, +{ + pub fn new(config: USBSystemConfig) -> Self { + let config = Arc::new(SpinNoIrq::new(config)); + Self { + config: config.clone(), + platform_abstractions: config.clone().lock().os.clone(), + host_driver_layer: USBHostSystem::new(config.clone()).unwrap(), + usb_driver_layer: USBDriverSystem::new(config.clone()), + driver_independent_devices: Vec::new(), + } + } + + pub fn init(mut self) -> Self { + trace!("initializing!"); + self.host_driver_layer.init(); + self.usb_driver_layer.init(); + trace!("usb system init complete"); + self + } + + pub fn init_probe(mut self) -> Self { + // async { //todo:async it! + { + self.driver_independent_devices.clear(); //need to have a merge algorithm for hot plug + let mut after = Vec::new(); + self.host_driver_layer.probe(|device| after.push(device)); + + for driver in after { + self.new_device(driver) + } + trace!("device probe complete"); + } + { + let mut preparing_list = Vec::new(); + self.usb_driver_layer + .init_probe(&mut self.driver_independent_devices, &mut preparing_list); + + //probe driver modules and load them + self.host_driver_layer + .tock(preparing_list, &mut self.driver_independent_devices); + + //and do some prepare stuff + } + // } + // .await; + + self + } + + pub fn init_probe1(mut self) -> Self { + // async { //todo:async it! + { + self.driver_independent_devices.clear(); //need to have a merge algorithm for hot plug + let mut after = Vec::new(); + self.host_driver_layer.probe(|device| after.push(device)); + + for driver in after { + self.new_device(driver) + } + trace!("device probe complete"); + } + { + let mut preparing_list = Vec::new(); + self.usb_driver_layer + .init_probe1(&mut self.driver_independent_devices, &mut preparing_list); + + //probe driver modules and load them + self.host_driver_layer + .tock(preparing_list, &mut self.driver_independent_devices); + + //and do some prepare stuff + } + // } + // .await; + + self + } + + pub fn driver_active(mut self) -> Self { + self + } + + pub fn drive_all(mut self) -> Self { + //TODO: Drive All + + loop { + let tick = self.usb_driver_layer.tick(); + if tick.len() != 0 { + trace!("tick! {:?}", tick.len()); + self.host_driver_layer + .tock(tick, &mut self.driver_independent_devices); + } + // trace!("tock!"); + } + self + } + + pub fn drive_all1(mut self) -> Self { + //TODO: Drive All + + loop { + let tick = self.usb_driver_layer.tick1(); + if tick.len() != 0 { + trace!("tick! {:?}", tick.len()); + self.host_driver_layer + .tock(tick, &mut self.driver_independent_devices); + } + // trace!("tock!"); + } + self + } + + pub fn drive_all2(mut self) -> Self { + //TODO: Drive All + + loop { + let tick = self.usb_driver_layer.tick2(); + if tick.len() != 0 { + trace!("tick! {:?}", tick.len()); + self.host_driver_layer + .tock(tick, &mut self.driver_independent_devices); + } + // trace!("tock!"); + } + self + } + + pub fn drop_device(&mut self, mut driver_independent_device_slot_id: usize) { + //do something + } + + pub fn new_device(&mut self, mut driver: DriverIndependentDeviceInstance) { + 'label: { + if let MightBeInited::Uninit = *driver.descriptors { + let buffer_device = DMA::new_vec( + 0u8, + O::PAGE_SIZE, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ); + + let desc = match (&driver.controller).lock().control_transfer( + driver.slotid, + ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Standard, + usb::trasnfer::control::Recipient::Device, + ), + request: StandardbRequest::GetDescriptor.into(), + index: 0, + value: construct_control_transfer_type( + USBStandardDescriptorTypes::Device as u8, + 0, + ) + .bits(), + data: Some(buffer_device.addr_len_tuple()), + }, + ) { + Ok(_) => { + let mut parser = RawDescriptorParser::::new(buffer_device); + parser.single_state_cycle(); + let num_of_configs = parser.num_of_configs(); + for index in 0..num_of_configs { + let buffer = DMA::new_vec( + 0u8, + O::PAGE_SIZE, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ); + (&driver.controller) + .lock() + .control_transfer( + driver.slotid, + ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Standard, + usb::trasnfer::control::Recipient::Device, + ), + request: StandardbRequest::GetDescriptor.into(), + index: 0, + value: construct_control_transfer_type( + USBStandardDescriptorTypes::Configuration as u8, + index as _, + ) + .bits(), + data: Some(buffer.addr_len_tuple()), + }, + ) + .inspect(|_| { + parser.append_config(buffer); + }); + } + driver.descriptors = Arc::new(MightBeInited::Inited(parser.summarize())); + } + Err(err) => { + error!("err! {:?}", err); + break 'label; + } + }; + } + + trace!("parsed descriptor:{:#?}", driver.descriptors); + + if let MightBeInited::Inited(TopologicalUSBDescriptorRoot { + device: devices, + others, + metadata, + }) = &*driver.descriptors + { + self.host_driver_layer + .urb_request( + URB::new( + driver.slotid, + RequestedOperation::ConfigureDevice( + operation::Configuration::SetupDevice( + //TODO: fixme + devices.first().unwrap().child.first().unwrap(), + ), + ), + ), + &mut self.driver_independent_devices, + ) + .unwrap(); + }; + + self.driver_independent_devices.push(driver); + trace!( + "pushed new device! {:?}", + self.driver_independent_devices.len() + ) + } + //do something + } +} + +// #[cfg(feature = "arceos")] +// pub mod ax; diff --git a/crates/driver_usb/src/usb/descriptors/desc_InterfaceAssociation.rs b/crates/driver_usb/src/usb/descriptors/desc_InterfaceAssociation.rs new file mode 100644 index 0000000000..d770cb8f99 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_InterfaceAssociation.rs @@ -0,0 +1,3 @@ +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct InterfaceAssociation {} diff --git a/crates/driver_usb/src/usb/descriptors/desc_configuration.rs b/crates/driver_usb/src/usb/descriptors/desc_configuration.rs new file mode 100644 index 0000000000..f86fe6f90f --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_configuration.rs @@ -0,0 +1,38 @@ +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub(crate) struct Configuration { + length: u8, + ty: u8, + total_length: u16, + num_interfaces: u8, + config_val: u8, + config_string: u8, + attributes: u8, + max_power: u8, +} +impl Configuration { + pub(crate) fn config_val(&self) -> u8 { + self.config_val + } + pub(crate) fn length(&self) -> u8 { + self.length + } + pub(crate) fn ty(&self) -> u8 { + self.ty + } + pub(crate) fn total_length(&self) -> u16 { + self.total_length + } + pub(crate) fn num_interfaces(&self) -> u8 { + self.num_interfaces + } + pub(crate) fn config_string(&self) -> u8 { + self.config_string + } + pub(crate) fn attributes(&self) -> u8 { + self.attributes + } + pub(crate) fn max_power(&self) -> u8 { + self.max_power + } +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_device.rs b/crates/driver_usb/src/usb/descriptors/desc_device.rs new file mode 100644 index 0000000000..2c23e2b6c4 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_device.rs @@ -0,0 +1,78 @@ +use const_enum::ConstEnum; + +#[derive(Copy, Clone, Default, Debug)] +#[repr(C, packed)] +pub(crate) struct Device { + pub len: u8, + pub descriptor_type: u8, + pub cd_usb: u16, + pub class: u8, + pub subclass: u8, + pub protocol: u8, + pub max_packet_size0: u8, + pub vendor: u16, + pub product_id: u16, + pub device: u16, + pub manufacture: u8, + pub product: u8, + pub serial_number: u8, + pub num_configurations: u8, +} +impl Device { + pub(crate) fn max_packet_size(&self) -> u16 { + if let (3, _) = self.version() { + 2_u16.pow(self.max_packet_size0.into()) + } else { + self.max_packet_size0.into() + } + } + + fn version(&self) -> (u8, u8) { + let cd_usb = self.cd_usb; + + ( + (cd_usb >> 8).try_into().unwrap(), + (cd_usb & 0xff).try_into().unwrap(), + ) + } +} + +#[derive(ConstEnum, Copy, Clone, Debug)] +#[repr(u8)] +pub enum StandardUSBDeviceClassCode { + ReferInterfaceDescriptor = 0x00, + Audio = 0x01, + CommunicationsAndCDCControl = 0x02, + HID = 0x03, + Physical = 0x05, + Image = 0x06, + Printer = 0x07, + MassStorage = 0x08, + Hub = 0x09, + CDCData = 0x0A, + SmartCard = 0x0B, + ContentSecurity = 0x0D, + Video = 0x0E, + PersonalHealthcare = 0x0F, + AudioVideoDevices = 0x10, + BillboardDeviceClass = 0x11, + USBTypeCBridge = 0x12, + DiagnosticDevice = 0xDC, + WirelessController = 0xE0, + Miscellaneous = 0xEF, + ApplicationSpecific = 0xFE, + VendorSpecific = 0xFF, +} + +// #[derive(Copy, Clone, Debug, ConstEnum)] +// #[repr(u8)] +// pub enum StandardUSBDeviceSubClassCode { +// Common = 0x02, +// Any = 0x03, +// } + +// #[derive(ConstEnum, Copy, Clone, Debug)] +// #[repr(u8)] +// pub enum StandardUSBDeviceProtocol { +// ReferInterfaceAssociationDescriptor = 0x01, +// } diff --git a/crates/driver_usb/src/usb/descriptors/desc_endpoint.rs b/crates/driver_usb/src/usb/descriptors/desc_endpoint.rs new file mode 100644 index 0000000000..a16b51d3f1 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_endpoint.rs @@ -0,0 +1,107 @@ +use bit_field::BitField; +use num_traits::FromPrimitive; +use xhci::context::EndpointType; + +use super::PortSpeed; + +#[derive(Copy, Clone, Default, Debug)] +#[repr(C, packed)] +pub(crate) struct Endpoint { + len: u8, + descriptor_type: u8, + pub(crate) endpoint_address: u8, + pub(crate) attributes: u8, + pub(crate) max_packet_size: u16, + pub(crate) interval: u8, + pub(crate) ssc: Option, +} + +#[derive(Clone, Copy, Debug)] +#[repr(C, packed)] +pub struct SuperSpeedCmp { + pub kind: u8, + pub max_burst: u8, + pub attributes: u8, + pub bytes_per_interval: u16, +} + +impl Endpoint { + pub(crate) fn endpoint_type(&self) -> EndpointType { + EndpointType::from_u8(if self.attributes == 0 { + 4 + } else { + self.attributes.get_bits(0..=1) + + if self.endpoint_address.get_bit(7) { + 4 + } else { + 0 + } + }) + .expect("EndpointType must be convertible from `attributes` and `endpoint_address`.") + } + + pub(crate) fn calc_actual_interval(&self, port_speed: PortSpeed) -> u8 { + if let PortSpeed::FullSpeed | PortSpeed::LowSpeed = port_speed { + if let EndpointType::IsochOut | EndpointType::IsochIn = self.endpoint_type() { + self.interval + 2 + } else { + self.interval + 3 + } + } else { + self.interval - 1 + } + } + + pub(crate) fn max_streams(&self) -> Option { + //TODO: complete me + if self.is_bulk_out() { + Some(self.calculate_max_streams()) + } else { + None + } + } + + pub(crate) fn is_bulk_out(&self) -> bool { + self.endpoint_type() == EndpointType::BulkOut + } + + pub(crate) fn calculate_max_streams(&self) -> u8 { + self.ssc + .as_ref() + .map(|ssc| { + if self.is_bulk_out() { + let raw = ssc.attributes & 0x1F; + raw + } else { + 0 + } + }) + .unwrap() + } + + pub(crate) fn is_superspeedplus(&self) -> bool { + false + } + + pub(crate) fn mult(&self, lec: bool) -> u8 { + if !lec && self.endpoint_type() == EndpointType::IsochOut { + if self.is_superspeedplus() { + return 0; + } + self.ssc + .as_ref() + .map(|ssc| ssc.attributes & 0x3) + .unwrap_or(0) + } else { + 0 + } + } + + pub(crate) fn doorbell_value_aka_dci(&self) -> u32 { + Self::calc_doorbell_value_aka_dci(self.endpoint_address) + } + + pub(crate) fn calc_doorbell_value_aka_dci(addr: u8) -> u32 { + 2 * u32::from(addr.get_bits(0..=3)) + addr.get_bit(7) as u32 + } +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_hid.rs b/crates/driver_usb/src/usb/descriptors/desc_hid.rs new file mode 100644 index 0000000000..180dcf8b0b --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_hid.rs @@ -0,0 +1,39 @@ +use const_enum::ConstEnum; + +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct Hid { + pub len: u8, + pub descriptor_type: u8, + pub hid_bcd: u16, + pub country_code: u8, + pub num_descriptions: u8, + pub report_descriptor_type: u8, // actually, these two entry is a variant length vector, but we only pick first entry! + pub report_descriptor_len: u16, // +} + +#[derive(ConstEnum, Copy, Clone, Debug)] +#[repr(u8)] +pub enum USBHIDSubclassDescriptorType { + None = 0, + BootInterface = 1, +} + +#[derive(ConstEnum, Copy, Clone, Debug)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub enum USBHIDProtocolDescriptorType { + None = 0, + KeyBoard = 1, + Mouse = 2, +} + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum HIDDescriptorTypes { + //HID + Hid = 0x21, + HIDReport = 0x22, + HIDPhysical = 0x23, +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_interface.rs b/crates/driver_usb/src/usb/descriptors/desc_interface.rs new file mode 100644 index 0000000000..5c34b86604 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_interface.rs @@ -0,0 +1,35 @@ +#[derive(Copy, Clone, Default, Debug)] +#[repr(C, packed)] +pub(crate) struct Interface { + pub len: u8, + pub descriptor_type: u8, + pub interface_number: u8, + pub alternate_setting: u8, + pub num_endpoints: u8, + pub interface_class: u8, + pub interface_subclass: u8, + pub interface_protocol: u8, + pub interface: u8, +} +impl Interface { + pub(crate) fn ty(&self) -> (u8, u8, u8) { + ( + self.interface_class, + self.interface_subclass, + self.interface_protocol, + ) + } +} + +#[derive(Copy, Clone, Default, Debug)] +#[repr(C, packed)] +pub(crate) struct InterfaceAssociation { + pub len: u8, + pub descriptor_type: u8, + pub first_interface: u8, + pub interface_count: u8, + pub function_class: u8, + pub function_subclass: u8, + pub function_protocol: u8, + pub function: u8, +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_str.rs b/crates/driver_usb/src/usb/descriptors/desc_str.rs new file mode 100644 index 0000000000..d4a476a9a1 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_str.rs @@ -0,0 +1,3 @@ +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct Str {} diff --git a/crates/driver_usb/src/usb/descriptors/desc_uvc/mod.rs b/crates/driver_usb/src/usb/descriptors/desc_uvc/mod.rs new file mode 100644 index 0000000000..7ff07cefc1 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_uvc/mod.rs @@ -0,0 +1,17 @@ +use const_enum::ConstEnum; +use num_derive::FromPrimitive; + +pub mod uvc_endpoints; +pub mod uvc_interfaces; + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq, FromPrimitive)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCDescriptorTypes { + UVCClassSpecUnderfined = 0x20, + UVCClassSpecDevice = 0x21, + UVCClassSpecConfiguration = 0x22, + UVCClassSpecString = 0x23, + UVCClassSpecInterface = 0x24, + UVCClassSpecVideoControlInterruptEndpoint = 0x25, +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_endpoints.rs b/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_endpoints.rs new file mode 100644 index 0000000000..7eaf3b194f --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_endpoints.rs @@ -0,0 +1,20 @@ +use const_enum::ConstEnum; + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCVideoClassEndpointSubtypes { + UNDEFINED = 0x00, + GENERAL = 0x01, + ENDPOINT = 0x02, + INTERRUPT = 0x03, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVideoControlInterruptEndpoint { + len: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + max_transfer_size: u16, +} diff --git a/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_interfaces.rs b/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_interfaces.rs new file mode 100644 index 0000000000..d8ec5dc8e7 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/desc_uvc/uvc_interfaces.rs @@ -0,0 +1,643 @@ +use core::ptr; + +use alloc::vec::Vec; +use const_enum::ConstEnum; +use log::trace; + +use super::UVCDescriptorTypes; + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCStandardVideoInterfaceClass { + CC_Video = 0x0e, +} + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCInterfaceSubclass { + UNDEFINED = 0x00, + VIDEOCONTROL = 0x01, + VIDEOSTREAMING = 0x02, + VIDEO_INTERFACE_COLLECTION = 0x03, +} + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCControlInterfaceSubclass { + DESCRIPTOR_UNDEFINED = 0x00, + HEADER = 0x01, + INPUT_TERMINAL = 0x02, + OUTPUT_TERMINAL = 0x03, + SELECTOR_UNIT = 0x04, + PROCESSING_UNIT = 0x05, + EXTENSION_UNIT = 0x06, + ENCODING_UNIT = 0x07, +} + +#[derive(ConstEnum, Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCVSInterfaceSubclass { + UNDEFINED = 0x00, + INPUT_HEADER = 0x01, + OUTPUT_HEADER = 0x02, + STILL_IMAGE_FRAME = 0x03, + FORMAT_UNCOMPRESSED = 0x04, + FRAME_UNCOMPRESSED = 0x05, + FORMAT_MJPEG = 0x06, + FRAME_MJPEG = 0x07, + FORMAT_MPEG2TS = 0x0A, + FORMAT_DV = 0x0C, + COLORFORMAT = 0x0D, + FORMAT_FRAME_BASED = 0x10, + FRAME_FRAME_BASED = 0x11, + FORMAT_STREAM_BASED = 0x12, + FORMAT_H264 = 0x13, + FRAME_H264 = 0x14, + FORMAT_H264_SIMULCAST = 0x15, + FORMAT_VP8 = 0x16, + FRAME_VP8 = 0x17, + FORMAT_VP8_SIMULCAST = 0x18, +} + +#[derive(ConstEnum, Clone, Debug, Copy, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u8)] +pub(crate) enum UVCStandardVideoInterfaceProtocols { + PC_PROTOCOL_UNDEFINED = 0x00, + PC_PROTOCOL_15 = 0x01, +} + +#[derive(Debug, Clone)] +pub enum UVCInterface { + Control(UVCControlInterface), + Streaming(UVCStreamingInterface), +} + +#[derive(Debug, Clone)] +pub enum UVCControlInterface { + Header(UVCControlInterfaceHeader), + OutputTerminal(UVCControlInterfaceOutputTerminal), + InputTerminal(UVCControlInterfaceInputTerminal), + ExtensionUnit(UVCControlInterfaceExtensionUnit), + ProcessingUnit(UVCControlInterfaceProcessingUnit), +} + +#[derive(Debug, Clone)] +pub enum UVCStreamingInterface { + InputHeader(UVCVSInterfaceInputHeader), + OutputHeader, + FormatUncompressed(UVCVSInterfaceFormatUncompressed), + FormatMjpeg(UVCVSInterfaceFormatMJPEG), + FormatMpeg2ts, + FormatDv, + FormatFrameBased, + FormatStreamBased, + FormatH264, + FormatH264Simulcast, + FormatVp8, + FormatVp8Simulcast, + COLORFORMAT(UVCVSInterfaceColorFormat), + + StillImageFrame(UVCVSInterfaceStillImageFrame), + FrameUncompressed(UVCVSInterfaceFrameUncompressed), + FrameMjpeg(UVCVSInterfaceFrameMJPEG), + FrameFrameBased, + FrameH264, + FrameVp8, +} + +#[derive(Clone, Debug, Copy)] +#[allow(non_camel_case_types)] +pub enum UVCStreamingFormartInterface { + FormatUncompressed(UVCVSInterfaceFormatUncompressed), + FormatMjpeg(UVCVSInterfaceFormatMJPEG), + COLORFORMAT(UVCVSInterfaceColorFormat), + FormatMpeg2ts, + FormatDv, + FormatFrameBased, + FormatStreamBased, + FormatH264, + FormatH264Simulcast, + FormatVp8, + FormatVp8Simulcast, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub enum UVCStreamingFrameInterface { + StillImageFrame(UVCVSInterfaceStillImageFrame), + FrameUncompressed(UVCVSInterfaceFrameUncompressed), + FrameMjpeg(UVCVSInterfaceFrameMJPEG), + FrameFrameBased, + FrameH264, + FrameVp8, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCControlInterfaceHeader { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + bcd_uvc: u16, + total_length: u16, + clock_frequency: u32, + in_collection: u8, + interface_nr: Vec, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCControlInterfaceInputTerminal { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + terminal_id: u8, + terminal_type: u16, + associated_terminal: u8, + string_index_terminal: u8, + reserved: Vec, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCControlInterfaceOutputTerminal { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + terminal_id: u8, + terminal_type: u16, + associated_terminal: u8, + source_id: u8, + string_index_terminal: u8, + reserved: Vec, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCControlInterfaceExtensionUnit { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + unit_id: u8, + guid_extension_code: [u8; 16], + num_controls: u8, + nr_in_pins: u8, + source_ids: Vec, + control_size: u8, + controls: Vec, + extension: u8, +} + +#[derive(Clone, Debug, Copy)] +#[allow(non_camel_case_types)] +pub struct UVCControlInterfaceProcessingUnit { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + unit_id: u8, + source_id: u8, + max_multiplier: u16, + control_size: u8, + controls: [u8; 3], + processing: u8, + video_standards: u8, +} + +#[derive(ConstEnum, Clone, Debug, Copy, PartialEq)] +#[allow(non_camel_case_types)] +#[repr(u16)] +pub(crate) enum UVCCONTROLOutputTerminalType { + OTT_VendorSpec = 0x300, + OTT_Display = 0x301, + OTT_MEDIA_TRANSPORT_OUTPUT = 0x302, + TT_VendorSpec = 0x0100, + TT_Streaming = 0x0101, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceInputHeader { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + num_formats: u8, + total_length: u16, + endpoint_address: u8, + info: u8, + terminal_link: u8, + still_capture_method: u8, + trigger_support: u8, + trigger_useage: u8, + control_size: u8, + interface_nr: Vec, +} + +#[derive(Clone, Debug, Copy)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceFormatMJPEG { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + format_index: u8, + num_frame_descriptors: u8, + flags: u8, + default_frame_index: u8, + aspect_ratio_x: u8, + aspect_ratio_y: u8, + interlace_flags: u8, + is_copy_protect: u8, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceFrameMJPEG { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + frame_index: u8, + capabilities: u8, + width: u16, + height: u16, + min_bit_rate: u32, + max_bit_rate: u32, + max_video_frame_buffer_size: u32, + default_frame_interval: u32, + frame_interval_type: u8, + frame_interval: FrameInterval, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceStillImageFrame { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + endpoint_address: u8, + num_image_size_paterns: u8, + width_heights: Vec<(u16, u16)>, + num_compression_pattern: u8, + compressions: Vec, +} + +#[derive(Clone, Copy, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceFormatUncompressed { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + format_index: u8, + number_frame_descriptor: u8, + guid_format: [u8; 16], + bits_per_pixel: u8, + default_frame_index: u8, + aspect_ratio_x: u8, + aspect_ratio_y: u8, + m_interlace_flags: u8, + is_copy_protect: u8, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceFrameUncompressed { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + frame_index: u8, + capabilities: u8, + width: u16, + height: u16, + min_bit_rate: u32, + max_bit_rate: u32, + max_video_frame_buffer_size: u32, + default_frame_interval: u32, + frame_interval_type: u8, + frame_interval: FrameInterval, +} + +#[derive(Clone, Debug)] +#[allow(non_camel_case_types)] +pub enum FrameInterval { + Continuous((u32, u32, u32)), + Discrete(Vec), +} + +#[derive(Clone, Debug, Copy)] +#[allow(non_camel_case_types)] +pub struct UVCVSInterfaceColorFormat { + length: u8, + descriptor_type: u8, + descriptor_sub_type: u8, + color_primaries: u8, + transfer_characteristics: u8, + matrix_coefficients: u8, +} + +impl UVCControlInterface { + pub fn from_u8_array(raw: &[u8]) -> Self { + trace!("buffer:{:?}", raw); + let len = raw[0]; + let descriptor_type = raw[1]; + let descriptor_sub_type = raw[2]; + trace!( + "subtype{:?}", + UVCControlInterfaceSubclass::from(descriptor_sub_type) + ); + + match UVCControlInterfaceSubclass::from(descriptor_sub_type) { + UVCControlInterfaceSubclass::DESCRIPTOR_UNDEFINED => panic!("impossible"), + UVCControlInterfaceSubclass::HEADER => Self::Header({ + trace!("header!"); + let len_array_nr = len - 12; + UVCControlInterfaceHeader { + length: len.clone(), + descriptor_type, + descriptor_sub_type, + bcd_uvc: u16::from_ne_bytes(raw[3..=4].try_into().unwrap()), + total_length: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()), + clock_frequency: u32::from_ne_bytes(raw[7..=10].try_into().unwrap()), + in_collection: raw[11], + interface_nr: { + let mut vec = Vec::new(); + for i in 12..len { + vec.push(raw[i as usize]); + } + vec + }, + } + }), + UVCControlInterfaceSubclass::INPUT_TERMINAL => { + Self::InputTerminal(UVCControlInterfaceInputTerminal { + length: len, + descriptor_type, + descriptor_sub_type, + terminal_id: raw[3], + terminal_type: u16::from_ne_bytes(unsafe { raw[4..=5].try_into().unwrap() }), + associated_terminal: raw[6], + string_index_terminal: raw[7], + reserved: raw[8..(len as usize)].to_vec(), + }) + } + UVCControlInterfaceSubclass::OUTPUT_TERMINAL => { + Self::OutputTerminal(UVCControlInterfaceOutputTerminal { + length: len, + descriptor_type, + descriptor_sub_type, + terminal_id: raw[3], + terminal_type: u16::from_ne_bytes(unsafe { raw[4..=5].try_into().unwrap() }), + associated_terminal: raw[6], + source_id: raw[7], + string_index_terminal: raw[8], + reserved: raw[9..(len as usize)].to_vec(), + }) + } + UVCControlInterfaceSubclass::SELECTOR_UNIT => todo!(), + UVCControlInterfaceSubclass::PROCESSING_UNIT => { + Self::ProcessingUnit({ + //this descriptor may change with different uvc version + unsafe { ptr::read((raw as *const [u8]).cast()) } + }) + } + UVCControlInterfaceSubclass::EXTENSION_UNIT => Self::ExtensionUnit({ + let nr_in_pins = raw[21]; + let last_in_pin = 21 + nr_in_pins as usize; + let in_pins = raw[21..last_in_pin].to_vec(); + + let control_size = raw[last_in_pin]; + let last_control = last_in_pin + control_size as usize; + let controls = raw[last_in_pin..last_control].to_vec(); + + UVCControlInterfaceExtensionUnit { + length: len, + descriptor_type, + descriptor_sub_type, + unit_id: raw[3], + guid_extension_code: { + let mut codes = [0u8; 16]; + codes.copy_from_slice(&raw[4..20]); + codes + }, + num_controls: raw[20], + nr_in_pins, + source_ids: in_pins, + control_size: control_size, + controls, + extension: raw[last_control], + } + }), + UVCControlInterfaceSubclass::ENCODING_UNIT => todo!(), + } + } +} + +impl UVCStreamingInterface { + pub fn from_u8_array(raw: &[u8]) -> Self { + trace!("buffer:{:?}", raw); + let len = raw[0]; + let descriptor_type = raw[1]; + let descriptor_sub_type = UVCVSInterfaceSubclass::from(raw[2]); + trace!("subtype{:?}", descriptor_sub_type); + match descriptor_sub_type { + UVCVSInterfaceSubclass::INPUT_HEADER => Self::InputHeader({ + let control_size = raw[12]; + UVCVSInterfaceInputHeader { + length: len, + descriptor_type, + descriptor_sub_type: descriptor_sub_type.into(), + num_formats: raw[3], + total_length: u16::from_ne_bytes(raw[4..=5].try_into().unwrap()), + endpoint_address: raw[6], + info: raw[7], + terminal_link: raw[8], + still_capture_method: raw[9], + trigger_support: raw[10], + trigger_useage: raw[11], + control_size, + interface_nr: raw[13..(len as usize)].to_vec(), + } + }), + UVCVSInterfaceSubclass::FORMAT_MJPEG => { + Self::FormatMjpeg(unsafe { ptr::read((raw as *const [u8]).cast()) }) + } + UVCVSInterfaceSubclass::FRAME_MJPEG => { + let frame_interval_type = raw[25]; + + let frame_interval = match frame_interval_type { + 0 => FrameInterval::Continuous(( + u32::from_ne_bytes(raw[26..30].try_into().unwrap()), + u32::from_ne_bytes(raw[30..34].try_into().unwrap()), + u32::from_ne_bytes(raw[34..(len as usize)].try_into().unwrap()), + )), + other => FrameInterval::Discrete( + raw[26..((26 + other * 4) as usize)] + .chunks(4) + .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) + .collect(), + ), + }; + + Self::FrameMjpeg(UVCVSInterfaceFrameMJPEG { + length: len, + descriptor_type, + descriptor_sub_type: descriptor_sub_type.into(), + frame_index: raw[3], + capabilities: raw[4], + width: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()), + height: u16::from_ne_bytes(raw[7..=8].try_into().unwrap()), + min_bit_rate: u32::from_ne_bytes(raw[9..13].try_into().unwrap()), + max_bit_rate: u32::from_ne_bytes(raw[13..17].try_into().unwrap()), + max_video_frame_buffer_size: u32::from_ne_bytes( + raw[17..21].try_into().unwrap(), + ), + default_frame_interval: u32::from_ne_bytes(raw[21..25].try_into().unwrap()), + frame_interval_type, + frame_interval, + }) + } + UVCVSInterfaceSubclass::STILL_IMAGE_FRAME => { + let num_image_size_paterns = raw[4]; + let loc_num_compression_pattern = 5 + 4 * num_image_size_paterns as usize; + let width_heights = raw[5..loc_num_compression_pattern] + .chunks(4) + .map(|t| { + ( + u16::from_ne_bytes(t[0..=1].try_into().unwrap()), + u16::from_ne_bytes(t[2..=3].try_into().unwrap()), + ) + }) + .collect(); + + Self::StillImageFrame(UVCVSInterfaceStillImageFrame { + length: len, + descriptor_type, + descriptor_sub_type: descriptor_sub_type.into(), + endpoint_address: raw[3], + num_image_size_paterns, + width_heights, + num_compression_pattern: raw[loc_num_compression_pattern], + compressions: raw[loc_num_compression_pattern + 1..len as usize].to_vec(), + }) + } + UVCVSInterfaceSubclass::FORMAT_UNCOMPRESSED => { + Self::FormatUncompressed(unsafe { ptr::read((raw as *const [u8]).cast()) }) + } + UVCVSInterfaceSubclass::FRAME_UNCOMPRESSED => { + let frame_interval_type = raw[25]; + + let frame_interval = match frame_interval_type { + 0 => FrameInterval::Continuous(( + u32::from_ne_bytes(raw[26..30].try_into().unwrap()), + u32::from_ne_bytes(raw[30..34].try_into().unwrap()), + u32::from_ne_bytes(raw[34..(len as usize)].try_into().unwrap()), + )), + other => FrameInterval::Discrete( + raw[26..((26 + other * 4) as usize)] + .chunks(4) + .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) + .collect(), + ), + }; + + Self::FrameUncompressed(UVCVSInterfaceFrameUncompressed { + length: len, + descriptor_type, + descriptor_sub_type: descriptor_sub_type.into(), + frame_index: raw[3], + capabilities: raw[4], + width: u16::from_ne_bytes(raw[5..=6].try_into().unwrap()), + height: u16::from_ne_bytes(raw[7..=8].try_into().unwrap()), + min_bit_rate: u32::from_ne_bytes(raw[9..13].try_into().unwrap()), + max_bit_rate: u32::from_ne_bytes(raw[13..17].try_into().unwrap()), + max_video_frame_buffer_size: u32::from_ne_bytes( + raw[17..21].try_into().unwrap(), + ), + default_frame_interval: u32::from_ne_bytes(raw[21..25].try_into().unwrap()), + frame_interval_type, + frame_interval, + }) + } + UVCVSInterfaceSubclass::COLORFORMAT => { + Self::COLORFORMAT(unsafe { ptr::read((raw as *const [u8]).cast()) }) + } + + todo => todo!("impl:{:?}", todo), + } + } +} + +impl UVCStreamingFormartInterface { + pub fn ismatch(&self, another: &UVCStreamingFrameInterface) -> bool { + match self { + UVCStreamingFormartInterface::FormatUncompressed(_) + if let UVCStreamingFrameInterface::FrameUncompressed(_) = another => + { + true + } + UVCStreamingFormartInterface::FormatMjpeg(_) + if let UVCStreamingFrameInterface::FrameMjpeg(_) = another => + { + true + } + UVCStreamingFormartInterface::FormatMpeg2ts => todo!(), + UVCStreamingFormartInterface::FormatDv => todo!(), + UVCStreamingFormartInterface::FormatFrameBased => todo!(), + UVCStreamingFormartInterface::FormatStreamBased => todo!(), + UVCStreamingFormartInterface::FormatH264 => todo!(), + UVCStreamingFormartInterface::FormatH264Simulcast => todo!(), + UVCStreamingFormartInterface::FormatVp8 => todo!(), + UVCStreamingFormartInterface::FormatVp8Simulcast => todo!(), + _ => false, + } + } + + pub fn filter_out_self(input: &UVCStreamingInterface) -> Option { + match input { + UVCStreamingInterface::FormatUncompressed(any) => { + Some(Self::FormatUncompressed(any.clone())) + } + UVCStreamingInterface::FormatMjpeg(any) => Some(Self::FormatMjpeg(any.clone())), + UVCStreamingInterface::FormatMpeg2ts => todo!(), + UVCStreamingInterface::FormatDv => todo!(), + UVCStreamingInterface::FormatFrameBased => todo!(), + UVCStreamingInterface::FormatStreamBased => todo!(), + UVCStreamingInterface::FormatH264 => todo!(), + UVCStreamingInterface::FormatH264Simulcast => todo!(), + UVCStreamingInterface::FormatVp8 => todo!(), + UVCStreamingInterface::FormatVp8Simulcast => todo!(), + _ => None, + } + } + + pub fn filter_out_color_formart(input: &UVCStreamingInterface) -> Option { + match input { + UVCStreamingInterface::COLORFORMAT(color) => Some(Self::COLORFORMAT(color.clone())), + _ => None, + } + } +} + +impl UVCStreamingFrameInterface { + pub fn filter_out_self(input: &UVCStreamingInterface) -> Option { + match input { + UVCStreamingInterface::FrameUncompressed(any) => { + Some(Self::FrameUncompressed(any.clone())) + } + UVCStreamingInterface::FrameMjpeg(any) => Some(Self::FrameMjpeg(any.clone())), + UVCStreamingInterface::FrameFrameBased => todo!(), + UVCStreamingInterface::FrameH264 => todo!(), + UVCStreamingInterface::FrameVp8 => todo!(), + _ => None, + } + } + + pub fn filter_out_still(input: &UVCStreamingInterface) -> Option { + match input { + UVCStreamingInterface::StillImageFrame(any) => Some(Self::StillImageFrame(any.clone())), + _ => None, + } + } +} diff --git a/crates/driver_usb/src/usb/descriptors/mod.rs b/crates/driver_usb/src/usb/descriptors/mod.rs new file mode 100644 index 0000000000..7d5c6b8474 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/mod.rs @@ -0,0 +1,187 @@ +// +use core::ptr; + +use alloc::{collections, vec, vec::Vec}; +use const_enum::ConstEnum; +use desc_configuration::Configuration; +use desc_device::Device; +use desc_endpoint::Endpoint; +use desc_hid::{HIDDescriptorTypes, Hid}; +use desc_interface::{Interface, InterfaceAssociation}; +use desc_str::Str; +use desc_uvc::{ + uvc_endpoints::UVCVideoControlInterruptEndpoint, + uvc_interfaces::{ + UVCControlInterface, UVCControlInterfaceHeader, UVCInterface, UVCInterfaceSubclass, + UVCStreamingInterface, + }, + UVCDescriptorTypes, +}; +use log::{debug, trace, warn}; +use num_derive::{FromPrimitive, ToPrimitive}; +use num_traits::FromPrimitive; +use parser::{Error, ParserMetaData}; +use tock_registers::interfaces; + +use crate::abstractions::{dma::DMA, PlatformAbstractions}; + +pub mod parser; +pub mod topological_desc; + +pub mod desc_configuration; +pub mod desc_device; +pub mod desc_endpoint; +pub mod desc_hid; +pub mod desc_interface; +pub mod desc_str; +pub mod desc_uvc; + +#[allow(non_camel_case_types)] +#[derive(FromPrimitive, ToPrimitive, Copy, Clone, Debug, PartialEq, ConstEnum)] +#[repr(u8)] +pub(crate) enum USBStandardDescriptorTypes { + //USB 1.1: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + Device = 0x01, + Configuration = 0x02, + String = 0x03, + Interface = 0x04, + Endpoint = 0x05, + // USB 2.0: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + DeviceQualifier = 0x06, + OtherSpeedConfiguration = 0x07, + InterfacePower1 = 0x08, + // USB 3.0+: 9.4 Standard Device Requests, Table 9-5. Descriptor Types + OTG = 0x09, + Debug = 0x0a, + InterfaceAssociation = 0x0b, + Bos = 0x0f, + DeviceCapability = 0x10, + SuperSpeedEndpointCompanion = 0x30, + SuperSpeedPlusIsochEndpointCompanion = 0x31, +} + +pub(crate) fn construct_control_transfer_type( + desc: u8, + index: u8, +) -> DescriptionTypeIndexPairForControlTransfer { + DescriptionTypeIndexPairForControlTransfer { ty: desc, i: index } +} + +pub(crate) struct DescriptionTypeIndexPairForControlTransfer { + ty: u8, + i: u8, +} + +impl DescriptionTypeIndexPairForControlTransfer { + pub(crate) fn bits(self) -> u16 { + (self.ty as u16) << 8 | u16::from(self.i) + } +} + +#[derive(Clone, Debug)] +pub(crate) enum USBDescriptor { + Device(Device), + Configuration(Configuration), + Str(Str), + Interface(Interface), + InterfaceAssociation(InterfaceAssociation), + Endpoint(Endpoint), + Hid(Hid), + UVCInterface(UVCInterface), + UVCClassSpecVideoControlInterruptEndpoint(UVCVideoControlInterruptEndpoint), +} + +impl USBDescriptor { + pub(crate) fn from_slice(raw: &[u8], metadata: ParserMetaData) -> Result { + assert_eq!(raw.len(), raw[0].into()); + match Self::from_slice_standard_usb(raw) { + Ok(okay) => Ok(okay), + Err(_) if let ParserMetaData::HID = metadata => Self::from_slice_hid(raw), + Err(_) if let ParserMetaData::UVC(flag) = metadata => Self::from_slice_uvc(raw, flag), + Err(any) => panic!("unknown situation {:?},{:?}", any, metadata), + } + } + + pub(crate) fn from_slice_uvc(raw: &[u8], flag: u8) -> Result { + trace!("from slice uvc!{:?}", raw); + match UVCDescriptorTypes::from(raw[1]) { + UVCDescriptorTypes::UVCClassSpecUnderfined => panic!("underfined!"), + UVCDescriptorTypes::UVCClassSpecDevice => todo!(), + UVCDescriptorTypes::UVCClassSpecConfiguration => todo!(), + UVCDescriptorTypes::UVCClassSpecString => todo!(), + UVCDescriptorTypes::UVCClassSpecInterface => { + match UVCInterfaceSubclass::from(if flag == 0 { raw[2] } else { flag }) { + UVCInterfaceSubclass::UNDEFINED => panic!("impossible!"), + UVCInterfaceSubclass::VIDEOCONTROL => Ok(Self::UVCInterface( + UVCInterface::Control(UVCControlInterface::from_u8_array(raw)), + )), + UVCInterfaceSubclass::VIDEOSTREAMING => Ok(Self::UVCInterface( + UVCInterface::Streaming(UVCStreamingInterface::from_u8_array(raw)), + )), + UVCInterfaceSubclass::VIDEO_INTERFACE_COLLECTION => { + panic!("this subclass only appear in iac, impossible here!"); + } + } + } + UVCDescriptorTypes::UVCClassSpecVideoControlInterruptEndpoint => { + Ok(Self::UVCClassSpecVideoControlInterruptEndpoint(unsafe { + ptr::read((raw as *const [u8]).cast()) + })) + } + } + } + + pub(crate) fn from_slice_hid(raw: &[u8]) -> Result { + match HIDDescriptorTypes::from(raw[1]) { + HIDDescriptorTypes::Hid => { + Ok(Self::Hid(unsafe { ptr::read((raw as *const [u8]).cast()) })) + } + HIDDescriptorTypes::HIDReport => todo!(), + HIDDescriptorTypes::HIDPhysical => todo!(), + } + } + + pub(crate) fn from_slice_standard_usb(raw: &[u8]) -> Result { + match USBStandardDescriptorTypes::from_u8(raw[1]) { + Some(t) => { + let raw: *const [u8] = raw; + match t { + // SAFETY: This operation is safe because the length of `raw` is equivalent to the + // one of the descriptor. + USBStandardDescriptorTypes::Device => { + Ok(Self::Device(unsafe { ptr::read(raw.cast()) })) + } + USBStandardDescriptorTypes::Configuration => { + Ok(Self::Configuration(unsafe { ptr::read(raw.cast()) })) + } + USBStandardDescriptorTypes::String => { + Ok(Self::Str(unsafe { ptr::read(raw.cast()) })) + } + USBStandardDescriptorTypes::Interface => { + Ok(Self::Interface(unsafe { ptr::read(raw.cast()) })) + } + USBStandardDescriptorTypes::Endpoint => { + Ok(Self::Endpoint(unsafe { ptr::read(raw.cast()) })) + } + USBStandardDescriptorTypes::InterfaceAssociation => { + Ok(Self::InterfaceAssociation(unsafe { ptr::read(raw.cast()) })) + } + other => { + unimplemented!("please implement descriptor type:{:?}", other) + } + } + } + None => Err(Error::UnrecognizedType(raw[1])), + } + } +} + +#[derive(Copy, Clone, ConstEnum)] +#[repr(u8)] +pub enum PortSpeed { + FullSpeed = 1, + LowSpeed = 2, + HighSpeed = 3, + SuperSpeed = 4, + SuperSpeedPlus = 5, +} diff --git a/crates/driver_usb/src/usb/descriptors/parser.rs b/crates/driver_usb/src/usb/descriptors/parser.rs new file mode 100644 index 0000000000..5321ab4359 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/parser.rs @@ -0,0 +1,546 @@ +use core::ptr; + +// +use alloc::vec; +use alloc::vec::Vec; +use log::{debug, error, trace, warn}; +use num_traits::FromPrimitive; + +use crate::{ + abstractions::{dma::DMA, PlatformAbstractions}, + usb::descriptors::{ + desc_hid::Hid, + desc_uvc::uvc_interfaces::{UVCControlInterface, UVCInterface, UVCStreamingInterface}, + USBDescriptor, USBStandardDescriptorTypes, + }, +}; + +use super::{ + desc_device::StandardUSBDeviceClassCode, + desc_interface::{Interface, InterfaceAssociation}, + desc_uvc::{ + uvc_interfaces::{ + UVCInterfaceSubclass, UVCStandardVideoInterfaceClass, + UVCStandardVideoInterfaceProtocols, + }, + UVCDescriptorTypes, + }, + topological_desc::{ + TopologicalUSBDescriptorConfiguration, TopologicalUSBDescriptorDevice, + TopologicalUSBDescriptorEndpoint, TopologicalUSBDescriptorFunction, + TopologicalUSBDescriptorRoot, + }, +}; + +pub(crate) struct RawDescriptorParser { + device: DMA<[u8], O::DMA>, + configs: Vec<(DMA<[u8], O::DMA>, usize)>, + state: ParserStateMachine, + result: Option, + others: Vec, + metadata: ParserMetaData, + current: usize, + current_len: usize, +} + +#[derive(Debug)] +pub(crate) enum Error { + UnrecognizedType(u8), + ParseOrderError, + EndOfDescriptors, + NotReadyToParse, + StateSwitch, +} + +#[derive(PartialEq, Debug)] +enum ParserStateMachine { + Device, + NotReady, + Config(usize), + Inetrface(usize, u8), + END, +} + +#[derive(Clone, Debug)] +pub enum ParserMetaData { + UVC(u8), + HID, + Unknown(ParserMetaDataUnknownSituation), + NotDetermined, +} + +#[derive(Clone, Debug)] +pub enum ParserMetaDataUnknownSituation { + Unknown, //treat as standard usb device + ReferIAC, + ReferInterface, +} + +impl ParserMetaData { + //refer https://www.usb.org/defined-class-codes + pub fn determine(class: u8, subclass: u8, protocol: u8) -> Self { + match (class.into(), subclass, protocol) { + (StandardUSBDeviceClassCode::Miscellaneous, 0x02, 0x01) => { + return Self::Unknown(ParserMetaDataUnknownSituation::ReferIAC) + } + (StandardUSBDeviceClassCode::HID, _, _) => return Self::HID, + (StandardUSBDeviceClassCode::ReferInterfaceDescriptor, _, _) => { + return Self::Unknown(ParserMetaDataUnknownSituation::ReferInterface) + } + (StandardUSBDeviceClassCode::VendorSpecific, 0, 0) => { + return Self::Unknown(ParserMetaDataUnknownSituation::Unknown) + } + _ => {} + } + + match (class.into(), subclass.into(), protocol.into()) { + ( + UVCStandardVideoInterfaceClass::CC_Video, + UVCInterfaceSubclass::VIDEO_INTERFACE_COLLECTION, + UVCStandardVideoInterfaceProtocols::PC_PROTOCOL_UNDEFINED, + ) => return Self::UVC(0u8), + _ => {} + } + + Self::Unknown(ParserMetaDataUnknownSituation::Unknown) + } +} + +impl RawDescriptorParser +where + O: PlatformAbstractions, +{ + pub fn new(raw_device: DMA<[u8], O::DMA>) -> Self { + let len = raw_device.len(); + Self { + device: raw_device, + configs: Vec::new(), + state: ParserStateMachine::Device, + current: 0, + current_len: len, + result: None, + others: Vec::new(), + metadata: ParserMetaData::NotDetermined, + } + } + + pub fn num_of_configs(&self) -> usize { + if self.state != ParserStateMachine::Device { + self.result + .as_ref() + .map(|r| r.data.num_configurations.clone() as _) + .unwrap() + } else { + panic!("do not call this method before device has been deserialized!"); + } + } + + pub fn append_config(&mut self, raw_config: DMA<[u8], O::DMA>) -> &mut Self { + let len = raw_config.len(); + self.configs.push((raw_config, len)); + self + } + + pub fn summarize(mut self) -> TopologicalUSBDescriptorRoot { + while self.single_state_cycle() {} + TopologicalUSBDescriptorRoot { + device: vec![self.result.unwrap()], + others: self.others, + metadata: self.metadata, + } + } + + //return false if reach end, otherwise true + pub fn single_state_cycle(&mut self) -> bool { + match &self.state { + ParserStateMachine::Device => { + self.result = self.parse_single_device_descriptor().ok(); + self.state = ParserStateMachine::NotReady; + trace!("state change:{:?}", self.state); + self.current = 0; + self.current_len = 0; + true + } + ParserStateMachine::Config(index) => { + let num_of_configs = self.num_of_configs(); + let current_index = *index; + if current_index >= num_of_configs { + self.state = ParserStateMachine::END; + trace!("state change:{:?}", self.state); + return false; + } + let topological_usbdescriptor_configuration = self.parse_current_config().unwrap(); + self.result + .as_mut() + .unwrap() + .child + .push(topological_usbdescriptor_configuration); + self.state = ParserStateMachine::Config(current_index + 1); + trace!("state change:{:?}", self.state); + true + } + ParserStateMachine::END => panic!("should not call anymore while reaching end"), + ParserStateMachine::NotReady => { + if let Some(res) = &self.result + && self.configs.len() >= res.data.num_configurations as _ + { + self.state = ParserStateMachine::Config(0); + trace!("state change:{:?}", self.state); + self.current_len = self.configs[0].1; + true + } else { + false + } + } + _ => true, + } + } + + fn cut_raw_descriptor(&mut self) -> Result, Error> { + match &self.state { + ParserStateMachine::Device => { + let len: usize = self.device[self.current].into(); + let v = self.device[self.current..(self.current + len)].to_vec(); + self.current += len; + Ok(v) + } + ParserStateMachine::NotReady => Err(Error::NotReadyToParse), + ParserStateMachine::Config(cfg_index) | ParserStateMachine::Inetrface(cfg_index, _) => { + let len: usize = (self.configs[*cfg_index].0)[self.current].into(); + let v = (self.configs[*cfg_index].0)[self.current..(self.current + len)].to_vec(); + self.current += len; + Ok(v) + } + ParserStateMachine::END => Err(Error::EndOfDescriptors), + } + } + + fn parse_single_device_descriptor(&mut self) -> Result { + trace!("parse single device desc!"); + if let USBDescriptor::Device(dev) = self.parse_any_descriptor()? { + { + trace!("dev:{:#?}", dev); + match self.metadata { + ParserMetaData::NotDetermined => { + self.metadata = + ParserMetaData::determine(dev.class, dev.subclass, dev.protocol) + } + _ => {} + } + }; + Ok(TopologicalUSBDescriptorDevice { + data: dev, + child: Vec::new(), + }) + } else { + Err(Error::ParseOrderError) + } + } + + fn parse_current_config(&mut self) -> Result { + trace!("parse config desc!"); + let raw = self.cut_raw_descriptor()?; + + let mut cfg = + USBDescriptor::from_slice(&raw, self.metadata.clone()).and_then(|converted| { + if let USBDescriptor::Configuration(cfg) = converted { + Ok(TopologicalUSBDescriptorConfiguration { + data: cfg, + child: Vec::new(), + }) + } else { + Err(Error::ParseOrderError) + } + })?; + + trace!("max num of interface num:{}", cfg.data.num_interfaces()); + + loop { + match self.parse_function() { + Ok(func) => { + cfg.child.push(func); + } + Err(Error::EndOfDescriptors) => { + break; + } + Err(Error::StateSwitch) => { + continue; + } + Err(other) => return Err(other), + } + } + + Ok(cfg) + } + + fn parse_function(&mut self) -> Result { + trace!("parse function desc!"); + + if let Some(desc_type) = self.peek_std_desc_type() { + match desc_type { + USBStandardDescriptorTypes::Interface => { + trace!( + "parse single interface desc! current state:{:?}", + self.state + ); + // let collections = TopologicalUSBDescriptorFunction::Interface(vec![]); + let mut interfaces = Vec::new(); + + loop { + trace!("loop! state:{:?}", self.state); + match &self.state { + ParserStateMachine::Config(cfg_id) => { + self.state = ParserStateMachine::Inetrface( + (*cfg_id), + self.peek_interface().unwrap().interface_number, + ); + trace!("state change:{:?}", self.state); + } + ParserStateMachine::Inetrface(cfg_index, current_interface_id) => { + trace!("state interface!"); + match &self.peek_interface() { + Some(next) + if (next.interface_number) == *current_interface_id => + { + trace!("equal!"); + trace!("current:{:?}", current_interface_id); + let interface = self.parse_interface().unwrap(); + trace!("got interface {:?}", interface); + let additional = self.parse_other_descriptors_by_metadata(); + trace!("got additional data {:?}", additional); + let endpoints = self.parse_endpoints(); + trace!("got endpoints {:?}", endpoints); + interfaces.push((interface, additional, endpoints)) + } + Some(next) + if (next.interface_number) != *current_interface_id => + { + trace!("not equal!"); + self.state = ParserStateMachine::Inetrface( + *cfg_index, + next.interface_number, + ); + trace!("state change:{:?}", self.state); + break; + } + None => break, + other => panic!("deserialize error! {:?}", other), + }; + } + _ => panic!("impossible situation!"), + } + } + + Ok(TopologicalUSBDescriptorFunction::Interface(interfaces)) + } + USBStandardDescriptorTypes::InterfaceAssociation => { + trace!("parse InterfaceAssociation desc!"); + let interface_association = self.parse_interface_association().unwrap(); + // match &self.state { + // ParserStateMachine::Config(cfg_id) => { + // self.state = ParserStateMachine::Inetrface(cfg_id.clone(), 0); + // trace!("state change:{:?}", self.state); + // } + // other => panic!("error on switching state! {:?}", other), + // } + let mut interfaces = Vec::new(); + for i in 0..interface_association.interface_count { + trace!("parsing {i}th interface!"); + //agreement:there is always some interfaces that match the cound behind association + interfaces.push(self.parse_function()?); + } + Ok(TopologicalUSBDescriptorFunction::InterfaceAssociation(( + interface_association, + interfaces, + ))) + } + anyother => { + trace!("unrecognize type!"); + Err(Error::UnrecognizedType(anyother as u8)) + } + } + } else { + Err(Error::EndOfDescriptors) + } + } + + fn parse_any_descriptor(&mut self) -> Result { + trace!( + "parse any desc at current{}! type:{:?}", + self.current, + self.peek_std_desc_type() + ); + let raw = self.cut_raw_descriptor()?; + trace!("from slice!"); + USBDescriptor::from_slice(&raw, self.metadata.clone()) + } + + fn parse_interface_association(&mut self) -> Result { + match self.parse_any_descriptor()? { + USBDescriptor::InterfaceAssociation(interface_association) => { + if let ParserMetaData::Unknown(ParserMetaDataUnknownSituation::ReferIAC) = + self.metadata + { + self.metadata = ParserMetaData::determine( + interface_association.function_class, + interface_association.function_subclass, + interface_association.function_protocol, + ) + } + + Ok(interface_association) + } + _ => Err(Error::ParseOrderError), + } + } + + fn peek_std_desc_type(&self) -> Option { + match self.state { + ParserStateMachine::Device => { + let peeked = + USBStandardDescriptorTypes::from_u8(self.device[self.current + 1] as u8); + trace!("peeked type:{:?}", peeked); + peeked + } + ParserStateMachine::Config(index) | ParserStateMachine::Inetrface(index, _) => { + let peeked = USBStandardDescriptorTypes::from_u8( + self.configs[index].0[self.current + 1] as u8, + ); + trace!("peeked std type:{:?}", peeked); + peeked + } + _ => panic!("impossible!"), + } + } + + //while call this methods, parser state machine always at "config" state + fn peek_uvc_desc_type(&mut self) -> Option { + trace!("peek uvc type!"); + match self.state { + ParserStateMachine::Config(index) | ParserStateMachine::Inetrface(index, _) => { + UVCDescriptorTypes::from_u8(self.configs[index].0[self.current + 1]) + } + _ => None, + } + } + + fn peek_interface(&self) -> Option { + match self.state { + ParserStateMachine::Config(index) | ParserStateMachine::Inetrface(index, _) => { + trace!( + "peek at {},value:{}", + self.current, + self.configs[index].0[self.current] + ); + + if self.peek_std_desc_type() == Some(USBStandardDescriptorTypes::Interface) { + let len = self.configs[index].0[self.current] as usize; + let from = self.current; + let to = from + len - 1; + trace!("len{len},from{from},to{to}"); + let raw = (&self.configs[index].0[from..to]) as *const [u8]; + let interface = unsafe { ptr::read_volatile(raw as *const Interface) }; //do not cast, in current version rust still had value cache issue + trace!("got:{:?}", interface); + + return Some(interface); + } + } + _ => {} + } + None + } + + fn parse_interface(&mut self) -> Result { + trace!("parse interfaces,metadata:{:?}", self.metadata); + match self.parse_any_descriptor()? { + USBDescriptor::Interface(int) => { + match &self.metadata { + ParserMetaData::UVC(_) => { + self.metadata = ParserMetaData::UVC(int.interface_subclass.clone()); + } + ParserMetaData::Unknown(ParserMetaDataUnknownSituation::ReferInterface) => { + self.metadata = ParserMetaData::determine( + int.interface_class, + int.interface_subclass, + int.interface_protocol, + ) + } + _ => {} + } + Ok(int) + } + _ => Err(Error::ParseOrderError), + } + } + + fn parse_other_descriptors_by_metadata(&mut self) -> Vec { + trace!( + "parse additional data for interface with metadata:{:?}", + self.metadata + ); + let mut vec = Vec::new(); + loop { + match self.peek_std_desc_type() { + Some( + USBStandardDescriptorTypes::Endpoint + | USBStandardDescriptorTypes::Interface + | USBStandardDescriptorTypes::InterfaceAssociation, + ) => break, + Some(_) | None => { + trace!("parse misc desc!"); + vec.push( + self.parse_any_descriptor() + .inspect_err(|e| error!("usb descriptor parse failed:{:?}", e)) + .unwrap(), + ); + continue; + } + } + } + vec + } + + fn parse_endpoints(&mut self) -> Vec { + trace!("parse enedpoints, metadata:{:?}", self.metadata); + let mut endpoints = Vec::new(); + + loop { + if let Some(USBStandardDescriptorTypes::Endpoint) = self.peek_std_desc_type() { + match self.parse_any_descriptor().unwrap() { + USBDescriptor::Endpoint(endpoint) => { + trace!("parsed endpoint:{:?}", endpoint); + endpoints.push(TopologicalUSBDescriptorEndpoint::Standard(endpoint)) + } + _ => {} + } + continue; + } + + match self.metadata { + ParserMetaData::UVC(_) => { + if let Some(UVCDescriptorTypes::UVCClassSpecVideoControlInterruptEndpoint) = + self.peek_uvc_desc_type() + { + trace!("uvc interrupt endpoint!"); + match self.parse_any_descriptor().unwrap() { + USBDescriptor::UVCClassSpecVideoControlInterruptEndpoint(ep) => { + trace!("got {:?}", ep); + endpoints.push(TopologicalUSBDescriptorEndpoint::UNVVideoControlInterruptEndpoint(ep)); + } + _ => { + panic!("impossible!"); + } + } + continue; + } else { + trace!("not uvc data!"); + } + } + _ => {} + } + + break; + } + endpoints + } +} diff --git a/crates/driver_usb/src/usb/descriptors/topological_desc.rs b/crates/driver_usb/src/usb/descriptors/topological_desc.rs new file mode 100644 index 0000000000..8cc5267495 --- /dev/null +++ b/crates/driver_usb/src/usb/descriptors/topological_desc.rs @@ -0,0 +1,47 @@ +use alloc::vec::Vec; + +use super::{ + desc_configuration::Configuration, + desc_device::Device, + desc_endpoint::Endpoint, + desc_interface::{Interface, InterfaceAssociation}, + desc_uvc::uvc_endpoints::UVCVideoControlInterruptEndpoint, + parser::ParserMetaData, + USBDescriptor, +}; + +#[derive(Clone, Debug)] +pub struct TopologicalUSBDescriptorDevice { + pub data: Device, + pub child: Vec, +} + +#[derive(Clone, Debug)] +pub struct TopologicalUSBDescriptorConfiguration { + pub data: Configuration, + pub child: Vec, +} + +#[derive(Clone, Debug)] +pub enum TopologicalUSBDescriptorFunction { + InterfaceAssociation((InterfaceAssociation, Vec)), //maybe we would have multi layer compose device in future? for now just treat it as a trick! + Interface( + Vec<( + Interface, + Vec, + Vec, + )>, + ), +} +#[derive(Clone, Debug)] +pub struct TopologicalUSBDescriptorRoot { + pub device: Vec, + pub others: Vec, + pub metadata: ParserMetaData, +} + +#[derive(Clone, Debug)] +pub enum TopologicalUSBDescriptorEndpoint { + Standard(Endpoint), + UNVVideoControlInterruptEndpoint(UVCVideoControlInterruptEndpoint), +} diff --git a/crates/driver_usb/src/usb/drivers/driverapi.rs b/crates/driver_usb/src/usb/drivers/driverapi.rs new file mode 100644 index 0000000000..cb9c1fc084 --- /dev/null +++ b/crates/driver_usb/src/usb/drivers/driverapi.rs @@ -0,0 +1,42 @@ +use core::fmt::Debug; + +use alloc::{sync::Arc, vec::Vec}; +use spinlock::SpinNoIrq; +use xhci::ring::trb::event; + +use crate::{ + abstractions::PlatformAbstractions, + glue::{driver_independent_device_instance::DriverIndependentDeviceInstance, ucb::UCB}, + usb::urb::URB, + USBSystemConfig, +}; + +pub trait USBSystemDriverModule<'a, O>: Send + Sync +where + O: PlatformAbstractions, +{ + fn should_active( + &self, + independent_dev: &mut DriverIndependentDeviceInstance, + config: Arc>>, + ) -> Option>>>>; + + fn preload_module(&self); +} + +pub trait USBSystemDriverModuleInstance<'a, O>: Send + Sync +where + O: PlatformAbstractions, +{ + fn prepare_for_drive(&mut self) -> Option>>; + + fn prepare_for_drive1(&mut self) -> Option>>; + + fn gather_urb(&mut self) -> Option>>; + + fn gather_urb1(&mut self) -> Option>>; + + fn gather_urb2(&mut self) -> Option>>; + + fn receive_complete_event(&mut self, ucb: UCB); +} diff --git a/crates/driver_usb/src/usb/drivers/mod.rs b/crates/driver_usb/src/usb/drivers/mod.rs new file mode 100644 index 0000000000..cb8fbf1fe1 --- /dev/null +++ b/crates/driver_usb/src/usb/drivers/mod.rs @@ -0,0 +1,84 @@ +use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use driverapi::USBSystemDriverModuleInstance; +use spinlock::SpinNoIrq; + +use crate::{ + abstractions::PlatformAbstractions, + glue::driver_independent_device_instance::DriverIndependentDeviceInstance, USBSystemConfig, +}; + +use self::driverapi::USBSystemDriverModule; + +use super::urb::URB; + +pub mod driverapi; + +pub struct DriverContainers<'a, O> +where + O: PlatformAbstractions, +{ + drivers: Vec>>, +} + +impl<'a, O> DriverContainers<'a, O> +where + O: PlatformAbstractions, +{ + pub fn new() -> Self { + DriverContainers { + drivers: Vec::new(), + } + } + + pub fn load_driver(&mut self, mut module: Box>) { + self.drivers.push(module) + } + + pub fn create_for_device( + &mut self, + device: &mut DriverIndependentDeviceInstance, + config: Arc>>, + preparing_list: &mut Vec>>, + ) -> Vec>>> { + let collect = self + .drivers + .iter() + .filter_map(|module| module.should_active(device, config.clone())) + .flat_map(|a| a) + .inspect(|a| { + let sender = a.clone(); + if let Some(mut prep_list) = a.lock().prepare_for_drive() { + prep_list + .iter_mut() + .for_each(|urb| urb.set_sender(sender.clone())); + preparing_list.push(prep_list) + } + }) + .collect(); + collect + } + + pub fn create_for_device1( + &mut self, + device: &mut DriverIndependentDeviceInstance, + config: Arc>>, + preparing_list: &mut Vec>>, + ) -> Vec>>> { + let collect = self + .drivers + .iter() + .filter_map(|module| module.should_active(device, config.clone())) + .flat_map(|a| a) + .inspect(|a| { + let sender = a.clone(); + if let Some(mut prep_list) = a.lock().prepare_for_drive1() { + prep_list + .iter_mut() + .for_each(|urb| urb.set_sender(sender.clone())); + preparing_list.push(prep_list) + } + }) + .collect(); + collect + } +} diff --git a/crates/driver_usb/src/usb/mod.rs b/crates/driver_usb/src/usb/mod.rs new file mode 100644 index 0000000000..5ef160c111 --- /dev/null +++ b/crates/driver_usb/src/usb/mod.rs @@ -0,0 +1,140 @@ +pub mod drivers; +pub mod operation; +use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use drivers::driverapi::{USBSystemDriverModule, USBSystemDriverModuleInstance}; +use log::trace; +use spinlock::SpinNoIrq; +use urb::URB; + +use crate::{ + abstractions::PlatformAbstractions, + glue::driver_independent_device_instance::DriverIndependentDeviceInstance, USBSystemConfig, +}; + +use self::drivers::DriverContainers; + +pub mod descriptors; +pub mod trasnfer; +pub mod urb; + +#[cfg(feature = "packed_drivers")] +pub(crate) mod universal_drivers; + +pub struct USBDriverSystem<'a, O> +where + O: PlatformAbstractions, +{ + config: Arc>>, + managed_modules: DriverContainers<'a, O>, + driver_device_instances: Vec>>>, +} + +impl<'a, O> USBDriverSystem<'a, O> +where + O: PlatformAbstractions + 'static, +{ + pub fn new(config: Arc>>) -> Self { + Self { + config, + managed_modules: DriverContainers::new(), + driver_device_instances: Vec::new(), + } + } + + pub fn init(&mut self) { + #[cfg(feature = "packed_drivers")] + { + self.managed_modules.load_driver(Box::new( + universal_drivers::hid_drivers::hid_mouse::HidMouseDriverModule, + )); + + self.managed_modules.load_driver(Box::new( + universal_drivers::uvc_drivers::generic_uvc::GenericUVCDriverModule, + )); + + self.managed_modules.load_driver(Box::new( + universal_drivers::ch341_drivers::ch341::CH341driverModule, + )); + } + + trace!("usb system driver modules load complete!") + } + + /** + * this method should invoked after driver independent devices created + */ + pub fn init_probe( + &mut self, + devices: &mut Vec>, + preparing_list: &mut Vec>>, + ) { + devices + .iter_mut() + .flat_map(|device| { + self.managed_modules + .create_for_device(device, self.config.clone(), preparing_list) + }) + .collect_into(&mut self.driver_device_instances); + trace!( + "current driver managed device num: {}", + self.driver_device_instances.len() + ) + } + + pub fn init_probe1( + &mut self, + devices: &mut Vec>, + preparing_list: &mut Vec>>, + ) { + devices + .iter_mut() + .flat_map(|device| { + self.managed_modules + .create_for_device1(device, self.config.clone(), preparing_list) + }) + .collect_into(&mut self.driver_device_instances); + trace!( + "current driver managed device num: {}", + self.driver_device_instances.len() + ) + } + + pub fn tick(&mut self) -> Vec>> { + self.driver_device_instances + .iter() + .filter_map(|drv_dev| { + drv_dev.lock().gather_urb().map(|mut vec| { + vec.iter_mut() + .for_each(|urb| urb.set_sender(drv_dev.clone())); + vec + }) + }) + .collect() + } + + pub fn tick1(&mut self) -> Vec>> { + self.driver_device_instances + .iter() + .filter_map(|drv_dev| { + drv_dev.lock().gather_urb1().map(|mut vec| { + vec.iter_mut() + .for_each(|urb| urb.set_sender(drv_dev.clone())); + vec + }) + }) + .collect() + } + + pub fn tick2(&mut self) -> Vec>> { + self.driver_device_instances + .iter() + .filter_map(|drv_dev| { + drv_dev.lock().gather_urb2().map(|mut vec| { + vec.iter_mut() + .for_each(|urb| urb.set_sender(drv_dev.clone())); + vec + }) + }) + .collect() + } +} diff --git a/crates/driver_usb/src/usb/operation/mod.rs b/crates/driver_usb/src/usb/operation/mod.rs new file mode 100644 index 0000000000..012e951f05 --- /dev/null +++ b/crates/driver_usb/src/usb/operation/mod.rs @@ -0,0 +1,24 @@ +use super::descriptors::topological_desc::TopologicalUSBDescriptorConfiguration; + +#[derive(Debug, Clone)] +pub enum Configuration<'a> { + SetupDevice(&'a TopologicalUSBDescriptorConfiguration), + SwitchInterface(InterfaceNumber, AltnativeNumber), + SwitchConfig(ConfigurationID, InterfaceNumber), + ResetEndpoint(EndpointIndex), +} + +pub type ConfigurationID = usize; +pub type InterfaceNumber = usize; +pub type AltnativeNumber = usize; + +#[derive(Debug, Clone)] +pub enum ExtraStep { + PrepareForTransfer(EndpointIndex), +} +pub type EndpointIndex = usize; + +#[derive(Debug, Clone)] +pub enum Debugop { + DumpDevice, +} diff --git a/crates/driver_usb/src/usb/trasnfer/bulk.rs b/crates/driver_usb/src/usb/trasnfer/bulk.rs new file mode 100644 index 0000000000..3ca25705db --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/bulk.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Clone)] +pub struct BulkTransfer { + pub endpoint_id: usize, + pub buffer_addr_len: (usize, usize), +} diff --git a/crates/driver_usb/src/usb/trasnfer/control.rs b/crates/driver_usb/src/usb/trasnfer/control.rs new file mode 100644 index 0000000000..c541e7b13e --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/control.rs @@ -0,0 +1,107 @@ +use alloc::vec::Vec; +use const_enum::ConstEnum; +use num_derive::ToPrimitive; +use xhci::ring::trb::transfer::Direction; + +use crate::abstractions::{dma::DMA, PlatformAbstractions}; + +#[derive(Debug, Clone)] +pub struct ControlTransfer { + pub request_type: bmRequestType, + pub request: bRequest, + pub index: u16, + pub value: u16, + pub data: Option<(usize, usize)>, +} + +#[derive(Debug, Clone)] +#[allow(non_camel_case_types)] +pub enum bRequest { + Generic(StandardbRequest), + DriverSpec(u8), +} + +impl From for bRequest { + fn from(value: StandardbRequest) -> Self { + Self::Generic(value) + } +} + +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Debug, Clone)] +pub enum StandardbRequest { + GetStatus = 0, + ClearFeature = 1, + SetFeature = 3, + SetAddress = 5, + GetDescriptor = 6, + SetDescriptor = 7, + GetConfiguration = 8, + SetConfiguration = 9, + GetInterface = 10, + SetInterface = 11, + SynchFrame = 12, + SetEncryption = 13, + GetEncryption = 14, + SetHandshake = 15, + GetHandshake = 16, + SetConnection = 17, + SetSecurityData = 18, + GetSecurityData = 19, + SetWusbData = 20, + LoopbackDataWrite = 21, + LoopbackDataRead = 22, + SetInterfaceDs = 23, + GetFwStatus = 26, + SetFwStatus = 27, + SetSel = 48, + SetIsochDelay = 49, +} + +#[allow(non_camel_case_types)] +#[repr(C, packed)] +#[derive(Debug, Clone)] +pub struct bmRequestType { + pub direction: Direction, + pub transfer_type: DataTransferType, + pub recipient: Recipient, +} + +impl bmRequestType { + pub fn new( + direction: Direction, + transfer_type: DataTransferType, + recipient: Recipient, + ) -> bmRequestType { + bmRequestType { + direction, + transfer_type, + recipient, + } + } +} + +impl From for u8 { + fn from(value: bmRequestType) -> Self { + (value.direction as u8) << 7 | (value.transfer_type as u8) << 5 | value.recipient as u8 + } +} + +#[derive(ConstEnum, Copy, Clone, Debug)] +#[repr(u8)] +pub enum DataTransferType { + Standard = 0, + Class = 1, + Vendor = 2, + Reserved = 3, +} + +#[derive(ConstEnum, Copy, Clone, Debug)] +#[repr(u8)] +pub enum Recipient { + Device = 0, + Interface = 1, + Endpoint = 2, + Other = 3, +} diff --git a/crates/driver_usb/src/usb/trasnfer/endpoints/mod.rs b/crates/driver_usb/src/usb/trasnfer/endpoints/mod.rs new file mode 100644 index 0000000000..5781610c1e --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/endpoints/mod.rs @@ -0,0 +1 @@ +use const_enum::ConstEnum; diff --git a/crates/driver_usb/src/usb/trasnfer/interrupt.rs b/crates/driver_usb/src/usb/trasnfer/interrupt.rs new file mode 100644 index 0000000000..9c1ad4cff7 --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/interrupt.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Clone)] +pub struct InterruptTransfer { + pub endpoint_id: usize, + pub buffer_addr_len: (usize, usize), +} diff --git a/crates/driver_usb/src/usb/trasnfer/isoch.rs b/crates/driver_usb/src/usb/trasnfer/isoch.rs new file mode 100644 index 0000000000..177aa69ab7 --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/isoch.rs @@ -0,0 +1,7 @@ +#[derive(Debug, Clone)] +pub struct IsochTransfer { + pub endpoint_id: usize, + pub buffer_addr_len: (usize, usize), + pub request_times: usize, + pub packet_size: usize, +} diff --git a/crates/driver_usb/src/usb/trasnfer/mod.rs b/crates/driver_usb/src/usb/trasnfer/mod.rs new file mode 100644 index 0000000000..46e5110c15 --- /dev/null +++ b/crates/driver_usb/src/usb/trasnfer/mod.rs @@ -0,0 +1,5 @@ +pub mod isoch; +pub mod interrupt; +pub mod endpoints; +pub mod control; +pub mod bulk; diff --git a/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/ch341.rs b/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/ch341.rs new file mode 100644 index 0000000000..2d4d99b1e2 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/ch341.rs @@ -0,0 +1,584 @@ +use core::mem::MaybeUninit; + +use alloc::sync::Arc; +use alloc::vec; +use alloc::vec::Vec; +use log::trace; +use num_traits::FromPrimitive; +use spinlock::SpinNoIrq; +use xhci::context::EndpointType; +use xhci::ring::trb::transfer::Direction; + +use crate::abstractions::dma::DMA; +use crate::glue::ucb::{TransferEventCompleteCode, UCB}; +use crate::usb::descriptors::desc_hid::HIDDescriptorTypes; +use crate::usb::descriptors::topological_desc::{ + TopologicalUSBDescriptorEndpoint, TopologicalUSBDescriptorFunction, +}; +use crate::usb::descriptors::USBStandardDescriptorTypes; +use crate::usb::operation::ExtraStep; +use crate::usb::trasnfer::bulk::BulkTransfer; +use crate::usb::trasnfer::control::{ + bRequest, bmRequestType, ControlTransfer, DataTransferType, Recipient, StandardbRequest, +}; +use crate::usb::trasnfer::interrupt::InterruptTransfer; +use crate::usb::universal_drivers::BasicSendReceiveStateMachine; +use crate::usb::urb::{RequestedOperation, URB}; +use crate::USBSystemConfig; +use crate::{ + abstractions::PlatformAbstractions, + glue::driver_independent_device_instance::DriverIndependentDeviceInstance, + host::data_structures::MightBeInited, + usb::{ + descriptors::{desc_device::StandardUSBDeviceClassCode, desc_endpoint::Endpoint}, + drivers::driverapi::{USBSystemDriverModule, USBSystemDriverModuleInstance}, + }, +}; + +pub struct CH341driverModule; + +impl<'a, O> USBSystemDriverModule<'a, O> for CH341driverModule +where + O: PlatformAbstractions + 'static, +{ + fn should_active( + &self, + independent_dev: &mut DriverIndependentDeviceInstance, + config: Arc>>, + ) -> Option>>>> { + if let MightBeInited::Inited(desc) = &*independent_dev.descriptors { + if desc.device.iter().any(|desc| desc.data.class == 255) { + if let Some(device1) = desc.device.get(0) { + if let Some(child1) = device1.child.get(0) { + if let Some(child2) = child1.child.get(0) { + match child2 { + TopologicalUSBDescriptorFunction::Interface(interface_data) => { + for (interface, usb_descriptors, endpoints) in interface_data { + if interface.interface_class == 255 { + return Some( + (vec![CH341driver::new_and_init( + independent_dev.slotid, + device1.data.protocol, + { + device1 + .child + .iter() + .find(|c| { + c.data.config_val() == independent_dev.configuration_val as u8 + }) + .expect("configuration not found") + .child + .iter() + .filter_map(|func| match func { + TopologicalUSBDescriptorFunction::InterfaceAssociation(_) => { + panic!("a super complex device, help meeeeeeeee!"); + } + TopologicalUSBDescriptorFunction::Interface(interface) => Some( + interface + .iter() + .find(|(interface, alternatives, endpoints)| { + interface.interface_number + == independent_dev.interface_val as u8 + && interface.alternate_setting + == independent_dev + .current_alternative_interface_value + as u8 + }) + .expect("invalid interface value or alternative value") + .2 + .clone(), + ), + }) + .take(1) + .flat_map(|a| a) + .filter_map(|e| { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = e { + Some(ep) + } else { + None + } + }) + .collect() + }, + config.clone(), + independent_dev.interface_val, + independent_dev + .current_alternative_interface_value, + independent_dev.configuration_val, + )]), + ); + }; + } + } + _ => (), + } + } + } + } + } + } + None + } + + fn preload_module(&self) { + trace!("nothing"); + } +} + +pub struct CH341driver +where + O: PlatformAbstractions, +{ + config: Arc>>, + bootable: usize, + device_slot_id: usize, + interrupt_in_channels: Vec, + interrupt_out_channels: Vec, + bulk_in_channels: Vec, + bulk_out_channels: Vec, + interface_value: usize, //temporary place them here + interface_alternative_value: usize, + config_value: usize, // same + driver_state_machine: BasicSendReceiveStateMachine, + receiption_buffer: Option>>, + baud_rate: usize, /* set baud rate */ + mcr: u8, + msr: u8, + lcr: u8, + quirks: usize, + version: u8, + break_end: usize, +} + +impl<'a, O> CH341driver +where + O: PlatformAbstractions + 'static, +{ + fn new_and_init( + device_slot_id: usize, + bootable: u8, + endpoints: Vec, + config: Arc>>, + interface_value: usize, + alternative_val: usize, + config_value: usize, + ) -> Arc>> { + Arc::new(SpinNoIrq::new(Self { + device_slot_id, + interrupt_in_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::InterruptIn => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + interrupt_out_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::InterruptOut => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + bulk_in_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::BulkIn => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + bulk_out_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::InterruptOut => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + config, + interface_value, + config_value, + interface_alternative_value: alternative_val, + bootable: bootable as usize, + driver_state_machine: BasicSendReceiveStateMachine::Sending, + receiption_buffer: None, + baud_rate: 0, + mcr: 0, + msr: 0, + lcr: 0, + quirks: 0, + version: 0, + break_end: 0, + })) + } +} + +impl<'a, O> USBSystemDriverModuleInstance<'a, O> for CH341driver +where + O: PlatformAbstractions, +{ + fn prepare_for_drive(&mut self) -> Option>> { + let last = self.interrupt_in_channels.last().unwrap(); + let endpoint_in = last; + let mut todo_list = Vec::new(); + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Standard, + Recipient::Device, + ), + request: StandardbRequest::SetConfiguration.into(), + index: self.interface_value as u16, + value: self.config_value as u16, + data: None, + }), + )); + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Standard, + Recipient::Interface, + ), + request: StandardbRequest::SetInterface.into(), + index: self.interface_alternative_value as u16, + value: self.interface_value as u16, + data: None, + }), + )); + + if self.bootable > 0 { + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Class, + Recipient::Interface, + ), + request: StandardbRequest::SetInterface.into(), //actually set protocol + index: if self.bootable == 2 { 1 } else { 0 }, + value: self.interface_value as u16, + data: None, + }), + )); + } + + self.interrupt_in_channels + .iter() + .chain(self.interrupt_out_channels.iter()) + .for_each(|dci| { + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::ExtraStep(ExtraStep::PrepareForTransfer(*dci as _)), + )); + }); + + Some(todo_list) + } + + fn prepare_for_drive1(&mut self) -> Option>> { + let last = self.interrupt_in_channels.last().unwrap(); + let endpoint_in = last; + let mut todo_list = Vec::new(); + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0xA1), + index: 0 as u16, + value: 0 as u16, + data: None, + }), + )); + let mut rate: usize = 9600; + let mut lcr: u8 = 0x80 | 0x40 | 0x03; + let mut factor: u32 = (1532620800 / rate).try_into().unwrap(); + let mut divisor: u16 = 3; + while (factor > 0xfff0) && (divisor > 0) { + factor >>= 3; + divisor -= 1; + } + if factor > 0xfff0 { + trace!("factor wrror"); + } + factor = 0x10000 - factor; + let mut a: u16 = (factor & 0xff00) as u16 | divisor; + a |= 1 << 7; + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x9A), + index: a as u16, + value: 0x1312 as u16, + data: None, + }), + )); + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x9A), + index: lcr as u16, + value: 0x2518 as u16, + data: None, + }), + )); + let mut mcr = self.mcr; + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0xA4), + index: !mcr as u16, + value: 0 as u16, + data: None, + }), + )); + let mut rate: usize = 9600; + let mut factor: u32 = (1532620800 / rate).try_into().unwrap(); + let mut divisor: u16 = 3; + while (factor > 0xfff0) && (divisor > 0) { + factor >>= 3; + divisor -= 1; + } + if factor > 0xfff0 { + trace!("factor wrror"); + } + factor = 0x10000 - factor; + let mut a: u16 = (factor & 0xff00) as u16 | divisor; + a |= 1 << 7; + + let mut lcr: u8 = 0x80 | 0x40; + let nDataBits:u8 = 8; + let nParity:u8 = 0; + let nStopBits:u8 = 1; + + match nDataBits { + 5 => lcr |= 0x00, + 6 => lcr |= 0x01, + 7 => lcr |= 0x02, + 8 => lcr |= 0x03, + _ => (), + } + + match nParity { + 1 => lcr |= 0x08, + 2 => lcr |= 0x08 | 0x10, + _ => (), + } + + if nStopBits == 2 { + lcr |= 0x04; + } + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x9A), + index: a as u16, + value: 0x1312 as u16, + data: None, + }), + )); + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x9A), + index: lcr as u16, + value: 0x2518 as u16, + data: None, + }), + )); + self.baud_rate = rate; + self.lcr = lcr; + mcr |= (1 << 5)|(1 << 6); + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0xA4), + index: !mcr as u16, + value: 0 as u16, + data: None, + }), + )); + self.mcr = mcr; + Some(todo_list) + } + + fn gather_urb(&mut self) -> Option>> { + match self.driver_state_machine { + BasicSendReceiveStateMachine::Waiting => None, + BasicSendReceiveStateMachine::Sending => { + self.driver_state_machine = BasicSendReceiveStateMachine::Waiting; + match &self.receiption_buffer { + Some(buffer) => buffer.lock().fill_with(|| 0u8), + None => { + self.receiption_buffer = Some(SpinNoIrq::new(DMA::new_vec( + 0u8, + 8, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ))) + } + } + + if let Some(buffer) = &mut self.receiption_buffer { + trace!("some!"); + return Some(vec![URB::::new( + self.device_slot_id, + RequestedOperation::Interrupt(InterruptTransfer { + endpoint_id: self.interrupt_in_channels.last().unwrap().clone() + as usize, + buffer_addr_len: buffer.lock().addr_len_tuple(), + }), + )]); + } + None + } + } + } + + fn gather_urb1(&mut self) -> Option>> { + match self.driver_state_machine { + BasicSendReceiveStateMachine::Waiting => None, + BasicSendReceiveStateMachine::Sending => { + self.driver_state_machine = BasicSendReceiveStateMachine::Waiting; + match &self.receiption_buffer { + Some(buffer) => buffer.lock().fill_with(|| 0u8), + None => { + self.receiption_buffer = Some(SpinNoIrq::new(DMA::new_vec( + 0u8, + 8, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ))) + } + } + + if let Some(buffer) = &mut self.receiption_buffer { + trace!("some!"); + return Some(vec![URB::::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x5F), + index: 0 as u16, + value: 0 as u16, + data: None, + }), + )]); + } + None + } + } + } + + fn gather_urb2(&mut self) -> Option>> { + match self.driver_state_machine { + BasicSendReceiveStateMachine::Waiting => None, + BasicSendReceiveStateMachine::Sending => { + self.driver_state_machine = BasicSendReceiveStateMachine::Waiting; + match &self.receiption_buffer { + Some(buffer) => buffer.lock().fill_with(|| 0u8), + None => { + self.receiption_buffer = Some(SpinNoIrq::new(DMA::new_vec( + 0u8, + 8, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ))) + } + } + + if let Some(buffer) = &mut self.receiption_buffer { + trace!("some!"); + return Some(vec![URB::::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Vendor, + Recipient::Device, + ), + request: bRequest::DriverSpec(0x95), + index: 0 as u16, + value: 0x0706 as u16, + data: None, + }), + )]); + } + None + } + } + } + + fn receive_complete_event(&mut self, ucb: UCB) { + match ucb.code { + crate::glue::ucb::CompleteCode::Event(TransferEventCompleteCode::Success) => { + trace!("completed!"); + self.receiption_buffer + .as_ref() + .map(|a| a.lock().to_vec().clone()) + .inspect(|a| { + trace!("-------------------------------------------------------------"); + trace!("current buffer:{:?}", a); + trace!("-------------------------------------------------------------"); + }); + self.driver_state_machine = BasicSendReceiveStateMachine::Sending + } + other => panic!("received {:?}", other), + } + } +} + diff --git a/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/mod.rs b/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/mod.rs new file mode 100644 index 0000000000..ffa66b2516 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/ch341_drivers/mod.rs @@ -0,0 +1,3 @@ + + +pub mod ch341; \ No newline at end of file diff --git a/crates/driver_usb/src/usb/universal_drivers/hid_drivers/hid_mouse.rs b/crates/driver_usb/src/usb/universal_drivers/hid_drivers/hid_mouse.rs new file mode 100644 index 0000000000..97b8a1abf4 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/hid_drivers/hid_mouse.rs @@ -0,0 +1,417 @@ +use core::mem::MaybeUninit; + +use alloc::sync::Arc; +use alloc::vec; +use alloc::vec::Vec; +use log::trace; +use num_traits::FromPrimitive; +use spinlock::SpinNoIrq; +use xhci::context::EndpointType; +use xhci::ring::trb::transfer::Direction; + +use crate::abstractions::dma::DMA; +use crate::glue::ucb::{TransferEventCompleteCode, UCB}; +use crate::usb::descriptors::desc_hid::HIDDescriptorTypes; +use crate::usb::descriptors::topological_desc::{ + TopologicalUSBDescriptorEndpoint, TopologicalUSBDescriptorFunction, +}; +use crate::usb::descriptors::USBStandardDescriptorTypes; +use crate::usb::operation::ExtraStep; +use crate::usb::trasnfer::control::{ + bmRequestType, ControlTransfer, DataTransferType, Recipient, StandardbRequest, +}; +use crate::usb::trasnfer::interrupt::InterruptTransfer; +use crate::usb::universal_drivers::BasicSendReceiveStateMachine; +use crate::usb::urb::{RequestedOperation, URB}; +use crate::USBSystemConfig; +use crate::{ + abstractions::PlatformAbstractions, + glue::driver_independent_device_instance::DriverIndependentDeviceInstance, + host::data_structures::MightBeInited, + usb::{ + descriptors::{desc_device::StandardUSBDeviceClassCode, desc_endpoint::Endpoint}, + drivers::driverapi::{USBSystemDriverModule, USBSystemDriverModuleInstance}, + }, +}; + +use super::USBHidDeviceSubClassCode; + +pub enum ReportDescState +where + O: PlatformAbstractions, +{ + Binary(SpinNoIrq>), +} + +pub struct HidMouseDriver +//Driver should had a copy of independent device,at least should had ref of interface/config val and descriptors +where + O: PlatformAbstractions, +{ + config: Arc>>, + + bootable: usize, + device_slot_id: usize, + interrupt_in_channels: Vec, + interrupt_out_channels: Vec, + interface_value: usize, //temporary place them here + interface_alternative_value: usize, + config_value: usize, // same + report_descriptor: Option>, + driver_state_machine: BasicSendReceiveStateMachine, + receiption_buffer: Option>>, +} + +impl<'a, O> HidMouseDriver +where + O: PlatformAbstractions + 'static, +{ + fn new_and_init( + device_slot_id: usize, + bootable: u8, + endpoints: Vec, + config: Arc>>, + interface_value: usize, + alternative_val: usize, + config_value: usize, + ) -> Arc>> { + Arc::new(SpinNoIrq::new(Self { + device_slot_id, + interrupt_in_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::InterruptIn => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + interrupt_out_channels: { + endpoints + .iter() + .filter_map(|ep| match ep.endpoint_type() { + EndpointType::InterruptOut => Some(ep.doorbell_value_aka_dci()), + _ => None, + }) + .collect() + }, + config, + interface_value, + config_value, + interface_alternative_value: alternative_val, + bootable: bootable as usize, + report_descriptor: None, + driver_state_machine: BasicSendReceiveStateMachine::Sending, + receiption_buffer: None, + })) + } +} + +impl<'a, O> USBSystemDriverModuleInstance<'a, O> for HidMouseDriver +where + O: PlatformAbstractions, +{ + fn gather_urb(&mut self) -> Option>> { + match self.driver_state_machine { + BasicSendReceiveStateMachine::Waiting => None, + BasicSendReceiveStateMachine::Sending => { + self.driver_state_machine = BasicSendReceiveStateMachine::Waiting; + match &self.receiption_buffer { + Some(buffer) => buffer.lock().fill_with(|| 0u8), + None => { + self.receiption_buffer = Some(SpinNoIrq::new(DMA::new_vec( + 0u8, + 8, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + ))) + } + } + + if let Some(buffer) = &mut self.receiption_buffer { + trace!("some!"); + return Some(vec![URB::::new( + self.device_slot_id, + RequestedOperation::Interrupt(InterruptTransfer { + endpoint_id: self.interrupt_in_channels.last().unwrap().clone() + as usize, + buffer_addr_len: buffer.lock().addr_len_tuple(), + }), + )]); + } + None + } + } + } + + fn receive_complete_event(&mut self, ucb: UCB) { + match ucb.code { + crate::glue::ucb::CompleteCode::Event(TransferEventCompleteCode::Success) => { + trace!("completed!"); + self.receiption_buffer + .as_ref() + .map(|a| a.lock().to_vec().clone()) + .inspect(|a| { + trace!("current buffer:{:?}", a); + }); + self.driver_state_machine = BasicSendReceiveStateMachine::Sending + } + other => panic!("received {:?}", other), + } + } + + fn prepare_for_drive(&mut self) -> Option>> { + trace!("hid mouse preparing for drive!"); + let endpoint_in = self.interrupt_in_channels.last().unwrap(); + let mut todo_list = Vec::new(); + + trace!( + "set interface for {},{}", + self.config_value, + self.interface_value + ); + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Standard, + Recipient::Device, + ), + request: StandardbRequest::SetConfiguration.into(), + index: self.interface_value as u16, + value: self.config_value as u16, + data: None, + }), + )); + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Standard, + Recipient::Interface, + ), + request: StandardbRequest::SetInterface.into(), + index: self.interface_alternative_value as u16, + value: self.interface_value as u16, + data: None, + }), + )); + + if self.bootable > 0 { + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::Out, + DataTransferType::Class, + Recipient::Interface, + ), + request: StandardbRequest::SetInterface.into(), //actually set protocol + index: if self.bootable == 2 { 1 } else { 0 }, + value: self.interface_value as u16, + data: None, + }), + )); + } + + self.report_descriptor = Some(ReportDescState::::Binary(SpinNoIrq::new(DMA::new( + 0u8, + O::PAGE_SIZE, + self.config.lock().os.dma_alloc(), + )))); + + if let Some(ReportDescState::Binary(buf)) = &self.report_descriptor { + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::Control(ControlTransfer { + request_type: bmRequestType::new( + Direction::In, + DataTransferType::Standard, + Recipient::Interface, + ), + request: StandardbRequest::GetDescriptor.into(), + index: self.interface_alternative_value as u16, + value: crate::usb::descriptors::construct_control_transfer_type( + HIDDescriptorTypes::HIDReport as u8, + 0, + ) + .bits(), + data: Some({ buf.lock().addr_len_tuple() }), + }), + )); + } + + self.interrupt_in_channels + .iter() + .chain(self.interrupt_out_channels.iter()) + .for_each(|dci| { + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::ExtraStep(ExtraStep::PrepareForTransfer(*dci as _)), + )); + }); + + Some(todo_list) + } + + fn prepare_for_drive1(&mut self) -> Option>>{ + todo!(); + } + + fn gather_urb1(&mut self) -> Option>>{ + todo!(); + } + + fn gather_urb2(&mut self) -> Option>> { + todo!(); + } +} + +pub struct HidMouseDriverModule; //TODO: Create annotations to register + +impl<'a, O> USBSystemDriverModule<'a, O> for HidMouseDriverModule +where + O: PlatformAbstractions + 'static, +{ + fn should_active( + &self, + independent_dev: &mut DriverIndependentDeviceInstance, + config: Arc>>, + ) -> Option>>>> { + if let MightBeInited::Inited(inited) = &*independent_dev.descriptors { + let device = inited.device.first().unwrap(); + return match ( + StandardUSBDeviceClassCode::from(device.data.class), + USBHidDeviceSubClassCode::from_u8(device.data.subclass), + device.data.protocol, + ) { + ( + StandardUSBDeviceClassCode::HID, + Some(USBHidDeviceSubClassCode::Mouse), + bootable, + ) => { + return Some(vec![HidMouseDriver::new_and_init( + independent_dev.slotid, + bootable, + { + device + .child + .iter() + .find(|c| { + c.data.config_val() == independent_dev.configuration_val as u8 + }) + .expect("configuration not found") + .child + .iter() + .filter_map(|func| match func { + TopologicalUSBDescriptorFunction::InterfaceAssociation(_) => { + panic!("a super complex device, help meeeeeeeee!"); + } + TopologicalUSBDescriptorFunction::Interface(interface) => Some( + interface + .iter() + .find(|(interface, alternatives, endpoints)| { + interface.interface_number + == independent_dev.interface_val as u8 + && interface.alternate_setting + == independent_dev + .current_alternative_interface_value + as u8 + }) + .expect("invalid interface value or alternative value") + .2 + .clone(), + ), + }) + .take(1) + .flat_map(|a| a) + .filter_map(|e| { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = e { + Some(ep) + } else { + None + } + }) + .collect() + }, + config.clone(), + independent_dev.interface_val, + independent_dev.current_alternative_interface_value, + independent_dev.configuration_val, + )]); + } + (StandardUSBDeviceClassCode::ReferInterfaceDescriptor, _, _) => { + Some({ + let collect = device + .child + .iter() + .find(|configuration| { + configuration.data.config_val() + == independent_dev.configuration_val as u8 + }) + .expect("configuration not found") + .child + .iter() + .filter_map(|interface| match interface { + TopologicalUSBDescriptorFunction::InterfaceAssociation(( + asso, + interfaces, + )) if let ( + StandardUSBDeviceClassCode::HID, + Some(USBHidDeviceSubClassCode::Mouse), + bootable, + ) = ( + StandardUSBDeviceClassCode::from(asso.function_class), + USBHidDeviceSubClassCode::from_u8(asso.function_subclass), + asso.function_protocol, + ) => + { + // return Some(Self::new_and_init(independent_dev.slotid, bootable)); + panic!("a super complex device, help meeeeeeeee!"); + } + TopologicalUSBDescriptorFunction::Interface(interfaces) => { + let (interface, additional, endpoints) = interfaces + .get(independent_dev.current_alternative_interface_value) + .expect("invalid anternative interface value"); + if let ( + StandardUSBDeviceClassCode::HID, + Some(USBHidDeviceSubClassCode::Mouse), + bootable, + ) = ( + StandardUSBDeviceClassCode::from(interface.interface_class), + USBHidDeviceSubClassCode::from_u8(interface.interface_subclass), + interface.interface_protocol, + ) { + return Some(HidMouseDriver::new_and_init( + independent_dev.slotid, + bootable, + endpoints.iter().filter_map(|e|if let TopologicalUSBDescriptorEndpoint::Standard(ep) = e{ + Some(ep.clone()) + }else {None}).collect(), + config.clone(), + independent_dev.interface_val, + independent_dev.current_alternative_interface_value, + independent_dev.configuration_val, + )); + } else { + None + } + } + _ => None, + }) + .collect(); + collect + }) + } + _ => None, + }; + } + None + } + + fn preload_module(&self) { + trace!("preloading Hid mouse driver!") + } +} diff --git a/crates/driver_usb/src/usb/universal_drivers/hid_drivers/mod.rs b/crates/driver_usb/src/usb/universal_drivers/hid_drivers/mod.rs new file mode 100644 index 0000000000..b50ffe40d9 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/hid_drivers/mod.rs @@ -0,0 +1,10 @@ +use const_enum::ConstEnum; +use num_derive::{FromPrimitive, ToPrimitive}; + +pub mod hid_mouse; + +#[derive(Copy, Clone, Debug, ToPrimitive, FromPrimitive)] +#[repr(u8)] +pub enum USBHidDeviceSubClassCode { + Mouse = 1, +} diff --git a/crates/driver_usb/src/usb/universal_drivers/mod.rs b/crates/driver_usb/src/usb/universal_drivers/mod.rs new file mode 100644 index 0000000000..ca50564f7a --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/mod.rs @@ -0,0 +1,14 @@ +pub mod hid_drivers; +pub mod uvc_drivers; +pub mod ch341_drivers; +pub enum BasicSendReceiveStateMachine { + Waiting, + Sending, +} + +pub enum BasicDriverLifeCycleStateMachine { + BeforeFirstSendAkaPreparingForDrive, + Driving, + Ending, + Sleeping, +} diff --git a/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/generic_uvc.rs b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/generic_uvc.rs new file mode 100644 index 0000000000..a56d78f3a4 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/generic_uvc.rs @@ -0,0 +1,452 @@ +use core::{fmt::Debug, mem::MaybeUninit}; + +use alloc::{collections::btree_map::BTreeMap, sync::Arc, vec, vec::Vec}; +use log::trace; +use spinlock::SpinNoIrq; +use xhci::{context::EndpointType, ring::trb::transfer::Direction}; + +use crate::{ + abstractions::{dma::DMA, PlatformAbstractions}, + glue::driver_independent_device_instance::DriverIndependentDeviceInstance, + host::data_structures::MightBeInited, + usb::{ + descriptors::{ + self, + desc_endpoint::Endpoint, + desc_interface::Interface, + desc_uvc::uvc_interfaces::{UVCInterface, UVCStreamingInterface}, + parser::ParserMetaData, + topological_desc::{ + TopologicalUSBDescriptorEndpoint, TopologicalUSBDescriptorFunction, + TopologicalUSBDescriptorRoot, + }, + USBDescriptor, + }, + drivers::driverapi::{USBSystemDriverModule, USBSystemDriverModuleInstance}, + operation::{Configuration, Debugop, ExtraStep}, + trasnfer::{ + control::{ + bmRequestType, ControlTransfer, DataTransferType, Recipient, StandardbRequest, + }, + isoch::IsochTransfer, + }, + universal_drivers::{BasicDriverLifeCycleStateMachine, BasicSendReceiveStateMachine}, + urb::{RequestedOperation, URB}, + }, + USBSystemConfig, +}; + +use super::{ + uvc_device_model::{ + UVCControlInterfaceModel, UVCControlInterfaceModelParser, UVCVSInterfaceModel, + }, + uvc_spec_transfer::UVCSpecBRequest, +}; + +pub struct GenericUVCDriverModule; //TODO: Create annotations to register +pub struct GenericUVCDriver +where + O: PlatformAbstractions, +{ + device_slot_id: usize, + config: Arc>>, + interrupt_endpoints: Vec, + isoch_endpoint: Option, + uvc_control_model: UVCControlInterfaceModel, + uvc_stream_model: UVCVSInterfaceModel, + alternative_settings: BTreeMap>, + interface_value: usize, //temporary place them here + interface_alternative_value: usize, + config_value: usize, // same + send_receive_state: BasicSendReceiveStateMachine, + lifecycle_machine: ExtraLifeCycle, + receiption_buffer: Option>>, +} + +impl<'a, O> USBSystemDriverModule<'a, O> for GenericUVCDriverModule +where + O: PlatformAbstractions + 'static, +{ + fn should_active( + &self, + independent_dev: &mut DriverIndependentDeviceInstance, + config: Arc>>, + ) -> Option>>>> { + if let MightBeInited::Inited(desc) = &*independent_dev.descriptors + && let ParserMetaData::UVC(_) = desc.metadata + { + let device = desc.device.first().unwrap(); + + independent_dev.interface_val = 1; + independent_dev.current_alternative_interface_value = 0; + Some(vec![GenericUVCDriver::new( + independent_dev.slotid, + config.clone(), + { + device + .child + .iter() + .find(|c| c.data.config_val() == independent_dev.configuration_val as u8) + .expect("configuration not found") + .child + .iter() + .filter_map(|func| match func { + TopologicalUSBDescriptorFunction::InterfaceAssociation(function) => { + Some(function.1.iter().filter_map(|f| match f { + TopologicalUSBDescriptorFunction::InterfaceAssociation(_) => { + panic!("currently, interface association cannot have association function child") + } + TopologicalUSBDescriptorFunction::Interface(func) => { + Some(func) + }, + }).flat_map(|a|a.clone()).collect::>()) + } + TopologicalUSBDescriptorFunction::Interface(_) => { + panic!("a uvc device is impossible had only one interface") + } + }).collect::>() + }, + independent_dev.interface_val, + independent_dev.current_alternative_interface_value, + independent_dev.configuration_val, + independent_dev.descriptors.clone(), + )]) + } else { + None + } + } + + fn preload_module(&self) { + trace!("loaded Generic UVC Driver Module!"); + } +} + +impl<'a, O> GenericUVCDriver +where + O: PlatformAbstractions + 'static, +{ + pub fn new( + device_slot_id: usize, + config: Arc>>, + function: Vec< + Vec<( + Interface, + Vec, + Vec, + )>, + >, + interface_value: usize, + alternative_val: usize, + config_value: usize, + descriptors: Arc>, + ) -> Arc>> { + let uvccontrol_interface_model = function + .iter() + .find_map(|a| { + a.iter().find(|b| { + b.1.iter().any(|interface| { + if let USBDescriptor::UVCInterface(UVCInterface::Control(_)) = interface { + true + } else { + false + } + }) + }) + }) + .map( + |control: &( + Interface, + Vec, + Vec, + )| UVCControlInterfaceModelParser::new(control).parse(), + ) + .expect("no control interface exist, is this broken?"); + + let uvc_stream_interface_model = function + .iter() + .find_map(|a| { + a.iter().find(|b| { + b.1.iter().any(|interface| { + if let USBDescriptor::UVCInterface(UVCInterface::Streaming(_)) = interface { + true + } else { + false + } + }) + }) + }) + .map( + |control: &( + Interface, + Vec, + Vec, + )| UVCVSInterfaceModel::new(control), + ) + .expect("no streaming interface exist, is this broken?"); + + let mut alternative_interface_endpoint: BTreeMap> = + BTreeMap::new(); + + function + .iter() + .filter_map(|a| { + a.iter().find(|(i, o, e)| { + o.is_empty() //yeah, this is a special point of uvc + }) + }) + .for_each(|(interface, _, endpoints)| { + endpoints + .iter() + .filter_map(|e| { + if let TopologicalUSBDescriptorEndpoint::Standard(ep) = e { + Some(ep) + } else { + None + } + }) + .for_each(|ep| { + alternative_interface_endpoint + .entry(ep.doorbell_value_aka_dci()) + .or_insert(Vec::new()) + .push((interface.clone(), ep.clone())) + }) + }); + + // trace!("goted function:{:#?}", function); + Arc::new(SpinNoIrq::new(Self { + config: config.clone(), + interrupt_endpoints: function + .iter() + .flat_map(|a| { + a.iter().flat_map(|b| { + b.2.iter() + .filter(|tep| { + match tep { + TopologicalUSBDescriptorEndpoint::Standard(ep) + if let EndpointType::InterruptIn = ep.endpoint_type() => + { + true + } + TopologicalUSBDescriptorEndpoint::UNVVideoControlInterruptEndpoint( + any, + ) => true, + _ => false, + } + }) + .map(|a| a.clone()) + }) + }) + .collect(), + interface_value, + interface_alternative_value: alternative_val, + config_value, + send_receive_state: BasicSendReceiveStateMachine::Sending, + lifecycle_machine: ExtraLifeCycle::STDWorking( + BasicDriverLifeCycleStateMachine::BeforeFirstSendAkaPreparingForDrive, + ), + device_slot_id, + uvc_control_model: uvccontrol_interface_model, + uvc_stream_model: uvc_stream_interface_model, + alternative_settings: alternative_interface_endpoint, + receiption_buffer: Some(SpinNoIrq::new(DMA::new_vec( + 0u8, + O::PAGE_SIZE, + O::PAGE_SIZE, + config.clone().lock().os.dma_alloc(), + ))), + isoch_endpoint: None, + })) + } + + pub fn determine_stream_interface(&mut self) { + // self.alternative_settings + // .iter() + // .filter_map(|(id, alternatives)| { + // alternatives + // .iter() + // .map(|(int, endp)| (id, int, endp)) + // .min_by(|(_, _, e1), (_, _, e2)| { + // let max_packet_size1 = e1.max_packet_size; + // let max_packet_size2 = e2.max_packet_size; + // max_packet_size1.cmp(&max_packet_size2) + // }) + // }) + // .last() + // .inspect(|(dci, interface, endpoint)| { + // trace!("founded!{:#?},{:#?}", interface, endpoint); + // self.interface_value = interface.interface_number as _; + // self.interface_alternative_value = interface.alternate_setting as _; + // }); + + self.alternative_settings + .iter() + .find_map(|(id, alternatives)| { + alternatives + .iter() + .map(|(int, endp)| (id, int, endp)) + .find(|(_, _, e1)| (e1.max_packet_size & 0x7ff) == 1024) + }) + .inspect(|(dci, interface, endpoint)| { + trace!("founded!{:#?},{:#?}", interface, endpoint); + self.interface_value = interface.interface_number as _; + self.interface_alternative_value = interface.alternate_setting as _; + self.isoch_endpoint = Some(**dci as _); + }); + } +} + +impl<'a, O> USBSystemDriverModuleInstance<'a, O> for GenericUVCDriver +where + O: PlatformAbstractions + 'static, +{ + fn prepare_for_drive(&mut self) -> Option>> { + // todo!(); + + let mut todo_list = Vec::new(); + + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::Control(ControlTransfer { + // request_type: bmRequestType::new( + // Direction::Out, + // DataTransferType::Class, + // Recipient::Interface, + // ), + // request: UVCSpecBRequest::SET_CUR.into(), + // index: (self.interface_value as u8) as u16, + // value: 1u16 << 8 | 0b00000000u16, + // data: todo!(), + // }), + // )); + + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::Debug(Debugop::DumpDevice), + // )); + + self.determine_stream_interface(); + + // self.alternative_settings.keys().for_each(|dci| { + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::ExtraStep(ExtraStep::PrepareForTransfer(*dci as _)), + // )) + // }); + + // // todo_list.push(URB::new( + // // self.device_slot_id, + // // RequestedOperation::Debug(Debugop::DumpDevice), + // // )); + + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::Control(ControlTransfer { + // request_type: bmRequestType::new( + // Direction::Out, + // DataTransferType::Standard, + // Recipient::Device, + // ), + // request: StandardbRequest::SetConfiguration.into(), + // index: 0, + // value: 1, + // data: None, + // }), + // )); + + todo_list.push(URB::new( + self.device_slot_id, + RequestedOperation::ConfigureDevice(Configuration::SwitchInterface( + self.interface_value, + self.interface_alternative_value, + )), + )); + + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::Control(ControlTransfer { + // request_type: bmRequestType::new( + // Direction::Out, + // DataTransferType::Class, + // Recipient::Interface, + // ), + // request: UVCSpecBRequest::SET_CUR.into(), + // index: (self.interface_value as u8) as u16, + // value: 1u16 << 8 | 0b00000000u16, + // data: todo!(), + // }), + // )); + + // if let Some(ReportDescState::Binary(buf)) = &self.report_descriptor { + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::Control(ControlTransfer { + // request_type: bmRequestType::new( + // Direction::In, + // DataTransferType::Standard, + // Recipient::Interface, + // ), + // request: bRequest::GetDescriptor, + // index: self.interface_alternative_value as u16, + // value: crate::usb::descriptors::construct_control_transfer_type( + // HIDDescriptorTypes::HIDReport as u8, + // 0, + // ) + // .bits(), + // data: Some({ buf.lock().addr_len_tuple() }), + // }), + // )); + // } + + // self.interrupt_in_channels + // .iter() + // .chain(self.interrupt_out_channels.iter()) + // .for_each(|dci| { + // todo_list.push(URB::new( + // self.device_slot_id, + // RequestedOperation::ExtraStep(ExtraStep::PrepareForTransfer(*dci as _)), + // )); + // }); + + Some(todo_list) + } + + fn gather_urb(&mut self) -> Option>> { + if let Some(buf) = &self.receiption_buffer { + let mut test = Vec::new(); + // todo!() //试试直接从端口获取? + test.push(URB::new( + self.device_slot_id, + RequestedOperation::Isoch(IsochTransfer { + endpoint_id: 3, + buffer_addr_len: buf.lock().addr_len_tuple(), + request_times: 3, + packet_size: 800, + }), + )); + Some(test) + } else { + None + } + } + + fn receive_complete_event(&mut self, ucb: crate::glue::ucb::UCB) { + trace!("received ucb:{:#?}", ucb.code) + } + + fn gather_urb1(&mut self) -> Option>> { + todo!(); + } + + fn prepare_for_drive1(&mut self) -> Option>> { + todo!(); + } + + fn gather_urb2(&mut self) -> Option>> { + todo!(); + } +} + +enum ExtraLifeCycle { + STDWorking(BasicDriverLifeCycleStateMachine), + ConfigureCS(u16), +} diff --git a/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/mod.rs b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/mod.rs new file mode 100644 index 0000000000..9a832334fe --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/mod.rs @@ -0,0 +1,3 @@ +pub mod uvc_device_model; +mod uvc_spec_transfer; +pub mod generic_uvc; diff --git a/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_device_model.rs b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_device_model.rs new file mode 100644 index 0000000000..ea7a4945c4 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_device_model.rs @@ -0,0 +1,205 @@ +use alloc::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + vec::Vec, +}; + +use crate::{ + err, + host::data_structures::MightBeInited, + usb::descriptors::{ + desc_endpoint::Endpoint, + desc_interface::Interface, + desc_uvc::{ + uvc_endpoints::UVCVideoControlInterruptEndpoint, + uvc_interfaces::{ + UVCControlInterface, UVCControlInterfaceExtensionUnit, UVCControlInterfaceHeader, + UVCControlInterfaceInputTerminal, UVCControlInterfaceOutputTerminal, + UVCControlInterfaceProcessingUnit, UVCInterface, UVCStreamingFormartInterface, + UVCStreamingFrameInterface, UVCStreamingInterface, UVCVSInterfaceFormatMJPEG, + UVCVSInterfaceInputHeader, + }, + }, + topological_desc::TopologicalUSBDescriptorEndpoint, + USBDescriptor, + }, +}; + +#[derive(Debug)] +pub struct UVCControlInterfaceModelParser { + pub header: Option, + pub outputs: Vec, + pub inputs: Vec, + pub units: Vec, + pub control_interrupt_endpoint: Option<(Endpoint, UVCVideoControlInterruptEndpoint)>, +} + +#[derive(Debug)] +pub struct UVCControlInterfaceModel { + pub header: UVCControlInterfaceHeader, + pub outputs: Vec, + pub inputs: Vec, + pub units: Vec, + pub control_interrupt_endpoint: Option<(Endpoint, UVCVideoControlInterruptEndpoint)>, +} + +#[derive(Debug)] +pub enum Unit { + ExtensionUnit(UVCControlInterfaceExtensionUnit), + ProcessingUnit(UVCControlInterfaceProcessingUnit), + EncodingUnit, //TODO + SelectorUnit, //TODO +} + +impl UVCControlInterfaceModelParser { + pub fn new( + (_, controls, interript_endpoint): &( + Interface, + Vec, + Vec, + ), + ) -> Self { + let mut uvccontrol_interface_model_parser = Self { + header: None, + outputs: Vec::new(), + inputs: Vec::new(), + units: Vec::new(), + control_interrupt_endpoint: None, + }; + + controls.iter().for_each(|c| match c { + USBDescriptor::UVCInterface(UVCInterface::Control(control)) => match control { + UVCControlInterface::Header(header) => { + uvccontrol_interface_model_parser.header = Some(header.clone()) + } + UVCControlInterface::OutputTerminal(output) => uvccontrol_interface_model_parser + .outputs + .push(output.clone()), + UVCControlInterface::InputTerminal(input) => { + uvccontrol_interface_model_parser.inputs.push(input.clone()) + } + UVCControlInterface::ExtensionUnit(ext) => uvccontrol_interface_model_parser + .units + .push(Unit::ExtensionUnit(ext.clone())), + UVCControlInterface::ProcessingUnit(processing) => { + uvccontrol_interface_model_parser + .units + .push(Unit::ProcessingUnit(processing.clone())) + } + }, + _ => panic!("error while parsing UVC control model!"), + }); + + if !interript_endpoint.is_empty() { + let mut interrupt_ep = None; + let mut interrupt_uvc_ep = None; + interript_endpoint.iter().for_each(|e| match e { + TopologicalUSBDescriptorEndpoint::Standard(interrupt) => { + interrupt_ep = Some(interrupt.clone()) + } + TopologicalUSBDescriptorEndpoint::UNVVideoControlInterruptEndpoint(ep) => { + interrupt_uvc_ep = Some(ep.clone()) + } + }); + uvccontrol_interface_model_parser.control_interrupt_endpoint = + Some((interrupt_ep.unwrap(), interrupt_uvc_ep.unwrap())); + }; + uvccontrol_interface_model_parser + } + + pub fn parse(self) -> UVCControlInterfaceModel { + UVCControlInterfaceModel { + header: self.header.unwrap(), + outputs: self.outputs, + inputs: self.inputs, + units: self.units, + control_interrupt_endpoint: self.control_interrupt_endpoint, + } + } +} + +/* + * TODO: + * StatusPacket-fetch from Interrupt endpoint, variable size, should refer page 30 to determine rest structure +*/ + +pub struct UVCVSInterfaceModel { + pub interface0_stream_desca: Interface, + pub input_header: UVCVSInterfaceInputHeader, + pub output_header: (), //todo! + pub formarts: Vec<( + UVCStreamingFormartInterface, + Vec, + )>, + pub still_frames: Vec, + pub colorformart: Vec, +} + +impl UVCVSInterfaceModel { + pub fn new( + (interface, controls, _): &( + Interface, + Vec, + Vec, + ), + ) -> Self { + let mut ret = Self { + interface0_stream_desca: interface.clone(), + input_header: controls + .iter() + .find_map(|a| match a { + USBDescriptor::UVCInterface(UVCInterface::Streaming( + UVCStreamingInterface::InputHeader(head), + )) => Some(head.clone()), + _ => None, + }) + .unwrap(), + output_header: (), + formarts: controls + .iter() + .filter_map(|a| match a { + USBDescriptor::UVCInterface(UVCInterface::Streaming(any)) => Some(any), + _ => None, + }) + .filter_map(UVCStreamingFormartInterface::filter_out_self) + .map(|formart| (formart, Vec::new())) + .collect(), + still_frames: Vec::new(), + colorformart: Vec::new(), + }; + + controls + .iter() + .filter_map(|a| match a { + USBDescriptor::UVCInterface(UVCInterface::Streaming(any)) => Some(any), + _ => None, + }) + .filter_map(UVCStreamingFrameInterface::filter_out_self) + .for_each(|any| { + ret.formarts.iter_mut().for_each(|(interface, v)| { + if interface.ismatch(&any) { + v.push(any.clone()) + } + }) + }); + + controls + .iter() + .filter_map(|a| match a { + USBDescriptor::UVCInterface(UVCInterface::Streaming(any)) => Some(any), + _ => None, + }) + .filter_map(UVCStreamingFrameInterface::filter_out_still) + .collect_into(&mut ret.still_frames); + + controls + .iter() + .filter_map(|a| match a { + USBDescriptor::UVCInterface(UVCInterface::Streaming(any)) => Some(any), + _ => None, + }) + .filter_map(UVCStreamingFormartInterface::filter_out_color_formart) + .collect_into(&mut ret.colorformart); + + ret + } +} diff --git a/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_spec_transfer.rs b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_spec_transfer.rs new file mode 100644 index 0000000000..899ff81fe6 --- /dev/null +++ b/crates/driver_usb/src/usb/universal_drivers/uvc_drivers/uvc_spec_transfer.rs @@ -0,0 +1,23 @@ +// + +use crate::usb::trasnfer::control::bRequest; + +#[allow(non_camel_case_types)] +#[repr(u8)] +#[derive(Debug, Clone)] +pub enum UVCSpecBRequest { + SET_CUR = 0b00000001, //设置属性 + GET_CUR = 0b10000001, //获取当前属性 + GET_MIN = 0b10000010, //获取最小设置属性 + GET_MAX = 0b10000011, //获取最大设置属性 + GET_RES = 0b10000100, //获取分辨率属性 + GET_LEN = 0b10000101, //获取数据长度属性 + GET_INF = 0b10000110, //获取设备支持的特定类请求属性 + GET_DEF = 0b10000111, //获取默认属性 +} + +impl From for bRequest { + fn from(value: UVCSpecBRequest) -> Self { + Self::DriverSpec(value as u8) + } +} diff --git a/crates/driver_usb/src/usb/urb.rs b/crates/driver_usb/src/usb/urb.rs new file mode 100644 index 0000000000..088c536cc6 --- /dev/null +++ b/crates/driver_usb/src/usb/urb.rs @@ -0,0 +1,52 @@ +use core::sync::atomic::AtomicUsize; + +use alloc::sync::Arc; +use log::trace; +use spinlock::{BaseSpinLock, SpinNoIrq}; +use xhci::ring::trb::event; + +use crate::PlatformAbstractions; + +use super::{ + drivers::driverapi::{USBSystemDriverModule, USBSystemDriverModuleInstance}, + operation::{Configuration, Debugop, ExtraStep}, + trasnfer::{bulk::BulkTransfer, control::ControlTransfer, interrupt::InterruptTransfer, isoch::IsochTransfer}, +}; + +#[derive(Clone)] +pub struct URB<'a, O> +where + O: PlatformAbstractions, +{ + pub device_slot_id: usize, + pub operation: RequestedOperation<'a>, + pub sender: Option>>>, +} + +impl<'a, O> URB<'a, O> +where + O: PlatformAbstractions, +{ + pub fn new(device_slot_id: usize, op: RequestedOperation<'a>) -> Self { + Self { + device_slot_id, + operation: op.clone(), + sender: None, + } + } + + pub fn set_sender(&mut self, sender: Arc>>) { + self.sender = Some(sender) + } +} + +#[derive(Debug, Clone)] +pub enum RequestedOperation<'a> { + ExtraStep(ExtraStep), + Control(ControlTransfer), + Bulk(BulkTransfer), + Interrupt(InterruptTransfer), + Isoch(IsochTransfer), + ConfigureDevice(Configuration<'a>), + Debug(Debugop), +} diff --git a/crates/driver_virtio/Cargo.toml b/crates/driver_virtio/Cargo.toml index 6131c34db7..f133167a9f 100644 --- a/crates/driver_virtio/Cargo.toml +++ b/crates/driver_virtio/Cargo.toml @@ -19,4 +19,4 @@ driver_common = { path = "../driver_common" } driver_block = { path = "../driver_block", optional = true } driver_net = { path = "../driver_net", optional = true } driver_display = { path = "../driver_display", optional = true} -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers.git", rev = "409ee72" } +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers.git", rev = "4b60f5d" } diff --git a/crates/driver_virtio/src/blk.rs b/crates/driver_virtio/src/blk.rs index 3edaa1a089..3afc9b40d6 100644 --- a/crates/driver_virtio/src/blk.rs +++ b/crates/driver_virtio/src/blk.rs @@ -44,13 +44,13 @@ impl BlockDriverOps for VirtIoBlkDev { fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult { self.inner - .read_block(block_id as _, buf) + .read_blocks(block_id as _, buf) .map_err(as_dev_err) } fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult { self.inner - .write_block(block_id as _, buf) + .write_blocks(block_id as _, buf) .map_err(as_dev_err) } diff --git a/crates/driver_virtio/src/gpu.rs b/crates/driver_virtio/src/gpu.rs index 1acc68841c..dd4e39410b 100644 --- a/crates/driver_virtio/src/gpu.rs +++ b/crates/driver_virtio/src/gpu.rs @@ -7,7 +7,7 @@ use virtio_drivers::{device::gpu::VirtIOGpu as InnerDev, transport::Transport, H /// The VirtIO GPU device driver. pub struct VirtIoGpuDev { - inner: InnerDev<'static, H, T>, + inner: InnerDev, info: DisplayInfo, } diff --git a/crates/driver_virtio/src/net.rs b/crates/driver_virtio/src/net.rs index e106f7e53f..207c9930fd 100644 --- a/crates/driver_virtio/src/net.rs +++ b/crates/driver_virtio/src/net.rs @@ -72,7 +72,7 @@ impl VirtIoNetDev { } } -impl const BaseDriverOps for VirtIoNetDev { +impl BaseDriverOps for VirtIoNetDev { fn device_name(&self) -> &str { "virtio-net" } @@ -90,12 +90,12 @@ impl NetDriverOps for VirtIoNetDev bool { - !self.free_tx_bufs.is_empty() && self.inner.can_transmit() + !self.free_tx_bufs.is_empty() && self.inner.can_send() } #[inline] fn can_receive(&self) -> bool { - self.inner.can_receive() + self.inner.poll_receive().is_some() } #[inline] diff --git a/crates/flatten_objects/src/lib.rs b/crates/flatten_objects/src/lib.rs index d5637f001d..f431371ec0b 100644 --- a/crates/flatten_objects/src/lib.rs +++ b/crates/flatten_objects/src/lib.rs @@ -30,7 +30,6 @@ //! ``` #![no_std] -#![feature(const_maybe_uninit_zeroed)] #![feature(maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_uninit_array)] diff --git a/crates/page_box/Cargo.toml b/crates/page_box/Cargo.toml new file mode 100644 index 0000000000..f0f3cff11f --- /dev/null +++ b/crates/page_box/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "page_box" +version = "0.1.0" +authors = ["dbydd "] +edition = "2021" +license = "GPL-3.0-or-later" +description = "modified from toku-sa-n's pagebox crate, try to make it into multi platform, adapt for arceos" + +[dependencies] + +axhal = {path = "../../modules/axhal"} +axalloc = {path = "../../modules/axalloc"} +page_table = {path = "../page_table"} +page_table_entry = {path = "../page_table_entry"} \ No newline at end of file diff --git a/crates/page_box/src/lib.rs b/crates/page_box/src/lib.rs new file mode 100644 index 0000000000..7863a0e1ab --- /dev/null +++ b/crates/page_box/src/lib.rs @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#![cfg_attr(not(test), no_std)] +#![allow(clippy::type_repetition_in_bounds)] +#![feature(strict_provenance)] +#![feature(allocator_api)] +use core::{ + alloc::{Allocator, Layout}, + convert::{TryFrom, TryInto}, + fmt, + marker::PhantomData, + mem, + ops::{Deref, DerefMut}, + ptr::{self, NonNull}, + slice, +}; + +use axhal::mem::{virt_to_phys, PhysAddr, VirtAddr}; +use page_table::PageSize; + +pub struct PageBox { + virt: VirtAddr, + bytes: usize, + _marker: PhantomData, +} +impl PageBox { + fn write_initial_value(&mut self, x: T) { + // SAFETY: This operation is safe because the memory `self.virt.as_mut_ptr` points is + // allocated, and is page-aligned. + unsafe { + ptr::write(self.virt.as_mut_ptr() as *mut T, x); + } + } +} +impl Deref for PageBox { + type Target = T; + fn deref(&self) -> &Self::Target { + // SAFETY: This operation is safe because the memory region `virt` points is allocated and + // is not used by the others. + unsafe { &*(self.virt.as_ptr() as *mut T) } + } +} +impl DerefMut for PageBox { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: This operation is safe because the memory region `virt` points is allocated and + // is not used by the others. + unsafe { &mut *(self.virt.as_mut_ptr() as *mut T) } + } +} +impl fmt::Display for PageBox { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} +impl fmt::Debug for PageBox +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} +impl Default for PageBox +where + T: Default, +{ + fn default() -> Self { + Self::from(T::default()) + } +} +impl Clone for PageBox +where + T: Clone, +{ + fn clone(&self) -> Self { + Self::from((**self).clone()) + } +} +impl From for PageBox { + fn from(x: T) -> Self { + assert_alignment(&x); + let bytes = mem::size_of::(); + let mut page_box = Self::from_bytes(bytes); + page_box.write_initial_value(x); + page_box + } +} + +impl PageBox<[T]> +where + T: Clone, +{ + pub fn new_slice(x: T, num_of_elements: usize) -> Self { + assert_alignment(&x); + let bytes = mem::size_of::() * num_of_elements; + let mut page_box = Self::from_bytes(bytes); + page_box.write_all_elements_with_same_value(x); + page_box + } + + pub fn alloc_pages(pages: usize, zero: T) -> Self { + let bytes = PageSize::Size4K as usize * pages; + let mut page_box = Self::from_bytes(bytes); + page_box.write_all_elements_with_same_value(zero); + page_box + } + + fn write_all_elements_with_same_value(&mut self, x: T) { + for i in 0..self.len() { + let ptr: usize = + usize::try_from(self.virt.as_usize()).unwrap() + mem::size_of::() * i; + + // SAFETY: This operation is safe. The memory ptr points is allocated and is aligned + // because the first elements is page-aligned. + unsafe { ptr::write(ptr as *mut T, x.clone()) } + } + } + + fn num_of_elements(&self) -> usize { + self.bytes / mem::size_of::() + } +} + +impl Deref for PageBox<[T]> +where + T: Clone, +{ + type Target = [T]; + fn deref(&self) -> &Self::Target { + unsafe { slice::from_raw_parts(self.virt.as_ptr() as *mut T, self.num_of_elements()) } + } +} +impl DerefMut for PageBox<[T]> +where + T: Clone, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + slice::from_raw_parts_mut(self.virt.as_mut_ptr() as *mut T, self.num_of_elements()) + } + } +} +impl fmt::Display for PageBox<[T]> +where + T: Clone, + [T]: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} +impl fmt::Debug for PageBox<[T]> +where + T: Clone, + [T]: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} +impl Clone for PageBox<[T]> +where + T: Clone, +{ + fn clone(&self) -> Self { + let mut b = Self::new_slice(self[0].clone(), self.len()); + + for (dst, src) in b.iter_mut().zip(self.iter()) { + *dst = src.clone(); + } + + b + } +} +impl From<&[T]> for PageBox<[T]> { + fn from(s: &[T]) -> Self { + let b = Self::new_slice(s[0], s.len()); + + unsafe { + ptr::copy_nonoverlapping(s.as_ptr(), b.virt_addr().as_mut_ptr() as *mut T, s.len()); + } + + b + } +} + +impl PageBox { + #[must_use] + pub fn virt_addr(&self) -> VirtAddr { + self.virt + } + + /// # Panics + /// + /// This method panics if the `PageBox` is not mapped. + #[must_use] + pub fn phys_addr(&self) -> PhysAddr { + // let a = virt_to_phys(self.virt); + + // if a.is_null() { + // unreachable!("Address: {:?} is not mapped.", self.virt); + // } + + // a + PhysAddr::from(self.virt.as_usize()) + } + + #[must_use] + pub fn bytes(&self) -> usize { + self.bytes + } + + fn from_bytes(bytes: usize) -> Self { + let alloc_pages = VirtAddr::from( + axalloc::global_no_cache_allocator() + .allocate(Layout::from_size_align(bytes, PageSize::Size4K as usize).unwrap()) + .expect("error on alloc page") + .addr() + .get(), + ); + //TODO + + // assert!(!virt.is_null(), "Failed to allocate pages."); + + Self { + virt: alloc_pages, + bytes, + _marker: PhantomData, + } + } +} +impl Drop for PageBox { + fn drop(&mut self) { + let num_of_pages = as_num_of_pages(self.bytes); + + axalloc::global_allocator().dealloc_pages(self.virt.as_usize(), num_of_pages); + } +} + +#[cfg(test)] +mod tests { + use super::PageBox; + + #[test] + fn clone_single_element() { + let b = PageBox::from(3); + let b2 = b.clone(); + + assert_eq!(*b, *b2); + } + + #[test] + fn clone_slice() { + let b = PageBox::new_slice(334, 5); + let b2 = b.clone(); + + assert_eq!(*b, *b2); + } + + #[test] + fn from_slice() { + let s: &[i32] = &[3, 3, 4]; + let b = PageBox::<[i32]>::from(s); + + assert_eq!(*b, *s); + } +} + +fn assert_alignment(x: &T) { + assert!( + mem::align_of_val(x) <= PageSize::Size4K as usize, + "The minimum alignment must be less than or equal to 4096." + ); +} + +fn as_num_of_pages(usize: usize) -> usize { + (usize + PageSize::Size4K as usize - 1) / PageSize::Size4K as usize +} diff --git a/crates/page_table/src/arch/aarch64.rs b/crates/page_table/src/arch/aarch64.rs index e652544ba2..5b10474fc7 100644 --- a/crates/page_table/src/arch/aarch64.rs +++ b/crates/page_table/src/arch/aarch64.rs @@ -7,7 +7,7 @@ use page_table_entry::aarch64::A64PTE; #[derive(Copy, Clone)] pub struct A64PagingMetaData; -impl const PagingMetaData for A64PagingMetaData { +impl PagingMetaData for A64PagingMetaData { const LEVELS: usize = 4; const PA_MAX_BITS: usize = 48; const VA_MAX_BITS: usize = 48; diff --git a/crates/page_table/src/lib.rs b/crates/page_table/src/lib.rs index 0af6649941..5f81da8db3 100644 --- a/crates/page_table/src/lib.rs +++ b/crates/page_table/src/lib.rs @@ -19,7 +19,6 @@ #![no_std] #![feature(const_trait_impl)] -#![feature(result_option_inspect)] #![feature(doc_auto_cfg)] #[macro_use] @@ -57,7 +56,6 @@ pub type PagingResult = Result; /// The **architecture-dependent** metadata that must be provided for /// [`PageTable64`]. -#[const_trait] pub trait PagingMetaData: Sync + Send + Sized { /// The number of levels of the hardware page table. const LEVELS: usize; diff --git a/crates/page_table_entry/src/arch/aarch64.rs b/crates/page_table_entry/src/arch/aarch64.rs index 5b88b97ec0..faf5f83bb7 100644 --- a/crates/page_table_entry/src/arch/aarch64.rs +++ b/crates/page_table_entry/src/arch/aarch64.rs @@ -81,6 +81,9 @@ impl DescriptorAttr { if matches!(idx, MemAttr::Normal | MemAttr::NormalNonCacheable) { bits |= Self::INNER.bits() | Self::SHAREABLE.bits(); } + if matches!(idx, MemAttr::Device) { + bits |= Self::SHAREABLE.bits(); + } Self::from_bits_retain(bits) } @@ -101,7 +104,7 @@ impl MemAttr { /// attributes in the descriptors. pub const MAIR_VALUE: u64 = { // Device-nGnRE memory - let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value; + let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_noEarlyWriteAck.value; // Normal memory let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; diff --git a/doc/XMODEM.TXT b/doc/XMODEM.TXT new file mode 100644 index 0000000000..a95592966f --- /dev/null +++ b/doc/XMODEM.TXT @@ -0,0 +1,102 @@ +Perception presents: +------------ Understanding The X-Modem File Transfer Protocol --------------- + + by Em Decay + +This has to be one of the most internationally accepted protocols for upload- + ing and downloading binary and text files. It is fairly straight-forward as + to how it is set up and there are some error checking capabilities. + + +--- Before you begin --- + +Things you need to know beforehand... + +The following terms are simply ascii codes: + SOH = chr(1) = CTRL-A = + EOT = chr(4) = CTRL-D = End of Transmission + ACK = chr(6) = CTRL-F = Positive Acknowledgement + NAK = chr(21) = CTRL-U = Negative Acknowledgement + CAN = chr(24) = CTRL-X = Cancel + +In order to send the file, you must first divide it into 128 byte sections + (packets). Bytes 0-127 of the file make up the first packet, bytes 128-255 + make up the second packet, etc. + +The packet number sent is simply the number of the packet. If the packet + number is greater than 255, then subtract 256 repeatedly until the number is + between 0 and 255. For example, if you were sending packet 731, then you + would send 731 - 256 - 256 = 219. + +The 1's complement of a byte (to make life easy) is simply 255 minus the + byte. For example, if you had to take the 1's complement of 142, the answer + would be 255 - 142 = 113. + +The checksum is the value of all the bytes in the packet added together. For + example, if the first five bytes were 45, 12, 64, 236, 173 and the other 123 + bytes were zeroes, the checksum would be 45+12+64+236+173+0+0+...+0 = 530. + However, to make each block one byte smaller, they repeatedly subtract 256 + from the checksum until it is between 0 and 255. In this case, the checksum + would be 530 - 256 - 256 = 18. + +The first byte the downloader sends is referred to as the NCGbyte. + +Provided that you aren't lost already, here is what happens next. The steps + below describe who sends what when :) + + +--- The Actual Transfer --- + +The uploader waits until the downloader sends a NAK byte. The NAK byte + is the signal that the downloader is ready to start. This byte is referred + to as the NCGbyte. If the downloader takes too long or an error occurs then + the uploader will stop waiting or "Time Out". If this happens, then the + file transfer must restart. + +With each packet sent... + + The uploader sends: + + 1. an SOH byte {1 byte} + 2. the packet number {1 byte} + 3. the 1's complement of the packet number {1 byte} + 4. the packet {128 bytes} + 5. the checksum {1 byte} + The above five things are called the block. + + The downloader: + + 1. ensures that the packet number sent matches the actual packet number + that it is (If the third block send has a '4' as the second byte, + something is wrong --> CANCEL TRANSFER (send CAN byte)) + 2. adds the packet number and the 1's complement of it together to make + sure that they add up to 255. if they don't --> CANCEL TRANSFER + 3. adds up all the bytes in the packet together --> THE SUM + 4. compares the last two significant digits of THE SUM with the checksum + 5. if everything looks ok (sum=checksum), then the downloader appends the + bytes in the packet to the file being created (sent). The down- + loader then sends an ACK byte which tells the uploader to send the + next block. + if the sums do not match then the downloader sends an NAK byte which + tells the uploader to send the same block it just sent over again. + +When the uploader sends an EOT byte instead of an SOH byte, the downloader + sends a NAK byte. If the uploader sends another EOT immediately after that, + the downloader sends an ACK byte and the transfer is complete. + +Another thing, the downloader can cancel the transfer at any time by sending + a CAN byte. The uploader can only cancel between blocks by sending a CAN + byte. It is recommended that you send anywhere between 2 and 8 consecutive + CAN bytes when you wish to cancel as some programs will not let you abort if + only 1 CAN byte is sent. + + +--- Wrap Up --- + +Hopefully, you were able to follow along. :) If not, you can e-mail me at + em_decay@norlink.net and I will try to clarify it for you. Have fun :) + +Perception: Em Decay -- Mark Korhonen + Cmf ------- Chris Fillion + +Written on Dec.28/95 diff --git a/doc/XMODEM1K.TXT b/doc/XMODEM1K.TXT new file mode 100644 index 0000000000..f3f2134b46 --- /dev/null +++ b/doc/XMODEM1K.TXT @@ -0,0 +1,109 @@ +Perception presents: +---------- Understanding The X-Modem 1K File Transfer Protocol -------------- + + by Em Decay + +This has to be one of the most internationally accepted protocols for upload- + ing and downloading binary and text files. It is fairly straight-forward as + to how it is set up and there are fairly good error checking capabilities. + + +--- Before you begin --- + +Look at my XMODEM.TXT and XMODEMCRC.TXT text file for a general understanding + of the X-Modem file transfer protocol and the terms used in it. + +New things you need to know beforehand... + +The following term is just an ASCII code: + STX = chr(2) = CTRL-B + +The CRC starts with a value of zero at the beginning of each block. Now to + update the CRC, with each byte in the 1024 byte packet simply do this (the + oldcrc is the crc value to be updated, data is the current byte): + CRC:=(oldcrc shl 8) xor (crctable[(oldcrc shr 8) xor data]); +The final value of the CRC (after all 1024 bytes) is what is being sent in + the X-Modem CRC protocol. + +If a 128 byte packet is sent, the CRC is calculated in the same manner as in + X-Modem CRC. + +These are the only new things that are needed in X-Modem 1K. :) + + +--- The Actual Transfer --- + +As in X-Modem, the uploader waits for the downloader to send the NCGbyte. + The NCGbyte for X-Modem 1K is identical to the NCGbyte for X-Modem CRC and + it is chr(67) or the capital letter C (unlike X-Modem where the NCGbyte is + chr(21), the NAK). If the downloader takes too long or an error occurs then + the uploader will stop waiting or "Time Out". If this happens, then the + file transfer must restart. + +The uploader can send either 1024 byte or 128 byte packets. 1024 byte + packets are faster but 128 bytes at the end of the transfer can save some + time at the end. This is because if there are only 125 bytes left to send, + only one 128 byte packet would be necessary (in which case you would send + 3 null (chr(0)) bytes) whereas sending a 1024 byte packet would send 999 + nulls. + +With each packet sent... + + In each 1024 byte (1k) packet, the uploader sends: + + 1. an STX byte {1 byte} + 2. the packet number {1 byte} + 3. the 1's complement of the packet number {1 byte} + 4. the packet {1024 bytes} + 5. the high byte of the CRC-16 {1 byte} + 6. the low byte of the CRC-16 {1 byte} + + In each 128 byte packet, the uploader sends: + + 1. an STX byte {1 byte} + 2. the packet number {1 byte} + 3. the 1's complement of the packet number {1 byte} + 4. the packet {128 bytes} + 5. the high byte of the CRC-16 {1 byte} + 6. the low byte of the CRC-16 {1 byte} + + These six things make up the block. + + The downloader: + + 1. ensures that the packet number sent matches the actual packet number + that it is (If the third block sent has a '4' as the second byte, + something is wrong --> CANCEL TRANSFER (send CAN byte)) + 2. adds the packet number and the 1's complement of the packet number + together to make sure that they add up to 255. if they don't --> + CANCEL TRANSFER + 3. sets the CRC to zero + 4. updates the CRC as each byte in the packet is sent + 5. compares the calculated CRC to the CRC that is sent + 6. if everything looks ok (calculated CRC=sent CRC), then the downloader + appends the bytes in the packet to the file being created (sent). + The downloader then sends an ACK byte which tells the uploader to + send the next block. + if the CRCs do not match, then the downloader sends a NAK byte which + tells the uploader to send the same block it just sent over again. + +When the uploader sends an EOT byte instead of an SOH or STX byte, the down- + loader sends a NAK byte. If the uploader sends another EOT immediately + after that, the downloader sends an ACK byte and the transfer is complete. + +Another thing, the downloader can cancel the transfer at any time by sending + a CAN byte. The uploadered can cancel only between blocks by sending a CAN + byte. It is recommended that you send between 2 and 8 consecutive CAN bytes + as some communication programs will not allow you to cancel with only 1 CAN + byte. + + +--- Wrap Up --- + +Hopefully, you were able to follow along. :) If not, you can e-mail me at + em_decay@norlink.net and I will try to clarify it for you. Have fun :) + +Perception: Em Decay -- Mark Korhonen + Cmf ------- Chris Fillion + +Written on Jan.19/95 diff --git a/doc/XMODMCRC.TXT b/doc/XMODMCRC.TXT new file mode 100644 index 0000000000..08de36cb54 --- /dev/null +++ b/doc/XMODMCRC.TXT @@ -0,0 +1,139 @@ +Perception presents: +---------- Understanding The X-Modem CRC File Transfer Protocol -------------- + + by Em Decay + +This has to be one of the most internationally accepted protocols for upload- + ing and downloading binary and text files. It is fairly straight-forward as + to how it is set up and there are some error checking capabilities. + + +--- Before you begin --- + +Look at my XMODEM.TXT text file for a general understanding of the X-Modem + file transfer protocol and the terms used in it. + +New things you need to know beforehand... + +One word is the same as two bytes. If you want the high byte and the low + byte of a word, simply do the following. + High byte = word DIV 256 (DIV is the same as divide except the answer is + truncated) + Low byte = $00ff AND word (AND refers to AND logic) + +To get a word from a high byte and a low byte, simply multiply the high byte + by 256 (or shift it left 8 bits, if you know assembly) and add the low byte + to it. + +CRC stands for Cyclical Redundancy Check. In X-Modem CRC, it is also refer- + red to as CRC-16 since there are 16 bits (1 word) at the end of the block + that contain the CRC. This 1 word CRC replaces the 1 byte checksum in + X-Modem. +CRC-16 guarantees detection of all single and double bit errors, all errors + with an odd number of bits and over 99.9969% of all burst errors (you don't + have to know what all these things are :). +The easiest and fastest way to calculate the CRC is to use a lookup table. + +Here is some source code about making a lookup table. Call this procedure + at the very beginning of the program. Make crctable an global variable. + It is an array [0..255] of word. + + procedure initcrc; + + var + i:integer; + + function calctable(data,genpoly,accum:word):word; + + var + j:word; + + begin + data:=data shl 8; + for j:=8 downto 1 do + begin + if ((data xor accum) and $8000)<>0 then + accum:=(accum shl 1) xor genpoly + else + accum:=accum shl 1; + data:=data shl1; + end; + calctable:=accum; + end; + + begin + for i:=0 to 255 do + crctable[i]:=calctable(i,4129,0); + end; + +The CRC starts with a value of zero at the beginning of each block. Now to + update the CRC, with each byte in the 128 byte packet simply do this (the + oldcrc is the crc value to be updated, data is the current byte): + CRC:=(oldcrc shl 8) xor (crctable[(oldcrc shr 8) xor data]); +The final value of the CRC (after all 128 bytes) is what is being sent in the + X-Modem CRC protocol. + +If you have somewhat understood what has just been described then you catch + on a lot faster than I did :) If you just use + + +--- The Actual Transfer --- + +As in X-Modem, the uploader waits for the downloader to send the NCGbyte. + The NCGbyte for X-Modem CRC is chr(67) or the capital letter C (unlike + X-Modem where the NCGbyte is chr(21), the NAK). If the downloader takes too + long or an error occurs then the uploader will stop waiting or "Time Out". + If this happens, then the file transfer must restart. + +With each packet sent... + + The uploader sends: + + 1. an SOH byte {1 byte} + 2. the packet number {1 byte} + 3. the 1's complement of the packet number {1 byte} + 4. the packet {128 bytes} + 5. the high byte of the CRC-16 {1 byte} + 6. the low byte of the CRC-16 {1 byte} + + These six things make up the block. + + The downloader: + + 1. ensures that the packet number sent matches the actual packet number + that it is (If the third block sent has a '4' as the second byte, + something is wrong --> CANCEL TRANSFER (send CAN byte)) + 2. adds the packet number and the 1's complement of the packet number + together to make sure that they add up to 255. if they don't --> + CANCEL TRANSFER + 3. sets the CRC to zero + 4. updates the CRC as each byte in the packet is sent + 5. compares the calculated CRC to the CRC that is sent + 6. if everything looks ok (calculated CRC=sent CRC), then the downloader + appends the bytes in the packet to the file being created (sent). + The downloader then sends an ACK byte which tells the uploader to + send the next block. + if the CRCs do not match, then the downloader sends a NAK byte which + tells the uploader to send the same block it just sent over again. + +When the uploader sends an EOT byte instead of an SOH byte, the downloader + sends a NAK byte. If the uploader sends another EOT immediately after that, + the downloader sends an ACK byte and the transfer is complete. + +Another thing, the downloader can cancel the transfer at any time by sending + a CAN byte. The uploadered can cancel only between blocks by sending a CAN + byte. It is recommended that you send between 2 and 8 consecutive CAN bytes + as some communication programs will not allow you to cancel with only 1 CAN + byte. + + +--- Wrap Up --- + +Hopefully, you were able to follow along. :) If not, you can e-mail me at + em_decay@norlink.net and I will try to clarify it for you. Have fun :) + +Perception: Em Decay -- Mark Korhonen + Cmf ------- Chris Fillion + +Written on Jan.3/95 + diff --git a/doc/apps_usb-hid.md b/doc/apps_usb-hid.md new file mode 100644 index 0000000000..84d0d71cfd --- /dev/null +++ b/doc/apps_usb-hid.md @@ -0,0 +1,105 @@ +[TOC] + +| App | Extra modules | Enabled features | Description | +| --------------------------- | ------------- | ---------------- | ----------------------- | +| [usb-hid](../apps/usb-hid/) | | | A usb-hid mouse example | + +# 介绍-中文 + +## 运行方法 + +### 环境需求 + +* 一张飞腾派开发板 + +* 一张sd卡,上面应当刷好了飞腾官方所提供的[uboot镜像/系统镜像](https://gitee.com/phytium_embedded/phytium-pi-os) + +* linux环境 + +* python,需要安装pyserial,xmodem,serial模块 + + * pip install pyserial serial xmodem + +* minicom + + * sudo apt install minicom #如果你用的是ubuntu + +### 运行步骤 + +1. 确认你的USB串口线正确的连接到了飞腾派的UART1 DEBUG输出 + +2. 确保串口被正确识别为/dev/ttyUSB0 + +3. 清除uboot上的启动环境变量(bootenv),方法为在uboot终端内输入 + + ```shell + setenv bootcmd '';saveenv; + ``` + +4. 确保鼠标已经插在板子上了(位置为靠近正面风扇的第一个usb3.0口(蓝色口)) + +5. 编译并运行,命令如下 + + ```shell + make A=apps/usb-hid PLATFORM=aarch64-phytium-pi LOG=trace chainboot + ``` + +6. 给板子上电开机,等待编译结果传输完成(脚本会自动将编译结果加载到0x90100000) + +7. 此时会自动进入minicom界面,输入go 0x90100000 + +8. 试试移动/点击鼠标,看看终端上的响应输出 + +## usb 系统架构: + +![usb system](figures/usb_main_architecture.png) + +# INTRODUCTION-English + +## RUN + +### Prequireties + +* Phytium Pi board + +* a sd card with Uboot from [Phytium's Fork](https://gitee.com/phytium_embedded/phytium-pi-os) + +* linux + +* python with pyserial, xmodem,serial package + + * pip install pyserial serial xmodem + +* minicom + + * sudo apt install minicom # if use ubuntu + +### Build&Run step + +1. ensure UsbSerial wire connect to Phytium Pi board with Uart 1 Debug port + +2. ensure yor usb-serial was recognized so that you had /dev/ttyUSB0 + +3. clear uboot's bootenv with + + ```shell + setenv bootcmd '';saveenv; + ``` + +4. ensure usb mouse has plugged in to proper position(first usb 3.0 port, close to front side of board) + +5. run command at project root: + + ```shell + make A=apps/usb-hid PLATFORM=aarch64-phytium-pi LOG=trace chainboot + ``` + +6. poweron board, waiting for [compile result](../apps/usb-hid/usb-hid_aarch64-phytium-pi.bin) load into address 0x90100000 by our [script](../tools/phytium-pi/yet_another_uboot_transfer.py) via uboot xmodem file transfer + +7. type "go 0x90100000" + +8. then the application was started automaticlly, try to move your mouse,or click some button! and see signal comes out in terminal + +## usb system structure: + +![usb system](figures/usb_main_architecture.png) diff --git a/doc/figures/arceos_cli.png b/doc/figures/arceos_cli.png new file mode 100644 index 0000000000..4ea1f0b716 Binary files /dev/null and b/doc/figures/arceos_cli.png differ diff --git a/doc/figures/draw_jtag_connected.jpg b/doc/figures/draw_jtag_connected.jpg new file mode 100644 index 0000000000..0a3e0db2f5 Binary files /dev/null and b/doc/figures/draw_jtag_connected.jpg differ diff --git a/doc/figures/endpoint-state-machine.png b/doc/figures/endpoint-state-machine.png new file mode 100644 index 0000000000..514b311d40 Binary files /dev/null and b/doc/figures/endpoint-state-machine.png differ diff --git a/doc/figures/image_jtag_connected.jpg b/doc/figures/image_jtag_connected.jpg new file mode 100644 index 0000000000..43075cee85 Binary files /dev/null and b/doc/figures/image_jtag_connected.jpg differ diff --git a/doc/figures/main_architecture.png b/doc/figures/main_architecture.png new file mode 100644 index 0000000000..0329667ac1 Binary files /dev/null and b/doc/figures/main_architecture.png differ diff --git a/doc/figures/main_architecture.svg b/doc/figures/main_architecture.svg new file mode 100644 index 0000000000..2e524aed46 --- /dev/null +++ b/doc/figures/main_architecture.svg @@ -0,0 +1,4 @@ + + + +
操作系统
操作系统
硬件ISA
硬件ISA
对系统暴露的API
对系统暴露的API
USB驱动层
USB驱动层
USB控制逻辑/XHCI控制逻辑转换
USB控制逻辑/XHCI控制逻辑转换
主机(XHCI控制器)驱动层
主机(XHCI控制器)驱动层
硬件操作抽象
硬件操作抽象
硬件抽象层
硬件抽象层
系统调用抽象
系统调用抽象
系统抽象层
系统抽象层
驱动无关的设备抽象
驱动无关的设备抽象
设备1
设备1
设备2
设备2
设备3
设备3
USB设备1
USB设备1
USB设备2
USB设备2
...
...
USB设备
USB设备
物理上的设备
物理上的设备
控制器主机
控制器主机
api
对外暴露的api...
鼠标驱动
鼠标驱动
U盘驱动
U盘驱动
摄像头驱动
摄像头驱动
...
...
动态加载
动态加载
驱动实例集合
驱动实例集合
驱动1
驱动1
驱动2
驱动2
...
...
获得驱动的设备实例
获得驱动的设备实例
Hid设备
Hid设备
鼠标
鼠标
手柄
手柄
键盘
键盘
...
...
存储设备
存储设备
U盘
U盘
移动硬盘
移动硬盘
其他设备
其他设备
...
...
摄像头
摄像头
设备a
设备a
设备b
设备b
设备c
设备c
...
...
其他类型设备
...
其他类型设备 ...
\ No newline at end of file diff --git a/doc/figures/phytium_pi_gpio.png b/doc/figures/phytium_pi_gpio.png new file mode 100644 index 0000000000..619b8a20f1 Binary files /dev/null and b/doc/figures/phytium_pi_gpio.png differ diff --git a/doc/figures/tick-tock-machine.png b/doc/figures/tick-tock-machine.png new file mode 100644 index 0000000000..65d9f6b415 Binary files /dev/null and b/doc/figures/tick-tock-machine.png differ diff --git a/doc/figures/usb_main_architecture.png b/doc/figures/usb_main_architecture.png new file mode 100644 index 0000000000..0329667ac1 Binary files /dev/null and b/doc/figures/usb_main_architecture.png differ diff --git a/doc/figures/usb_main_architecture.svg b/doc/figures/usb_main_architecture.svg new file mode 100644 index 0000000000..2e524aed46 --- /dev/null +++ b/doc/figures/usb_main_architecture.svg @@ -0,0 +1,4 @@ + + + +
操作系统
操作系统
硬件ISA
硬件ISA
对系统暴露的API
对系统暴露的API
USB驱动层
USB驱动层
USB控制逻辑/XHCI控制逻辑转换
USB控制逻辑/XHCI控制逻辑转换
主机(XHCI控制器)驱动层
主机(XHCI控制器)驱动层
硬件操作抽象
硬件操作抽象
硬件抽象层
硬件抽象层
系统调用抽象
系统调用抽象
系统抽象层
系统抽象层
驱动无关的设备抽象
驱动无关的设备抽象
设备1
设备1
设备2
设备2
设备3
设备3
USB设备1
USB设备1
USB设备2
USB设备2
...
...
USB设备
USB设备
物理上的设备
物理上的设备
控制器主机
控制器主机
api
对外暴露的api...
鼠标驱动
鼠标驱动
U盘驱动
U盘驱动
摄像头驱动
摄像头驱动
...
...
动态加载
动态加载
驱动实例集合
驱动实例集合
驱动1
驱动1
驱动2
驱动2
...
...
获得驱动的设备实例
获得驱动的设备实例
Hid设备
Hid设备
鼠标
鼠标
手柄
手柄
键盘
键盘
...
...
存储设备
存储设备
U盘
U盘
移动硬盘
移动硬盘
其他设备
其他设备
...
...
摄像头
摄像头
设备a
设备a
设备b
设备b
设备c
设备c
...
...
其他类型设备
...
其他类型设备 ...
\ No newline at end of file diff --git a/doc/ixgbe.md b/doc/ixgbe.md index cba58e3b6a..ac93e3e9a3 100644 --- a/doc/ixgbe.md +++ b/doc/ixgbe.md @@ -13,3 +13,37 @@ You can also use the following command to start the iperf application: ```shell make A=apps/c/iperf PLATFORM=x86_64-pc-oslab FEATURES=driver-ixgbe,driver-ramdisk ``` + +## Use ixgbe NIC in QEMU with PCI passthrough + +1. Install the `vfio-pci` driver in the host: + + ```shell + sudo modprobe vfio-pci + ``` + +2. Bind the NIC to the `vfio-pci` driver (assume the PCI address is `02:00.0`): + + ```shell + sudo ./scripts/net/pci-bind.sh vfio-pci 02:00.0 + # Equivalent to: + # echo 0000:02:00.0 > /sys/bus/pci/drivers/ixgbe/unbind + # echo vfio-pci > /sys/bus/pci/devices/0000:02:00.0/driver_override + # echo 0000:02:00.0 > /sys/bus/pci/drivers/vfio-pci/bind + ``` + +3. Build and run ArceOS: + + ```shell + make A=apps/net/httpserver FEATURES=driver-ixgbe VFIO_PCI=02:00.0 IP=x.x.x.x GW=x.x.x.x run + ``` + +4. If no longer in use, bind the NIC back to the `ixgbe` driver: + + ```shell + sudo ./scripts/net/pci-bind.sh ixgbe 02:00.0 + # Equivalent to: + # echo 0000:02:00.0 > /sys/bus/pci/drivers/vfio-pci/unbind + # echo ixgbe > /sys/bus/pci/devices/0000:02:00.0/driver_override + # echo 0000:02:00.0 > /sys/bus/pci/drivers/ixgbe/bind + ``` diff --git a/doc/jtag_debug_in_raspi4.md b/doc/jtag_debug_in_raspi4.md new file mode 100644 index 0000000000..f732a59b15 --- /dev/null +++ b/doc/jtag_debug_in_raspi4.md @@ -0,0 +1,276 @@ +# Introduction + +This article describes a way to debug jtags via openocd, gdb, jlink debugger. + +## Requirement + +### Resources + +1. Authors using [H-JLINK v9 type c Universal ARM Downloader](https://m.tb.cn/h.5FpduM7jUbbFlzo?tk=Z6t5WlsfPtl), +but theoretically, you can use whatever you want. + +2. [Serial USB to TTL CH340 Module](https://www.amazon.com/HiLetgo-Module-Microcontroller-Download-Serial/dp/B00LZV1G6K/ref=sr_1_3?dib=eyJ2IjoiMSJ9.EVDg6VSjpenXHkAOIddkejC8NrNLBaiI9YKosxxcvxsvWHCkJuYWT97oslmx7iE-il7I7ilkI07pfXYrJnjb0-gM8hu4y8_hMEVA7hiUtPZtjhovoAeF0-L7rM0xTe-hdNscYjbIspct3yjOtYSF9QPNFmr9XmeC5Os2gCQxZihglIJJDxUWWAhJL_MNl06dDKZnk82pkR_p09laqdfg0nFMwJwdxLDObHv3gzDHWNk.pvOBDJ9aVLFwecXlCYuMONK54Z_7sxnzAvdO71qkHWI&dib_tag=se&keywords=CH340&qid=1709218438&sr=8-3) + +3. Some Female to Female [Dupont Wire](https://www.amazon.com/Elegoo-EL-CP-004-Multicolored-Breadboard-arduino/dp/B01EV70C78/ref=sr_1_3?dib=eyJ2IjoiMSJ9.OCLDs3D5By4QvSSJfVxcRa7LFdoHpv56YLqS9wbJRIGaY_r5UKFkopHdBRu0aVmyYfSaH77oX0ure59RTu2R0GWeOUm8DEzRUHiLTYnKqPa02peSrC0JWZMUQPaErE40BeYQpDl0ywu9vg7zI1gHJWxdYtOgrehyUhiT9G9657pN73jvrY3Vd5RrBH9-5aAYEDKpN_P1gS48Yqv9n7S3efD7AKdAsgYsLsN1QLBFeyI.VxVp4ZfND0S73SSXYiJlh6KJD8GRdD2Pn2LHUrCHSj4&dib_tag=se&keywords=DuPont+line&qid=1709218493&sr=8-3) + +4. A laptop + +### Preliminary preparation + +1. Connect CH304 from [bcm2711 pin 8,10,12](https://datasheets.raspberrypi.com/rpi4/raspberry-pi-4-reduced-schematics.pdf) (Rx to Tx, Tx to Rx, GND to GND). + By the ways, power indicator closest to 1. + +2. Connect H-JLINK based on the picture below: + +![connect_jtag_debugger](./figures/image_jtag_connected.jpg) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GPIO # Name JTAG # Note Diagram
VTREF1to 3.3V
GND4to GND
22TRST3
26TDI5
27TMS7
25TCK9
23RTCK11
24TDO13
+

+*thanks for andre-richter provide this sections.* + +3. Try to test whether chainboot works properly + 1. go to tools/raspi4/chainloader + 2. run `make clean && make`, it should generate a kernel8.img under this directory. + if everything right, the image file should be 8576 via `ls -al`. + 3. move this image into your sd card. + 4. check if your sd card has contians following file + [start4.elf](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/start4.elf), + [fixup4.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat), + [bcm2711-rpi-4-b.dtb](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bcm2711-rpi-4-b.dtb) + 5. just run `make A=apps/helloworld PLATFORM=aarch64-raspi4 chainboot`, then should display this image. + + + + + + + + + + + + + + + + + + +
Minipush 1.0





[MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected


[MP]  Please power the target now
This means that CH340 is not connected or connected in some other wayconnection is successful
maybe /dev/ttyUSB1 or something else
+ + After power up the board: + + ``` + + __ __ _ _ _ _ + | \/ (_)_ _ (_) | ___ __ _ __| | + | |\/| | | ' \| | |__/ _ \/ _` / _` | + |_| |_|_|_||_|_|____\___/\__,_\__,_| + + Raspberry Pi 4 + + [ML] Requesting binary + [MP] ⏩ Pushing 36 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 + [ML] Loaded! Executing the payload now + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ You're using chainboot image . @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + d8888 .d88888b. .d8888b. + d88888 d88P" "Y88b d88P Y88b + d88P888 888 888 Y88b. + d88P 888 888d888 .d8888b .d88b. 888 888 "Y888b. + d88P 888 888P" d88P" d8P Y8b 888 888 "Y88b. + d88P 888 888 888 88888888 888 888 "888 + d8888888888 888 Y88b. Y8b. Y88b. .d88P Y88b d88P + d88P 888 888 "Y8888P "Y8888 "Y88888P" "Y8888P" + + arch = aarch64 + platform = aarch64-raspi4 + target = aarch64-unknown-none-softfloat + smp = 1 + build_mode = release + log_level = warn + + Hello, world! + ``` + +## Run + +### Preliminary preparation + + 1. go to tools/raspi4/chainloader + 2. run `make clean && make JTAG=y`, it should generate a kernel8.img under this directory. + if everything right, the image file should be 8576 via `ls -al`. + 3. move this image into your sd card. + 4. check if your sd card has contians following file + [start4.elf](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/start4.elf), + [fixup4.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup4.dat), + [bcm2711-rpi-4-b.dtb](https://raw.githubusercontent.com/raspberrypi/firmware/master/boot/bcm2711-rpi-4-b.dtb) + +### Start Debugging + + 1. just run `make A=apps/helloworld PLATFORM=aarch64-raspi4 chainboot` and Power up the board., then should display this image. + + ``` + Minipush 1.0 + + [MP] ✅ Serial connected + [MP] 🔌 Please power the target now + + __ __ _ _ _ _ + | \/ (_)_ _ (_) | ___ __ _ __| | + | |\/| | | ' \| | |__/ _ \/ _` / _` | + |_| |_|_|_||_|_|____\___/\__,_\__,_| + + Raspberry Pi 4 + + [ML] Requesting binary + [MP] ⏩ Pushing 36 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 + [ML] Loaded! Executing the payload now + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ You're using a JTAG debug image. @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ 1. open openocd, gdb @ + @ 2. target extended-remote :3333; @ + @ 3. set $pc=0x80000 @ + @ 4. break rust_entry/others @ + @ 5. break $previous_addr @ + @ 6. delete 1 @ + @ 7. load @ + @ 8. continue @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + ``` + + *the following guidelines is basically like previous datasheets, In fact, if you're a senior developer, skip the following. XD* + 3. My personal suggestions is using zellij, but you could choice what ever you want. + 4. A: Keeping this miniload running (just don't terminate it) in terminal A. + 5. B: run `make A=apps/helloworld PLATFORM=aarch64-raspi4 openocd`, + the windows should display following, but it doesn't matter, we don't need to care about this. + + ``` + $ make A=apps/helloworld PLATFORM=aarch64-raspi4 openocd + + Launching OpenOCD + [sudo] password for jacky: + Open On-Chip Debugger 0.11.0+dev-g1ad6ed3 (2021-12-02-20:10) + Licensed under GNU GPL v2 + For bug reports, read + http://openocd.org/doc/doxygen/bugs.html + DEPRECATED! use 'adapter speed' not 'adapter_khz' + Warn : DEPRECATED! use '-baseaddr' not '-ctibase' + Warn : DEPRECATED! use '-baseaddr' not '-ctibase' + Warn : DEPRECATED! use '-baseaddr' not '-ctibase' + Warn : DEPRECATED! use '-baseaddr' not '-ctibase' + Info : Listening on port 6666 for tcl connections + Info : Listening on port 4444 for telnet connections + Info : J-Link V9 compiled May 7 2021 16:26:12 + Info : Hardware version: 9.60 + Info : VTarget = 3.311 V + Info : clock speed 1000 kHz + Info : JTAG tap: rpi4.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4) + Info : rpi4.core0: hardware has 6 breakpoints, 4 watchpoints + Info : rpi4.core1: hardware has 6 breakpoints, 4 watchpoints + Info : rpi4.core2: hardware has 6 breakpoints, 4 watchpoints + Info : rpi4.core3: hardware has 6 breakpoints, 4 watchpoints + Info : starting gdb server for rpi4.core0 on 3333 + Info : Listening on port 3333 for gdb connections + Info : starting gdb server for rpi4.core1 on 3334 + Info : Listening on port 3334 for gdb connections + Info : starting gdb server for rpi4.core2 on 3335 + Info : Listening on port 3335 for gdb connections + Info : starting gdb server for rpi4.core3 on 3336 + Info : Listening on port 3336 for gdb connections + + ``` + + 6. C: run `make A=apps/helloworld PLATFORM=aarch64-raspi4 gdb` in terminal C. + 7. You are now in GDB, but just don't start your debug immediately. + Because the use of minipush script, we could simple push our image to board before power up the board. + Like a double-edged sword. It also constrains our behavior, + which it's incapable for us to power up the board then use some kinds like halt command to halt the CPU. + (I think it can be done through script modification, but now there is no time to study and change ruby for a trivial upgrade.) + So we add a dead loop at the end of the image we generate lastest. + + ```gdb + (gdb) target extended-remote :3333 // connect to openocd gdb serve + // you should see $pc=0x2080db4 + (gdb) set $pc=0x80000 // The following behavior is unnecessary and can be debugged normally. + (gdb) monitor poll // MMU disable + (gdb) break rust_entry // Start debug module/axhal/ ... the location is VADDR will case error, + // you should use b *0x81a90 (manally remove 0xffff ... from output) + (gdb) b *0x81a90 + (gdb) break rust_main // as previous + (gdb) b *0x82888 + (gdb) delete 1 3 + (gdb) continue // first stop at rust_entry + (gdb) continue // second stop at rust_main + (gdb) monitor poll // MMU enable (in rust_entry) + ``` + +## Reference + +1. [rust-embedded/rust-raspberrypi-OS-tutorials](https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials) +2. [Raspberry Pi 4をJTAGデバッグしてみる(FTDI C232HM-DDHSL-0使用)](https://hikalium.hatenablog.jp/entry/2021/07/18/214013) +3. [Rust Raspberry Pi OS tutorials 08 HW debug JTAG by hikalium 2021-09-20](https://www.youtube.com/watch?v=6ULvzK1Drgo&t=21s) +4. [my record](https://bitbucket.org/jackyliu16/blog/src/master/content/jtag-load-failure-debug.cn.md) +4. openocd docs, bcm2711 docs, gdb docs ... etc. + + diff --git a/doc/platform_phytium_pi.md b/doc/platform_phytium_pi.md new file mode 100644 index 0000000000..2fb995b09c --- /dev/null +++ b/doc/platform_phytium_pi.md @@ -0,0 +1,34 @@ +# 飞腾派开发板帮助 + +## Host依赖 + +```shell +pip3 install pyserial +pip3 install xmodem +apt install minicom +``` + +## u-boot 配置 + +1.启动倒计时结束前按任意键进入命令行 + +2.执行 + +```shell +# 设置启动参数 +setenv bootcmd "" +# 保存 +saveenv +``` + +## 启动 + +host先插入串口转usb,然后执行 + +```shell +make A=apps/cli PLATFORM=aarch64-phytium-pi LOG=debug chainboot +``` + +开发板上电,并等待固件传输完成 + +输入 `go 0x90100000` 加载镜像,进入ArceOS diff --git a/doc/resources/HID/hid1_11.pdf b/doc/resources/HID/hid1_11.pdf new file mode 100644 index 0000000000..88c3edc60f Binary files /dev/null and b/doc/resources/HID/hid1_11.pdf differ diff --git "a/doc/resources/[PCIE\350\247\204\350\214\203]PCI Express Base Specification Revision 6.0.pdf" "b/doc/resources/[PCIE\350\247\204\350\214\203]PCI Express Base Specification Revision 6.0.pdf" new file mode 100644 index 0000000000..f6b3abbf1f Binary files /dev/null and "b/doc/resources/[PCIE\350\247\204\350\214\203]PCI Express Base Specification Revision 6.0.pdf" differ diff --git "a/doc/resources/[USB3.2\345\215\217\350\256\256\350\247\204\350\214\203]USB 3.2 Revision 1.1.pdf" "b/doc/resources/[USB3.2\345\215\217\350\256\256\350\247\204\350\214\203]USB 3.2 Revision 1.1.pdf" new file mode 100644 index 0000000000..f06b149b24 Binary files /dev/null and "b/doc/resources/[USB3.2\345\215\217\350\256\256\350\247\204\350\214\203]USB 3.2 Revision 1.1.pdf" differ diff --git a/doc/resources/[UVC]/USB_Video_Example 1.5.pdf b/doc/resources/[UVC]/USB_Video_Example 1.5.pdf new file mode 100644 index 0000000000..cb27cd4600 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Example 1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_FAQ_1.5.pdf b/doc/resources/[UVC]/USB_Video_FAQ_1.5.pdf new file mode 100644 index 0000000000..44f14c5b2f Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_FAQ_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_DV_15.pdf b/doc/resources/[UVC]/USB_Video_Payload_DV_15.pdf new file mode 100644 index 0000000000..330752f93b Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_DV_15.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_Frame_Based_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_Frame_Based_1.5.pdf new file mode 100644 index 0000000000..bfccbc759b Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_Frame_Based_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_H264_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_H264_1.5.pdf new file mode 100644 index 0000000000..e3995f9f21 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_H264_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_MJPEG_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_MJPEG_1.5.pdf new file mode 100644 index 0000000000..5138592dfc Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_MJPEG_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_MPEG-2_TS_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_MPEG-2_TS_1.5.pdf new file mode 100644 index 0000000000..46b6293b93 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_MPEG-2_TS_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_Stream_Based_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_Stream_Based_1.5.pdf new file mode 100644 index 0000000000..73783abb18 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_Stream_Based_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_Uncompressed_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_Uncompressed_1.5.pdf new file mode 100644 index 0000000000..4dfa5aa8f8 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_Uncompressed_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Payload_VP8_1.5.pdf b/doc/resources/[UVC]/USB_Video_Payload_VP8_1.5.pdf new file mode 100644 index 0000000000..f5e00d5308 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Payload_VP8_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Temporal_Encoder_Examples_1.5.pdf b/doc/resources/[UVC]/USB_Video_Temporal_Encoder_Examples_1.5.pdf new file mode 100644 index 0000000000..5ae92e555b Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Temporal_Encoder_Examples_1.5.pdf differ diff --git a/doc/resources/[UVC]/USB_Video_Transport_1.5.pdf b/doc/resources/[UVC]/USB_Video_Transport_1.5.pdf new file mode 100644 index 0000000000..a8ff14b4b3 Binary files /dev/null and b/doc/resources/[UVC]/USB_Video_Transport_1.5.pdf differ diff --git a/doc/resources/[UVC]/UVC 1.5 Class specification.pdf b/doc/resources/[UVC]/UVC 1.5 Class specification.pdf new file mode 100644 index 0000000000..b01578cb13 Binary files /dev/null and b/doc/resources/[UVC]/UVC 1.5 Class specification.pdf differ diff --git "a/doc/resources/[XHCI\346\216\247\345\210\266\345\231\250\350\247\204\350\214\203]extensible-host-controler-interface-usb-xhci.pdf" "b/doc/resources/[XHCI\346\216\247\345\210\266\345\231\250\350\247\204\350\214\203]extensible-host-controler-interface-usb-xhci.pdf" new file mode 100644 index 0000000000..5890cfe80c Binary files /dev/null and "b/doc/resources/[XHCI\346\216\247\345\210\266\345\231\250\350\247\204\350\214\203]extensible-host-controler-interface-usb-xhci.pdf" differ diff --git a/doc/resources/i2c/i2c_1.png b/doc/resources/i2c/i2c_1.png new file mode 100644 index 0000000000..ead6d11968 Binary files /dev/null and b/doc/resources/i2c/i2c_1.png differ diff --git a/doc/resources/i2c/i2c_2.png b/doc/resources/i2c/i2c_2.png new file mode 100644 index 0000000000..b8636886f0 Binary files /dev/null and b/doc/resources/i2c/i2c_2.png differ diff --git a/doc/resources/res/capture_result_wireless_receiver_mouse.ulz b/doc/resources/res/capture_result_wireless_receiver_mouse.ulz new file mode 100644 index 0000000000..bf7358db14 Binary files /dev/null and b/doc/resources/res/capture_result_wireless_receiver_mouse.ulz differ diff --git a/doc/resources/res/usb-hid.log b/doc/resources/res/usb-hid.log new file mode 100644 index 0000000000..0339044629 --- /dev/null +++ b/doc/resources/res/usb-hid.log @@ -0,0 +1,1291 @@ + +## Total Size = 0x00035040 = 217152 Bytes +## Start Addr = 0x90100000 +Phytium-Pi#o 0x90100000 +Unknown command 'o' - try 'help' +Phytium-Pi#go 0x90100000 +## Starting application at 0x90100000 ... +aaaaaaaaaaaaarch = aarch64 +platform = aarch64-phytium-pi +target = aarch64-unknown-none-softfloat +smp = 1 +build_mode = release +log_level = trace + +[ 38.933540 0 axruntime:143] Logging is enabled. +[ 38.939268 0 axruntime:144] Primary CPU 512 started, dtb = 0x1. +[ 38.946386 0 axruntime:146] Found physcial memory regions: +[ 38.953070 0 axruntime:149] [PA:0x90100000, PA:0x9012a000) .text (READ | EXECUTE | RESERVED) +[ 38.962878 0 axruntime:149] [PA:0x9012a000, PA:0x90132000) .rodata (READ | RESERVED) +[ 38.971992 0 axruntime:149] [PA:0x90132000, PA:0x90136000) .data .tdata .tbss .percpu (READ | WRITE | RESERVED) +[ 38.983449 0 axruntime:149] [PA:0x90136000, PA:0x90176000) boot stack (READ | WRITE | RESERVED) +[ 38.993518 0 axruntime:149] [PA:0x90176000, PA:0x9019c000) .bss (READ | WRITE | RESERVED) +[ 39.003066 0 axruntime:149] [PA:0x0, PA:0x1000) spintable (READ | WRITE | RESERVED) +[ 39.012093 0 axruntime:149] [PA:0x9019c000, PA:0x9089c000) nocache memory (READ | WRITE | DEVICE) +[ 39.022336 0 axruntime:149] [PA:0x9089c000, PA:0xff900000) free memory (READ | WRITE | FREE) +[ 39.032144 0 axruntime:149] [PA:0x2800c000, PA:0x2800d000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.042473 0 axruntime:149] [PA:0x2800d000, PA:0x2800e000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.052802 0 axruntime:149] [PA:0x2800e000, PA:0x2800f000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.063132 0 axruntime:149] [PA:0x2800f000, PA:0x28010000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.073461 0 axruntime:149] [PA:0x30000000, PA:0x38000000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.083790 0 axruntime:149] [PA:0x40000000, PA:0x80000000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.094119 0 axruntime:149] [PA:0x1000000000, PA:0x3000000000) mmio (READ | WRITE | DEVICE | RESERVED) +[ 39.104796 0 axruntime:228] Initialize global memory allocator... +[ 39.112087 0 axruntime:229] use TLSF allocator. +[ 39.117992 0 axalloc:284] initialize global allocator at: free-[0xffff00009089c000, 0xffff0000ff900000) +[ 39.128902 0 axruntime:163] Initialize kernel page table... +[ 39.135355 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000090100000, VA:0xffff00009012a000) -> [PA:0x90100000, PA:0x9012a000) MappingFlags(READ | EXECUTE) +[ 39.152023 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00009012a000, VA:0xffff000090132000) -> [PA:0x9012a000, PA:0x90132000) MappingFlags(READ) +[ 39.167813 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000090132000, VA:0xffff000090136000) -> [PA:0x90132000, PA:0x90136000) MappingFlags(READ | WRITE) +[ 39.184305 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000090136000, VA:0xffff000090176000) -> [PA:0x90136000, PA:0x90176000) MappingFlags(READ | WRITE) +[ 39.200800 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000090176000, VA:0xffff00009019c000) -> [PA:0x90176000, PA:0x9019c000) MappingFlags(READ | WRITE) +[ 39.217291 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000000000000, VA:0xffff000000001000) -> [PA:0x0, PA:0x1000) MappingFlags(READ | WRITE) +[ 39.232828 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0x9019c000, VA:0x9089c000) -> [PA:0x9019c000, PA:0x9089c000) MappingFlags(READ | WRITE | DEVICE) +[ 39.248723 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00009089c000, VA:0xffff0000ff900000) -> [PA:0x9089c000, PA:0xff900000) MappingFlags(READ | WRITE) +[ 39.265272 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00002800c000, VA:0xffff00002800d000) -> [PA:0x2800c000, PA:0x2800d000) MappingFlags(READ | WRITE | DEVICE) +[ 39.282476 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00002800d000, VA:0xffff00002800e000) -> [PA:0x2800d000, PA:0x2800e000) MappingFlags(READ | WRITE | DEVICE) +[ 39.299749 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00002800e000, VA:0xffff00002800f000) -> [PA:0x2800e000, PA:0x2800f000) MappingFlags(READ | WRITE | DEVICE) +[ 39.317022 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff00002800f000, VA:0xffff000028010000) -> [PA:0x2800f000, PA:0x28010000) MappingFlags(READ | WRITE | DEVICE) +[ 39.334295 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000030000000, VA:0xffff000038000000) -> [PA:0x30000000, PA:0x38000000) MappingFlags(READ | WRITE | DEVICE) +[ 39.351571 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff000040000000, VA:0xffff000080000000) -> [PA:0x40000000, PA:0x80000000) MappingFlags(READ | WRITE | DEVICE) +[ 39.368841 0 page_table::bits64:159] map_region(PA:0x908a4000): [VA:0xffff001000000000, VA:0xffff003000000000) -> [PA:0x1000000000, PA:0x3000000000) MappingFlags(READ | WRITE | DEVICE) +[ 39.386467 0 axhal::arch::aarch64:67] set page table root: PA:0x90132000 => PA:0x908a4000 +[ 39.395837 0 axruntime:263] Initialize global no cache memory allocator... +[ 39.403910 0 axalloc:300] initialize global allocator at: nocache-[0x9019c000,0x9089c000) +[ 39.413285 0 axruntime:170] Initialize platform devices... +[ 39.419967 0 axhal::platform::aarch64_common::gic:51] Initialize GICv2... +[ 39.427953 0 axhal::platform::aarch64_common::gic:27] GICD set enable: 30 true +[ 39.436372 0 axhal::platform::aarch64_common::gic:27] GICD set enable: 56 true +[ 39.444792 0 axtask::api:66] Initialize scheduling... +[ 39.451045 0 axtask::task:146] new task: Task(1, "idle") +[ 39.457555 0 axtask::task:146] new task: Task(3, "gc") +[ 39.463892 0 axalloc:126] expand heap memory: [0xffff0000908ae000, 0xffff0000908ee000) +[ 39.473008 0 axalloc:126] expand heap memory: [0xffff0000908ee000, 0xffff00009096e000) +[ 39.482119 0 axtask::api:72] use Round-robin scheduler. +[ 39.488713 0 axruntime:196] Initialize interrupt handlers... +[ 39.495570 0 axhal::platform::aarch64_common::gic:36] register handler irq 30 +[ 39.503902 0 axhal::platform::aarch64_common::gic:27] GICD set enable: 30 true +[ 39.512322 0 axruntime:206] Primary CPU 512 init OK. +[ 39.518489 0:2 driver_usb::host::data_structures::host_controllers::xhci:639] [XHCI] Max_slots: 16, max_ports: 2, max_irqs: 1, page size: 1 +[ 39.533127 0:2 driver_usb::host::data_structures::host_controllers::xhci:652] [XHCI] ring size 256 +[ 39.542356 0:2 driver_usb:80] initializing! +[ 39.547737 0:2 driver_usb::host::data_structures::host_controllers::xhci:106] [XHCI] Reset begin +[ 39.557718 0:2 driver_usb::host::data_structures::host_controllers::xhci:107] [XHCI] Stop +[ 39.567093 0:2 driver_usb::host::data_structures::host_controllers::xhci:112] [XHCI] Until halt +[ 39.576988 0:2 driver_usb::host::data_structures::host_controllers::xhci:114] [XHCI] Halted +[ 39.586536 0:2 driver_usb::host::data_structures::host_controllers::xhci:119] [XHCI] Wait for ready... +[ 39.597039 0:2 driver_usb::host::data_structures::host_controllers::xhci:121] [XHCI] Ready +[ 39.606501 0:2 driver_usb::host::data_structures::host_controllers::xhci:129] [XHCI] Reset HC +[ 39.616222 0:2 driver_usb::host::data_structures::host_controllers::xhci:145] [XHCI] XCHI reset ok +[ 39.626377 0:2 driver_usb::host::data_structures::host_controllers::xhci:151] [XHCI] Setting enabled slots to 16. +[ 39.637835 0:2 driver_usb::host::data_structures::host_controllers::xhci:160] [XHCI] Writing DCBAAP: 9019D000 +[ 39.648946 0:2 driver_usb::host::data_structures::host_controllers::xhci:173] [XHCI] Writing CRCR: 901BD880 +[ 39.659883 0:2 driver_usb::host::data_structures::host_controllers::xhci:206] [XHCI] Disable interrupts +[ 39.670472 0:2 driver_usb::host::data_structures::host_controllers::xhci:215] [XHCI] Writing ERSTZ +[ 39.680628 0:2 driver_usb::host::data_structures::host_controllers::xhci:219] [XHCI] Writing ERDP: 901BE900 +[ 39.691565 0:2 driver_usb::host::data_structures::host_controllers::xhci:226] [XHCI] Writing ERSTBA: 901BE8C0 +[ 39.702676 0:2 driver_usb::host::data_structures::host_controllers::xhci:236] [XHCI] Enabling primary interrupter. +[ 39.714220 0:2 driver_usb::host::data_structures::host_controllers::xhci:315] [XHCI] Scratch buf count: 0 +[ 39.724982 0:2 driver_usb::host::data_structures::host_controllers::xhci:319] buf count=0,is it a error? +[ 39.735658 0:2 driver_usb::host::data_structures::host_controllers::xhci:188] [XHCI] Start run +[ 39.745468 0:2 driver_usb::host::data_structures::host_controllers::xhci:195] [XHCI] Is running +[ 39.755362 0:2 driver_usb::host::data_structures::host_controllers::xhci:341] [XHCI] Test command ring +[ 39.765866 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 0 @0x901BD880 +0 +0 +0 +5c01 +------------------------------------------------ +[ 39.782270 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> Noop(Noop { cycle_bit: true }) @901BD880 +[ 39.795377 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 39.804753 0:2 driver_usb::host::data_structures::host_controllers::xhci:401] event: PortStatusChange(PortStatusChange { completion_code: Ok(Success), port_id: 1, cycle_bit: true }) +[ 39.822112 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD880 got result, cycle true +[ 39.834785 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 1 @0x901BD890 +0 +0 +0 +5c01 +------------------------------------------------ +[ 39.851189 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> Noop(Noop { cycle_bit: true }) @901BD890 +[ 39.864296 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 39.873671 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD890 got result, cycle true +[ 39.886344 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 2 @0x901BD8A0 +0 +0 +0 +5c01 +------------------------------------------------ +[ 39.902748 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> Noop(Noop { cycle_bit: true }) @901BD8A0 +[ 39.915856 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 39.925230 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD8A0 got result, cycle true +[ 39.937903 0:2 driver_usb::host::data_structures::host_controllers::xhci:347] [XHCI] Command ring ok +[ 39.948232 0:2 driver_usb::host::data_structures::host_controllers::xhci:288] [XHCI] Port 0 start reset +[ 40.016664 0:2 driver_usb::host::data_structures::host_controllers::xhci:301] [XHCI] Port 0 reset ok +[ 40.024121 0:2 driver_usb::host::data_structures::host_controllers::xhci:288] [XHCI] Port 1 start reset +[ 40.034716 0:2 driver_usb::host::data_structures::host_controllers::xhci:301] [XHCI] Port 1 reset ok +[ 40.045040 0:2 driver_usb::host:61] controller init complete +[ 40.051897 0:2 driver_usb::usb:52] usb system driver modules load complete! +[ 40.060056 0:2 driver_usb:83] usb system init complete +[ 40.066394 0:2 driver_usb::host::data_structures::host_controllers::xhci:689] [XHCI] Port 0: Enabled: true, Connected: true, Speed 2, Power true +[ 40.080543 0:2 driver_usb::host::data_structures::host_controllers::xhci:689] [XHCI] Port 1: Enabled: false, Connected: false, Speed 0, Power true +[ 40.094863 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 3 @0x901BD8B0 +0 +0 +0 +2401 +------------------------------------------------ +[ 40.111268 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> EnableSlot(EnableSlot { slot_type: 0, cycle_bit: true }) @901BD8B0 +[ 40.126632 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 40.136007 0:2 driver_usb::host::data_structures::host_controllers::xhci:401] event: PortStatusChange(PortStatusChange { completion_code: Ok(Success), port_id: 1, cycle_bit: true }) +[ 40.153366 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD8B0 got result, cycle true +[ 40.166040 0:2 driver_usb::host::data_structures::host_controllers::xhci:857] assigned slot id: 1 +[ 40.176261 0:2 driver_usb::host::data_structures::host_controllers::xhci:710] assign complete! +[ 40.185919 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 40.197200 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 40.208487 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 4 @0x901BD8C0 +901a1000 +0 +0 +1002c01 +------------------------------------------------ +[ 40.225757 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> AddressDevice(AddressDevice { input_context_pointer: 2417627136, block_set_address_request: false, slot_id: 1, cycle_bit: true }) @901BD8C0 +[ 40.247458 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 40.256832 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD8C0 got result, cycle true +[ 40.269505 0:2 driver_usb::host::data_structures::host_controllers::xhci:926] address slot [1] ok +[ 40.279574 0:2 driver_usb::host::data_structures::host_controllers::xhci:409] slot 1 Addressed +[ 40.289382 0:2 driver_usb::host::data_structures::host_controllers::xhci:418] ep dci 1: Running +[ 40.299455 0:2 driver_usb::host::data_structures::host_controllers::xhci:930] control_fetch_control_point_packet_size +[ 40.311258 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 128, + request: 6, + value: 256, + index: 0, + length: 8, + interrupt_on_completion: false, + transfer_type: In, + cycle_bit: false, +} +[ 40.339206 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 40.350489 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 0 @0x901BF940 +1000680 +80000 +8 +30841 +------------------------------------------------ +[ 40.367849 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 1 @0x901BF950 +901c4140 +0 +8 +10c01 +------------------------------------------------ +[ 40.384948 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 2 @0x901BF960 +0 +0 +0 +1021 +------------------------------------------------ +[ 40.401354 0:2 driver_usb::host::data_structures::host_controllers::xhci:791] [Transfer] >> setup@0x901BF940, data@0x901BF950, status@0x901BF960 +[ 40.415502 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BF960 +[ 40.425920 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BF960 got result1, cycle true, len 0 +[ 40.439893 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bf960 +[ 40.450831 0:2 driver_usb::host::data_structures::host_controllers::xhci:950] got [18, 1, 16, 1, 0, 0, 0, 8] +[ 40.461854 0:2 driver_usb::host::data_structures::host_controllers::xhci:716] packet_size0: 8 +[ 40.471575 0:2 driver_usb::host::data_structures::host_controllers::xhci:964] CMD: evaluating context for set endpoint0 packet size 8 +[ 40.484768 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 5 @0x901BD8D0 +901a1000 +0 +0 +1003401 +------------------------------------------------ +[ 40.502041 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> EvaluateContext(EvaluateContext { input_context_pointer: 2417627136, slot_id: 1, cycle_bit: true }) @901BD8D0 +[ 40.521138 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 40.530512 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD8D0 got result, cycle true +[ 40.543462 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 128, + request: 6, + value: 256, + index: 0, + length: 4096, + interrupt_on_completion: false, + transfer_type: In, + cycle_bit: false, +} +[ 40.571395 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 40.582679 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 3 @0x901BF970 +1000680 +10000000 +8 +30841 +------------------------------------------------ +[ 40.600299 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 4 @0x901BF980 +901c5000 +0 +1000 +10c01 +------------------------------------------------ +[ 40.617659 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 5 @0x901BF990 +0 +0 +0 +1021 +------------------------------------------------ +[ 40.634064 0:2 driver_usb::host::data_structures::host_controllers::xhci:791] [Transfer] >> setup@0x901BF970, data@0x901BF980, status@0x901BF990 +[ 40.648213 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BF990 +[ 40.658630 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BF990 got result1, cycle true, len 0 +[ 40.672603 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bf990 +[ 40.683541 0:2 driver_usb::usb::descriptors:164] parse root desc! +[ 40.690832 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Device) +[ 40.698817 0:2 driver_usb::usb::descriptors:204] parse single device desc! +[ 40.707169 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 128, + request: 6, + value: 512, + index: 0, + length: 4096, + interrupt_on_completion: false, + transfer_type: In, + cycle_bit: false, +} +[ 40.735100 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 40.746383 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 6 @0x901BF9A0 +2000680 +10000000 +8 +30841 +------------------------------------------------ +[ 40.764004 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 7 @0x901BF9B0 +901c5000 +0 +1000 +10c01 +------------------------------------------------ +[ 40.781364 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 8 @0x901BF9C0 +0 +0 +0 +1021 +------------------------------------------------ +[ 40.797769 0:2 driver_usb::host::data_structures::host_controllers::xhci:791] [Transfer] >> setup@0x901BF9A0, data@0x901BF9B0, status@0x901BF9C0 +[ 40.811918 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BF9C0 +[ 40.822335 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BF9C0 got result1, cycle true, len 0 +[ 40.836308 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bf9c0 +[ 40.847245 0:2 driver_usb::usb::descriptors:244] parse config desc! +[ 40.854712 0:2 driver_usb::usb::descriptors:258] num of interfaces:1 +[ 40.862262 0:2 driver_usb::usb::descriptors:276] parse function desc! +[ 40.869900 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Interface) +[ 40.878146 0:2 driver_usb::usb::descriptors:280] parse single interface desc! +[ 40.886479 0:2 driver_usb::usb::descriptors:385] peek at 9,value:9 +[ 40.893857 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Interface) +[ 40.902104 0:2 driver_usb::usb::descriptors:385] peek at 9,value:9 +[ 40.909481 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Interface) +[ 40.917729 0:2 driver_usb::usb::descriptors:289] peeked Interface { + len: 4, + descriptor_type: 0, + interface_number: 0, + alternate_setting: 1, + num_endpoints: 3, + interface_class: 1, + interface_subclass: 2, + interface_protocol: 0, + interface: 9, +},compare with Interface { + len: 4, + descriptor_type: 0, + interface_number: 0, + alternate_setting: 1, + num_endpoints: 3, + interface_class: 1, + interface_subclass: 2, + interface_protocol: 0, + interface: 9, +} +[ 40.965033 0:2 driver_usb::usb::descriptors:290] loop for interface desc! +[ 40.973018 0:2 driver_usb::usb::descriptors:360] parse interfaces +[ 40.980310 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Interface) +[ 40.988555 0:2 driver_usb::usb::descriptors:196] parse any desc! type:Some(Interface) +[ 40.997585 0:2 driver_usb::usb::descriptors:292] got interface Interface { len: 9, descriptor_type: 4, interface_number: 0, alternate_setting: 0, num_endpoints: 1, interface_class: 3, interface_subclass: 1, interface_protocol: 2, interface: 0 } +[ 41.020411 0:2 driver_usb::usb::descriptors:334] parse additional data for interface +[ 41.029352 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Hid) +[ 41.037077 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Hid) +[ 41.044802 0:2 driver_usb::usb::descriptors:196] parse any desc! type:Some(Hid) +[ 41.053311 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Endpoint) +[ 41.061468 0:2 driver_usb::usb::descriptors:348] parse enedpoints +[ 41.068759 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Endpoint) +[ 41.076918 0:2 driver_usb::usb::descriptors:380] peeked type:Some(Endpoint) +[ 41.085077 0:2 driver_usb::usb::descriptors:196] parse any desc! type:Some(Endpoint) +[ 41.094021 0:2 driver_usb::usb::descriptors:380] peeked type:None +[ 41.101310 0:2 driver_usb::usb::descriptors:385] peek at 34,value:0 +[ 41.108774 0:2 driver_usb::usb::descriptors:380] peeked type:None +[ 41.116065 0:2 driver_usb::usb::descriptors:276] parse function desc! +[ 41.123703 0:2 driver_usb::usb::descriptors:380] peeked type:None +[ 41.130997 0:2 driver_usb:213] parsed descriptor:Inited( + TopologicalUSBDescriptorRoot { + device: [ + TopologicalUSBDescriptorDevice { + data: Device { + len: 18, + descriptor_type: 1, + cd_usb: 272, + class: 0, + subclass: 0, + protocol: 0, + max_packet_size0: 8, + vendor: 12538, + product_id: 770, + device: 256, + manufacture: 1, + product: 2, + serial_number: 0, + num_configurations: 1, + }, + child: [ + TopologicalUSBDescriptorConfiguration { + data: Configuration { + length: 9, + ty: 2, + total_length: 34, + num_interfaces: 1, + config_val: 1, + config_string: 0, + attributes: 160, + max_power: 50, + }, + child: [ + Interface( + [ + ( + Interface { + len: 9, + descriptor_type: 4, + interface_number: 0, + alternate_setting: 0, + num_endpoints: 1, + interface_class: 3, + interface_subclass: 1, + interface_protocol: 2, + interface: 0, + }, + [ + Hid( + Hid { + len: 9, + descriptor_type: 33, + hid_bcd: 273, + country_code: 0, + num_descriptions: 1, + report_descriptor_type: 34, + report_descriptor_len: 64, + }, + ), + ], + [ + Endpoint { + len: 7, + descriptor_type: 5, + endpoint_address: 129, + attributes: 3, + max_packet_size: 5, + interval: 10, + ssc: Some( + SuperSpeedCmp { + kind: 0, + max_burst: 0, + attributes: 0, + bytes_per_interval: 0, + }, + ), + }, + ], + ), + ], + ), + ], + }, + ], + }, + ], + others: [], + }, +) +[ 41.497119 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 41.508401 0:2 driver_usb::host::data_structures::host_controllers::xhci:533] init ep 3 InterruptIn +[ 41.518644 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 6 @0x901BD8E0 +901a1000 +0 +0 +1003001 +------------------------------------------------ +[ 41.535916 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:61] [CMD] >> ConfigureEndpoint(ConfigureEndpoint { input_context_pointer: 2417627136, deconfigure: false, slot_id: 1, cycle_bit: true }) @901BD8E0 +[ 41.557096 0:2 driver_usb::host::data_structures::host_controllers::xhci:376] Wait result +[ 41.566470 0:2 driver_usb::host::data_structures::host_controllers::xhci:387] [CMD] << Success @901BD8E0 got result, cycle true +[ 41.579144 0:2 driver_usb::host::data_structures::host_controllers::xhci:409] slot 1 Configured +[ 41.589038 0:2 driver_usb::host::data_structures::host_controllers::xhci:418] ep dci 1: Running +[ 41.599107 0:2 driver_usb::host::data_structures::host_controllers::xhci:418] ep dci 3: Running +[ 41.609181 0:2 driver_usb:98] device probe complete +[ 41.615257 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:167] hid mouse preparing for drive! +[ 41.626368 0:2 driver_usb::usb:70] current driver managed device num: 1 +[ 41.634174 0:2 driver_usb::host:121] tock! check deadlock! +[ 41.640858 0:2 driver_usb::host:100] request transfer! +[ 41.647194 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 0, + request: 9, + value: 1, + index: 0, + length: 0, + interrupt_on_completion: false, + transfer_type: No, + cycle_bit: false, +} +[ 41.674797 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 41.686080 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 9 @0x901BF9D0 +10900 +0 +8 +841 +------------------------------------------------ +[ 41.702746 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 10 @0x901BF9E0 +0 +0 +0 +1021 +------------------------------------------------ +[ 41.719238 0:2 driver_usb::host::data_structures::host_controllers::xhci:785] [Transfer] >> setup@0x901BF9D0, status@0x901BF9E0 +[ 41.731911 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BF9E0 +[ 41.742328 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BF9E0 got result1, cycle true, len 0 +[ 41.756301 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bf9e0 +[ 41.767239 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 41.774096 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 41.783470 0:2 driver_usb::host:100] request transfer! +[ 41.789806 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 1, + request: 11, + value: 0, + index: 0, + length: 0, + interrupt_on_completion: false, + transfer_type: No, + cycle_bit: false, +} +[ 41.817496 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 41.828779 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 11 @0x901BF9F0 +b01 +0 +8 +841 +------------------------------------------------ +[ 41.845358 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 12 @0x901BFA00 +0 +0 +0 +1021 +------------------------------------------------ +[ 41.861850 0:2 driver_usb::host::data_structures::host_controllers::xhci:785] [Transfer] >> setup@0x901BF9F0, status@0x901BFA00 +[ 41.874523 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BFA00 +[ 41.884940 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BFA00 got result1, cycle true, len 0 +[ 41.898914 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bfa00 +[ 41.909851 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 41.916708 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 41.926082 0:2 driver_usb::host:100] request transfer! +[ 41.932419 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 33, + request: 11, + value: 0, + index: 1, + length: 0, + interrupt_on_completion: false, + transfer_type: No, + cycle_bit: false, +} +[ 41.960195 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 41.971479 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 13 @0x901BFA10 +b21 +1 +8 +841 +------------------------------------------------ +[ 41.988058 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 14 @0x901BFA20 +0 +0 +0 +1021 +------------------------------------------------ +[ 42.004550 0:2 driver_usb::host::data_structures::host_controllers::xhci:785] [Transfer] >> setup@0x901BFA10, status@0x901BFA20 +[ 42.017223 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BFA20 +[ 42.027640 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BFA20 got result1, cycle true, len 0 +[ 42.041613 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bfa20 +[ 42.052550 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 42.059407 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 42.068782 0:2 driver_usb::host:100] request transfer! +[ 42.075118 0:2 driver_usb::host::data_structures::host_controllers::xhci:762] SetupStage { + interrupt_on_completion: false, + request_type: 129, + request: 6, + value: 8704, + index: 0, + length: 1, + interrupt_on_completion: false, + transfer_type: In, + cycle_bit: false, +} +[ 42.103154 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci1 +[ 42.114438 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 15 @0x901BFA30 +22000681 +10000 +8 +30841 +------------------------------------------------ +[ 42.131972 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 16 @0x901BFA40 +901c5000 +0 +1 +10c01 +------------------------------------------------ +[ 42.149158 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 17 @0x901BFA50 +0 +0 +0 +1021 +------------------------------------------------ +[ 42.165650 0:2 driver_usb::host::data_structures::host_controllers::xhci:791] [Transfer] >> setup@0x901BFA30, data@0x901BFA40, status@0x901BFA50 +[ 42.179799 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901BFA50 +[ 42.190216 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << Success @0x901BFA50 got result1, cycle true, len 0 +[ 42.204189 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:Success,pointer:901bfa50 +[ 42.215126 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 42.221983 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 42.231358 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 42.242643 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 0 @0x901BFDC0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.258960 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 1 @0x901BFDD0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.275279 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 2 @0x901BFDE0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.291597 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 3 @0x901BFDF0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.307916 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 4 @0x901BFE00 +0 +0 +0 +401 +------------------------------------------------ +[ 42.324234 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 5 @0x901BFE10 +0 +0 +0 +401 +------------------------------------------------ +[ 42.340552 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 6 @0x901BFE20 +0 +0 +0 +401 +------------------------------------------------ +[ 42.356871 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 7 @0x901BFE30 +0 +0 +0 +401 +------------------------------------------------ +[ 42.373189 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 8 @0x901BFE40 +0 +0 +0 +401 +------------------------------------------------ +[ 42.389507 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 9 @0x901BFE50 +0 +0 +0 +401 +------------------------------------------------ +[ 42.405826 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 10 @0x901BFE60 +0 +0 +0 +401 +------------------------------------------------ +[ 42.422231 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 11 @0x901BFE70 +0 +0 +0 +401 +------------------------------------------------ +[ 42.438636 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 12 @0x901BFE80 +0 +0 +0 +401 +------------------------------------------------ +[ 42.455041 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 13 @0x901BFE90 +0 +0 +0 +401 +------------------------------------------------ +[ 42.471447 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 14 @0x901BFEA0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.487852 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 15 @0x901BFEB0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.504257 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 16 @0x901BFEC0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.520662 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 17 @0x901BFED0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.537067 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 18 @0x901BFEE0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.553473 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 19 @0x901BFEF0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.569878 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 20 @0x901BFF00 +0 +0 +0 +401 +------------------------------------------------ +[ 42.586283 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 21 @0x901BFF10 +0 +0 +0 +401 +------------------------------------------------ +[ 42.602688 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 22 @0x901BFF20 +0 +0 +0 +401 +------------------------------------------------ +[ 42.619094 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 23 @0x901BFF30 +0 +0 +0 +401 +------------------------------------------------ +[ 42.635499 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 24 @0x901BFF40 +0 +0 +0 +401 +------------------------------------------------ +[ 42.651904 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 25 @0x901BFF50 +0 +0 +0 +401 +------------------------------------------------ +[ 42.668309 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 26 @0x901BFF60 +0 +0 +0 +401 +------------------------------------------------ +[ 42.684714 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 27 @0x901BFF70 +0 +0 +0 +401 +------------------------------------------------ +[ 42.701119 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 28 @0x901BFF80 +0 +0 +0 +401 +------------------------------------------------ +[ 42.717525 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 29 @0x901BFF90 +0 +0 +0 +401 +------------------------------------------------ +[ 42.733930 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 30 @0x901BFFA0 +0 +0 +0 +401 +------------------------------------------------ +[ 42.750335 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:101] flip and link! +[ 42.760491 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:107] link! +[ 42.769865 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 42.776722 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 42.786100 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 42.795039 0:2 driver_usb:126] tick! 1 +[ 42.799985 0:2 driver_usb::host:121] tock! check deadlock! +[ 42.806668 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 42.817952 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 0 @0x901BFDC0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 42.834879 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 43.742474 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFDC0 got result13, cycle true, len 5 +[ 43.754011 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfdc0 +[ 43.765296 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 43.775972 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 43.782829 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 43.792205 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[1, 0, 0, 0, 0, 0, 0, 0] +[ 43.804095 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 43.813035 0:2 driver_usb:126] tick! 1 +[ 43.817983 0:2 driver_usb::host:121] tock! check deadlock! +[ 43.824666 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 43.835950 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 1 @0x901BFDD0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 43.852877 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 43.863293 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFDD0 got result13, cycle true, len 5 +[ 43.877701 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfdd0 +[ 43.888985 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 43.899662 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 43.906519 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 43.915894 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[1, 3, 3, 0, 0, 0, 0, 0] +[ 43.927785 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 43.936725 0:2 driver_usb:126] tick! 1 +[ 43.941673 0:2 driver_usb::host:121] tock! check deadlock! +[ 43.948356 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 43.959640 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 2 @0x901BFDE0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 43.976567 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 43.986983 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFDE0 got result13, cycle true, len 5 +[ 44.001391 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfde0 +[ 44.012675 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 44.023351 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 44.030209 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 44.039585 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 2, 2, 0, 0, 0, 0, 0] +[ 44.051475 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 44.060415 0:2 driver_usb:126] tick! 1 +[ 44.065363 0:2 driver_usb::host:121] tock! check deadlock! +[ 44.072046 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 44.083330 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 3 @0x901BFDF0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 44.100257 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 44.110674 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFDF0 got result13, cycle true, len 5 +[ 44.125081 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfdf0 +[ 44.136365 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 44.147042 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 44.153899 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 44.163275 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 1, 1, 0, 0, 0, 0, 0] +[ 44.175165 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 44.184105 0:2 driver_usb:126] tick! 1 +[ 44.189053 0:2 driver_usb::host:121] tock! check deadlock! +[ 44.195736 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 44.207020 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 4 @0x901BFE00 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 44.223947 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 44.781474 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE00 got result13, cycle true, len 5 +[ 44.793011 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe00 +[ 44.804295 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 44.814972 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 44.821829 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 44.831205 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[2, 0, 0, 0, 0, 0, 0, 0] +[ 44.843095 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 44.852036 0:2 driver_usb:126] tick! 1 +[ 44.856983 0:2 driver_usb::host:121] tock! check deadlock! +[ 44.863667 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 44.874951 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 5 @0x901BFE10 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 44.891877 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 44.902294 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE10 got result13, cycle true, len 5 +[ 44.916701 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe10 +[ 44.927985 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 44.938662 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 44.945519 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 44.954895 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 0, 0, 0, 0, 0, 0, 0] +[ 44.966785 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 44.975726 0:2 driver_usb:126] tick! 1 +[ 44.980673 0:2 driver_usb::host:121] tock! check deadlock! +[ 44.987357 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 44.998641 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 6 @0x901BFE20 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 45.015567 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 45.673474 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE20 got result13, cycle true, len 5 +[ 45.685011 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe20 +[ 45.696295 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 45.706972 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 45.713829 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 45.723204 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 0, 1, 0, 0, 0, 0, 0] +[ 45.735095 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 45.744035 0:2 driver_usb:126] tick! 1 +[ 45.748983 0:2 driver_usb::host:121] tock! check deadlock! +[ 45.755666 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 45.766950 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 7 @0x901BFE30 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 45.783877 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 45.794294 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE30 got result13, cycle true, len 5 +[ 45.808701 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe30 +[ 45.819985 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 45.830662 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 45.837519 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 45.846894 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 64, 255, 0, 0, 0, 0, 0] +[ 45.859045 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 45.867986 0:2 driver_usb:126] tick! 1 +[ 45.872933 0:2 driver_usb::host:121] tock! check deadlock! +[ 45.879617 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 45.890901 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 8 @0x901BFE40 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 45.907827 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 45.918244 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE40 got result13, cycle true, len 5 +[ 45.932651 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe40 +[ 45.943935 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 45.954612 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 45.961469 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 45.970845 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 29, 0, 0, 0, 0, 0, 0] +[ 45.982822 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 45.991763 0:2 driver_usb:126] tick! 1 +[ 45.996710 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.003393 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.014677 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 9 @0x901BFE50 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.031604 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.042021 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE50 got result13, cycle true, len 5 +[ 46.056428 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe50 +[ 46.067712 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.078389 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.085246 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.094622 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 15, 0, 0, 0, 0, 0, 0] +[ 46.106599 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 46.115539 0:2 driver_usb:126] tick! 1 +[ 46.120487 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.127170 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.138454 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 10 @0x901BFE60 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.155467 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.165884 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE60 got result13, cycle true, len 5 +[ 46.180292 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe60 +[ 46.191576 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.202252 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.209109 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.218485 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 7, 0, 0, 0, 0, 0, 0] +[ 46.230376 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 46.239316 0:2 driver_usb:126] tick! 1 +[ 46.244263 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.250947 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.262231 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 11 @0x901BFE70 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.279244 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.289661 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE70 got result13, cycle true, len 5 +[ 46.304069 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe70 +[ 46.315353 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.326029 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.332886 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.342262 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 4, 0, 0, 0, 0, 0, 0] +[ 46.354153 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 46.363093 0:2 driver_usb:126] tick! 1 +[ 46.368040 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.374724 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.386008 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 12 @0x901BFE80 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.403021 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.413438 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE80 got result13, cycle true, len 5 +[ 46.427845 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe80 +[ 46.439129 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.449806 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.456663 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.466039 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 2, 0, 0, 0, 0, 0, 0] +[ 46.477930 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 46.486870 0:2 driver_usb:126] tick! 1 +[ 46.491817 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.498501 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.509785 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 13 @0x901BFE90 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.526798 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.537215 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFE90 got result13, cycle true, len 5 +[ 46.551622 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfe90 +[ 46.562906 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.573583 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.580440 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.589816 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 255, 1, 0, 0, 0, 0, 0] +[ 46.601880 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 46.610820 0:2 driver_usb:126] tick! 1 +[ 46.615767 0:2 driver_usb::host:121] tock! check deadlock! +[ 46.622451 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 46.633735 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 14 @0x901BFEA0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 46.650748 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 46.937474 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFEA0 got result13, cycle true, len 5 +[ 46.949011 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfea0 +[ 46.960295 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 46.970972 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 46.977829 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 46.987204 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 255, 1, 0, 0, 0, 0, 0] +[ 46.999269 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.008209 0:2 driver_usb:126] tick! 1 +[ 47.013156 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.019840 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.031124 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 15 @0x901BFEB0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.048137 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.058554 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFEB0 got result13, cycle true, len 5 +[ 47.072961 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfeb0 +[ 47.084245 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.094922 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.101779 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.111155 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 232, 3, 0, 0, 0, 0, 0] +[ 47.123219 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.132159 0:2 driver_usb:126] tick! 1 +[ 47.137107 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.143790 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.155074 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 16 @0x901BFEC0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.172087 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.182504 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFEC0 got result13, cycle true, len 5 +[ 47.196912 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfec0 +[ 47.208196 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.218872 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.225729 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.235105 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 240, 0, 0, 0, 0, 0, 0] +[ 47.247170 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.256110 0:2 driver_usb:126] tick! 1 +[ 47.261057 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.267741 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.279025 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 17 @0x901BFED0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.296038 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.306455 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFED0 got result13, cycle true, len 5 +[ 47.320862 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfed0 +[ 47.332146 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.342823 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.349680 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.359056 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 248, 0, 0, 0, 0, 0, 0] +[ 47.371120 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.380060 0:2 driver_usb:126] tick! 1 +[ 47.385007 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.391691 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.402975 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 18 @0x901BFEE0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.419988 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.430405 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFEE0 got result13, cycle true, len 5 +[ 47.444813 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfee0 +[ 47.456097 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.466773 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.473630 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.483006 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 252, 0, 0, 0, 0, 0, 0] +[ 47.495070 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.504011 0:2 driver_usb:126] tick! 1 +[ 47.508958 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.515642 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.526926 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 19 @0x901BFEF0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.543939 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.554356 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFEF0 got result13, cycle true, len 5 +[ 47.568763 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bfef0 +[ 47.580047 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.590724 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.597581 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.606956 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 254, 0, 0, 0, 0, 0, 0] +[ 47.619021 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.627961 0:2 driver_usb:126] tick! 1 +[ 47.632908 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.639592 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.650876 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 20 @0x901BFF00 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.667889 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.678306 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF00 got result13, cycle true, len 5 +[ 47.692714 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff00 +[ 47.703997 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.714674 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.721531 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.730907 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 255, 0, 0, 0, 0, 0, 0] +[ 47.742971 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.751911 0:2 driver_usb:126] tick! 1 +[ 47.756859 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.763542 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.774826 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 21 @0x901BFF10 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.791840 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.802256 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF10 got result13, cycle true, len 5 +[ 47.816664 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff10 +[ 47.827948 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.838624 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.845482 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.854857 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 255, 0, 0, 0, 0, 0, 0] +[ 47.866922 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.875862 0:2 driver_usb:126] tick! 1 +[ 47.880809 0:2 driver_usb::host:121] tock! check deadlock! +[ 47.887493 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 47.898777 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 22 @0x901BFF20 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 47.915790 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 47.926207 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF20 got result13, cycle true, len 5 +[ 47.940614 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff20 +[ 47.951898 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 47.962575 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 47.969432 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 47.978808 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 1, 254, 0, 0, 0, 0, 0] +[ 47.990872 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 47.999812 0:2 driver_usb:126] tick! 1 +[ 48.004759 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.011443 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.022727 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 23 @0x901BFF30 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.039740 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.349475 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x0 got result13, cycle true, len 5 +[ 48.360404 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:0 +[ 48.371080 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 48.381757 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 48.388614 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 48.397990 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 0, 255, 0, 0, 0, 0, 0] +[ 48.410054 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 48.418994 0:2 driver_usb:126] tick! 1 +[ 48.423942 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.430625 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.441909 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 24 @0x901BFF40 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.458922 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.469339 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF40 got result13, cycle true, len 5 +[ 48.483747 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff40 +[ 48.495031 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 48.505707 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 48.512564 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 48.521940 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 239, 201, 0, 0, 0, 0, 0] +[ 48.534178 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 48.543118 0:2 driver_usb:126] tick! 1 +[ 48.548066 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.554749 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.566033 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 25 @0x901BFF50 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.583046 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.593463 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF50 got result13, cycle true, len 5 +[ 48.607871 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff50 +[ 48.619155 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 48.629831 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 48.636688 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 48.646064 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 243, 218, 0, 0, 0, 0, 0] +[ 48.658302 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 48.667242 0:2 driver_usb:126] tick! 1 +[ 48.672190 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.678873 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.690157 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 26 @0x901BFF60 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.707170 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.717587 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF60 got result13, cycle true, len 5 +[ 48.731995 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff60 +[ 48.743279 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 48.753955 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 48.760812 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 48.770188 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 250, 237, 0, 0, 0, 0, 0] +[ 48.782426 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 48.791366 0:2 driver_usb:126] tick! 1 +[ 48.796314 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.802997 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.814281 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 27 @0x901BFF70 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.831295 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.841711 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF70 got result13, cycle true, len 5 +[ 48.856119 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff70 +[ 48.867403 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 48.878079 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 48.884936 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 48.894312 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 253, 247, 0, 0, 0, 0, 0] +[ 48.906550 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 48.915490 0:2 driver_usb:126] tick! 1 +[ 48.920438 0:2 driver_usb::host:121] tock! check deadlock! +[ 48.927121 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 48.938405 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 28 @0x901BFF80 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 48.955418 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 48.965835 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF80 got result13, cycle true, len 5 +[ 48.980243 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff80 +[ 48.991527 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 49.002203 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 49.009060 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 49.018436 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 254, 251, 0, 0, 0, 0, 0] +[ 49.030674 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 49.039614 0:2 driver_usb:126] tick! 1 +[ 49.044562 0:2 driver_usb::host:121] tock! check deadlock! +[ 49.051245 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 49.062529 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 29 @0x901BFF90 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 49.079542 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 49.089959 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFF90 got result13, cycle true, len 5 +[ 49.104367 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bff90 +[ 49.115651 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 49.126327 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 49.133184 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 49.142560 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 255, 254, 0, 0, 0, 0, 0] +[ 49.154798 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 49.163738 0:2 driver_usb:126] tick! 1 +[ 49.168686 0:2 driver_usb::host:121] tock! check deadlock! +[ 49.175369 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 49.186653 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 30 @0x901BFFA0 +901c6000 +0 +8 +424 +------------------------------------------------ +[ 49.203666 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:101] flip and link! +[ 49.213822 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:107] link! +[ 49.223196 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 +[ 49.233613 0:2 driver_usb::host::data_structures::host_controllers::xhci:461] [Transfer] << ShortPacket @0x901BFFA0 got result13, cycle true, len 5 +[ 49.248021 0:2 driver_usb::host::data_structures::host_controllers::xhci:474] code:ShortPacket,pointer:901bffa0 +[ 49.259305 0:2 driver_usb::host::data_structures::host_controllers::xhci:1001] ok! return a success ucb! +[ 49.269981 0:2 driver_usb::host:127] tock! check deadlock! 2 +[ 49.276838 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:153] completed! +[ 49.286214 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:158] current buffer:[0, 0, 255, 0, 0, 0, 0, 0] +[ 49.298278 0:2 driver_usb::usb::universal_drivers::hid_drivers::hid_mouse:135] some! +[ 49.307219 0:2 driver_usb:126] tick! 1 +[ 49.312166 0:2 driver_usb::host:121] tock! check deadlock! +[ 49.318850 0:2 driver_usb::host::data_structures::host_controllers::xhci:437] fetch transfer ring at slot1-dci3 +[ 49.330134 0:2 driver_usb::host::data_structures::host_controllers::xhci::ring:78] enqueued 0 @0x901BFDC0 +901c6000 +0 +8 +425 +------------------------------------------------ +[ 49.347060 0:2 driver_usb::host::data_structures::host_controllers::xhci:452] Wait result @0x901C6000 diff --git a/doc/resources/res/usb-hid.png b/doc/resources/res/usb-hid.png new file mode 100644 index 0000000000..4a574f30dc Binary files /dev/null and b/doc/resources/res/usb-hid.png differ diff --git "a/doc/resources/\351\243\236\350\205\276\346\264\276\346\225\260\346\215\256\346\211\213\345\206\214V1.0\347\211\210\346\234\254.pdf" "b/doc/resources/\351\243\236\350\205\276\346\264\276\346\225\260\346\215\256\346\211\213\345\206\214V1.0\347\211\210\346\234\254.pdf" new file mode 100644 index 0000000000..b27a808d86 Binary files /dev/null and "b/doc/resources/\351\243\236\350\205\276\346\264\276\346\225\260\346\215\256\346\211\213\345\206\214V1.0\347\211\210\346\234\254.pdf" differ diff --git "a/doc/resources/\351\243\236\350\205\276\346\264\276\350\275\257\344\273\266\347\274\226\347\250\213\346\211\213\345\206\214V1.0.pdf" "b/doc/resources/\351\243\236\350\205\276\346\264\276\350\275\257\344\273\266\347\274\226\347\250\213\346\211\213\345\206\214V1.0.pdf" new file mode 100644 index 0000000000..109f7b0733 Binary files /dev/null and "b/doc/resources/\351\243\236\350\205\276\346\264\276\350\275\257\344\273\266\347\274\226\347\250\213\346\211\213\345\206\214V1.0.pdf" differ diff --git a/doc/ymodem.txt b/doc/ymodem.txt new file mode 100644 index 0000000000..f09f81ecf2 --- /dev/null +++ b/doc/ymodem.txt @@ -0,0 +1,1650 @@ + + + + - 1 - + + + + XMODEM/YMODEM PROTOCOL REFERENCE + A compendium of documents describing the + + XMODEM and YMODEM + + File Transfer Protocols + + + + + + + + + + + + Edited by Chuck Forsberg + + + + + + + + + + + + + + + Please distribute as widely as possible. + + Questions to Chuck Forsberg + + + + + + Omen Technology Inc + 17505-V Sauvie Island Road + Portland Oregon 97231 + Voice: 503-621-3406 + Modem (Telegodzilla): 503-621-3746 Speed 1200,300 + Compuserve: 70715,131 + UUCP: ...!tektronix!reed!omen!caf + + + + + + + + + + + + + + + + - 2 - + + + +1. ROSETTA STONE + +Here are some definitions which reflect the current vernacular in the +computer media. The attempt here is identify the file transfer protocol +rather than specific programs. + +XMODEM refers to the original 1979 file transfer etiquette introduced by + Ward Christensen's 1979 MODEM2 program. It's also called the + MODEM or MODEM2 protocol. Some who are unaware of MODEM7's + unusual batch file mode call it MODEM7. Other aliases include + "CP/M Users's Group" and "TERM II FTP 3". This protocol is + supported by every serious communications program because of its + universality, simplicity, and reasonable performance. + +XMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclical + Redunancy Check (CRC-16), giving modern error detection + protection. + +YMODEM refers to the XMODEM/CRC protocol with the throughput and/or batch + transmission enhancements described below. + + +2. YET ANOTHER PROTOCOL? + +Since its development half a decade ago, the Ward Christensen modem +protocol has enabled a wide variety of computer systems to interchange +data. There is hardly a communications program that doesn't at least +claim to support this protocol. + +Recent advances in computing, modems and networking have revealed a number +of weaknesses in the original protocol: + + + The short block length caused throughput to suffer when used with + timesharing systems, packet switched networks, satellite circuits, + and buffered (error correcting) modems. + + + The 8 bit arithmetic checksum and other aspects allowed line + impairments to interfere with dependable, accurate transfers. + + + Only one file could be sent per command. The file name had to be + given twice, first to the sending program and then again to the + receiving program. + + + The transmitted file could accumulate as many as 127 extraneous + bytes. + + + The modification date of the file was lost. + +A number of other protocols have been developed over the years, but none +have displaced XMODEM to date: + + + + +Chapter 2 + + + + + + + +X/YMODEM Protocol Reference 10-10-85 3 + + + + + Lack of public domain documentation and example programs have kept + proprietary protocols such as MNP, Blast, and others tightly bound to + the fortunes of their suppliers. + + + Complexity discourages the widespread application of BISYNC, SDLC, + HDLC, X.25, and X.PC protocols. + + + Performance compromises and moderate complexity have limited the + popularity of the Kermit protocol, which was developed to allow file + transfers in environments hostile to XMODEM. + +The YMODEM Protocol extensions were developed as a means of addressing the +weaknesses described above while maintaining XMODEM's simplicity as much +as possible. + +YMODEM is supported by the public domain programs YAM (CP/M), +YAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), MODEM76.ASM (CP/M), +rb/sb (Unix, VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus) +as well as Professional-YAM.1 These programs have been in use since 1981. + +The 1k packet length capability described below may be used in conjunction +with the Batch Protocol, or with single file transfers identical to the +XMODEM/CRC protocol except for the minimal changes to support 1k packets. + +Another extension is simply called the g option. It provides maximum +throughput when used with end to end error correcting media, such as X.PC +and error correcting modems, including the emerging 9600 bps units by +Electronic Vaults and others. + +To complete this tome, Ward Christensen's original protocol document and +John Byrns's CRC-16 document are included for reference. + +References to the MODEM or MODEM7 protocol have been changed to XMODEM to +accommodate the vernacular. In Australia, it is properly called the +Christensen Portocol. + +Watch for an article describing the YMODEM protocol in a more coherent +fashion later this year. The article will include some interesting +history on the development of microcomputer file transfers. + + + + + + + + +__________ + + 1. Available for IBM PC,XT,AT, Unix and Xenix + + + + +Chapter 2 + + + + + + + +X/YMODEM Protocol Reference 10-10-85 4 + + + +2.1 Some Messages from the Pioneer + +#: 130940 S0/Communications 25-Apr-85 18:38:47 +Sb: my protocol +Fm: Ward Christensen 76703,302 (EDITED) +To: all + +Be aware the article2 DID quote me correctly in terms of the phrases like +"not robust", etc. + +It was a quick hack I threw together, very unplanned (like everything I +do), to satisfy a personal need to communicate with "some other" people. + +ONLY the fact that it was done in 8/77, and that I put it in the public +domain immediately, made it become the standard that it is. + +I think its time for me to + +(1) document it; (people call me and say "my product is going to include +it - what can I 'reference'", or "I'm writing a paper on it, what do I put +in the bibliography") and + +(2) propose an "incremental extension" to it, which might take "exactly" +the form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M and +put it in the public domain, and wrote a batch protocol for Unix3 called +rb and sb (receive batch, send batch), which was basically XMODEM with + (a) a record 0 containing filename date time and size + (b) a 1K block size option + (c) CRC-16. + +He did some clever programming to detect false ACK or EOT, but basically +left them the same. + +People who suggest I make SIGNIFICANT changes to the protocol, such as +"full duplex", "multiple outstanding blocks", "multiple destinations", etc +etc don't understand that the incredible simplicity of the protocol is one +of the reasons it survived to this day in as many machines and programs as +it may be found in! + +Consider the PC-NET group back in '77 or so - documenting to beat the band +- THEY had a protocol, but it was "extremely complex", because it tried to +be "all things to all people" - i.e. send binary files on a 7-bit system, +etc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART, + + +__________ + + 2. Infoworld April 29 p. 16 + + 3. VAX/VMS versions of these programs are also available. + + + + +Chapter 2 + + + + + + + +X/YMODEM Protocol Reference 10-10-85 5 + + + +so "my protocol was an 8-bit protocol", and I would just say "sorry" to +people who were held back by 7-bit limitations. ... + +Block size: Chuck Forsberg created an extension of my protocol, called +YAM, which is also supported via his public domain programs for UNIX +called rb and sb - receive batch and send batch. They cleverly send a +"block 0" which contains the filename, date, time, and size. +Unfortunately, its UNIX style, and is a bit weird4 - octal numbers, etc. +BUT, it is a nice way to overcome the kludgy "echo the chars of the name" +introduced with MODEM7. Further, chuck uses CRC-16 and optional 1K +blocks. Thus the record 0, 1K, and CRC, make it a "pretty slick new +protocol" which is not significantly different from my own. + +Also, there is a catchy name - YMODEM. That means to some that it is the +"next thing after XMODEM", and to others that it is the Y(am)MODEM +protocol. I don't want to emphasize that too much - out of fear that +other mfgrs might think it is a "competitive" protocol, rather than an +"unaffiliated" protocol. Chuck is currently selling a much-enhanced +version of his CP/M-80 C program YAM, calling it Professional Yam, and its +for the PC - I'm using it right now. VERY slick! 32K capture buffer, +script, scrolling, previously captured text search, plus built-in commands +for just about everything - directory (sorted every which way), XMODEM, +YMODEM, KERMIT, and ASCII file upload/download, etc. You can program it +to "behave" with most any system - for example when trying a number for +CIS it detects the "busy" string back from the modem and substitutes a +diff phone # into the dialing string and branches back to try it. + + + +3. XMODEM PROTOCOL ENHANCEMENTS + +This chapter discusses the protocol extensions to Ward Christensen's 1982 +XMODEM protocol description document. + +The original document recommends the user be asked whether to continue +trying or abort after 10 retries. Most programs no longer ask the +operator whether he wishes to keep retrying. Virtually all correctable +errors are corrected within the first few retransmissions. If the line is +so bad that ten attempts are insufficient, there is a significant danger +of undetected errors. If the connection is that bad, it's better to +redial for a better connection, or mail a floppy disk. + + + + + +__________ + + 4. The file length, time, and file mode are optional. The pathname and + file length may be sent alone if desired. + + + + +Chapter 3 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 6 + + + +3.1 Graceful Abort + +YAM and Professional-YAM recognize a sequence of two consecutive CAN (Hex +18) characters without modem errors (overrun, framing, etc.) as a transfer +abort command.1 The check for two consecutive CAN characters virtually +eliminates the possibility of a line hit aborting the transfer. YAM sends +five CAN characters when it aborts an XMODEM or YMODEM protocol file +transfer, followed by five backspaces to delete the CAN characters from +the remote's keyboard input buffer (in case the remote had already aborted +the transfer). + + +3.2 CRC-16 Option + +The XMODEM protocol uses an optional two character CRC-16 instead of the +one character arithmetic checksum used by the original protocol and by +most commercial implementations. CRC-16 guarantees detection of all +single and double bit errors, all errors with an odd number of error +bits, all burst errors of length 16 or less, 99.9969% of all 17-bit error +bursts, and 99.9984 per cent of all possible longer error bursts. By +contrast, a double bit error, or a burst error of 9 bits or more can sneak +past the XMODEM protocol arithmetic checksum. + +The XMODEM/CRC protocol is similar to the XMODEM protocol, except that the +receiver specifies CRC-16 by sending C (Hex 43) instead of NAK when +requesting the FIRST packet. A two byte CRC is sent in place of the one +byte arithmetic checksum. + +YAM's c option to the r command enables CRC-16 in single file reception, +corresponding to the original implementation in the MODEM7 series +programs. This remains the default because many commercial communications +programs and bulletin board systems still do not support CRC-16, +especially those written in Basic or Pascal. + +XMODEM protocol with CRC is accurate provided both sender and receiver +both report a successful transmission. The protocol is robust in the +presence of characters lost by buffer overloading on timesharing systems. + +The single character ACK/NAK responses generated by the receiving program +adapt well to split speed modems, where the reverse channel is limited to +ten per cent or less of the main channel's speed. + +XMODEM and YMODEM are half duplex protocols which do not attempt to +transmit information and control signals in both directions at the same + + +__________ + + 1. This is recognized when YAM is waiting for the beginning of a packet + or for an acknowledge to one that has been sent. + + + + +Chapter 3 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 7 + + + +time. This avoids buffer overrun problems that have been reported by +users attempting to exploit full duplex aynchronous file transfer +protocols such as Blast. + +Professional-YAM adds several proprietary logic enhancements to XMODEM's +error detection and recovery. These compatible enhancements eliminate +most of the bad file transfers other programs make when using the XMODEM +protocol under less than ideal conditions. + + +3.3 1024 Byte Packet Option + +The choice to use 1024 byte packets is expressed to the sending program on +its command line or selection menu. + +Programs using the Hoff protocol use a two character sequence emitted by +the receiver (CK) to automatically trigger the use of 1024 byte packets as +an alternative to specifying this option on this command line. Although +this two character sequence works well on single process micros in direct +communication, timesharing systems and packet switched networks can +separate the successive characters by several seconds, rendering this +method unreliable. + +An STX (02) replaces the SOH (01) at the beginning of the transmitted +block to notify the receiver of the longer packet length. The transmitted +packet contains 1024 bytes of data. The receiver should be able to accept +any mixture of 128 and 1024 byte packets. The packet number is +incremented by one for each packet regardless of the packet length. + +The sender must not change between 128 and 1024 byte packet lengths if it +has not received a valid ACK for the current packet. Failure to observe +this restriction allows certain transmission errors to pass undetected. + +If 1024 byte packets are being used, it is possible for a file to "grow" +up to the next multiple of 1024 bytes. This does not waste disk space if +the allocation granularity is 1k or greater. When 1024 byte packets are +used with YMODEM batch transmission, the file length transmitted in the +file name packet allows the receiver to discard the padding, preserving +the exact file length and contents. + +CRC-16 should be used with the k option to preserve data integrity over +phone lines.2 1024 byte packets may be used with batch file transmission +or with single file transmission. + + + + +__________ + + 2. Some programs enforce this recommendation. + + + + +Chapter 3 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 8 + + + + Figure 1. 1024 byte Packets + + SENDER RECEIVER + "s -k foo.bar" + "foo.bar open x.x minutes" + C + STX 01 FE Data[1024] CRC CRC + ACK + STX 02 FD Data[1024] CRC CRC + ACK + STX 03 FC Data[1000] CPMEOF[24] CRC CRC + ACK + EOT + ACK + + Figure 2. Mixed 1024 and 128 byte Packets + + SENDER RECEIVER + "s -k foo.bar" + "foo.bar open x.x minutes" + C + STX 01 FE Data[1024] CRC CRC + ACK + STX 02 FD Data[1024] CRC CRC + ACK + SOH 03 FC Data[128] CRC CRC + ACK + SOH 04 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + ACK + +4. YMODEM Batch File Transmission + +The YMODEM Batch protocol is an extension to the XMODEM/CRC protocol that +allows 0 or more files to be transmitted with a single command. (Zero +files may be sent if none of the requested files is accessible.) The +design approach of the YMODEM Batch protocol is to use the normal routines +for sending and receiving XMODEM packets in a layered fashion similar to +packet switching methods. + +Why was it necessary to design a new batch protocol when one already +existed in MODEM7?1 The batch file mode used by MODEM7 is unsuitable + + +__________ + + 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 and + t1...t3 one character at a time. The receiver echoed these bytes as + received, one at a time. + + + + +Chapter 4 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 9 + + + +because it does not permit full pathnames, file length, file date, or +other attribute information to be transmitted. Such a restrictive design, +hastily implemented with only CP/M in mind, would not have permitted +extensions to current areas of personal computing such as Unix, DOS, and +object oriented systems. In addition, the MODEM7 batch file mode is +somewhat susceptible to transmission impairments. + +As in the case of single a file transfer, the receiver initiates batch +file transmission by sending a "C" character (for CRC-16). + +The sender opens the first file and sends packet number 0 with the +following information.2 + +Only the pathname (file name) part is required for batch transfers. + +To maintain upwards compatibility, all unused bytes in packet 0 must be +set to null. + +Pathname The pathname (conventionally, the file name) is sent as a null + terminated ASCII string. This is the filename format used by the + handle oriented MSDOS(TM) functions and C library fopen functions. + An assembly language example follows: + DB 'foo.bar',0 + No spaces are included in the pathname. Normally only the file name + stem (no directory prefix) is transmitted unless the sender has + selected YAM's f option to send the full pathname. The source drive + (A:, B:, etc.) is never sent. + + Filename Considerations: + + + File names should be translated to lower case unless the sending + system supports upper/lower case file names. This is a + convenience for users of systems (such as Unix) which store + filenames in upper and lower case. + + + The receiver should accommodate file names in lower and upper + case. + + + The rb(1) program on Unix systems normally translates the + filename to lower case unless one or more letters in the + filename are already in lower case. + + + When transmitting files between different operating systems, + file names must be acceptable to both the sender and receiving + operating systems. + + +__________ + + 2. Only the data part of the packet is described here. + + + + +Chapter 4 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 10 + + + + If directories are included, they are delimited by /; i.e., + "subdir/foo" is acceptable, "subdir\foo" is not. + +Length The file length and each of the succeeding fields are optional.3 + The length field is stored in the packet as a decimal string counting + the number of data bytes in the file. The file length does not + include any CPMEOF (^Z) characters used to pad the last packet. + + If the file being transmitted is growing during transmission, the + length field should be set to at least the final expected file + length, or not sent. + + The receiver stores the specified number of characters, discarding + any padding added by the sender to fill up the last packet. + +Modification Date A single space separates the modification date from the + file length. + + The mod date is optional, and the filename and length may be sent + without requiring the mod date to be sent. + + The mod date is sent as an octal number giving the time the contents + of the file were last changed measured in seconds from Jan 1 1970 + Universal Coordinated Time (GMT). A date of 0 implies the + modification date is unknown and should be left as the date the file + is received. + + This standard format was chosen to eliminate ambiguities arising from + transfers between different time zones. + + Two Microsoft blunders complicate the use of modification dates in + file transfers with MSDOS(TM) systems. The first is the lack of + timezone standardization in MS-DOS. A file's creation time can not + be known unless the timezone of the system that wrote the file4 is + known. Unix solved this problem (for planet Earth, anyway) by + stamping files with Universal Time (GMT). Microsoft would have to + include the timezone of origin in the directory entries, but does + not. Professional-YAM gets around this problem by using the z + parameter which is set to the number of minutes local time lags GMT. + For files known to originate from a different timezone, the -zT + option may be used to specify T as the timezone for an individual + file transfer. + + + +__________ + + 3. Fields may not be skipped. + + 4. Not necessarily that of the transmitting system! + + + + +Chapter 4 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 11 + + + + The second problem is the lack of a separate file creation date in + DOS. Since some backup schemes used with DOS rely on the file + creation date to select files to be copied to the archive, back- + dating the file modification date could interfere with the safety of + the transferred files. For this reason, Professional-YAM does not + modify the date of received files with the header information unless + the d parameter is non zero. + + +Mode A single space separates the file mode from the modification date. + The file mode is stored as an octal string. Unless the file + originated from a Unix system, the file mode is set to 0. rb(1) + checks the file mode for the 0x8000 bit which indicates a Unix type + regular file. Files with the 0x8000 bit set are assumed to have been + sent from another Unix (or similar) system which uses the same file + conventions. Such files are not translated in any way. + + +Serial Number A single space separates the serial number from the file + mode. The serial number of the transmitting program is stored as an + octal string. Programs which do not have a serial number should omit + this field, or set it to 0. The receiver's use of this field is + optional. + +The rest of the packet is set to nulls. This is essential to preserve +upward compatibility.5 After the filename packet has been received, it is +ACK'ed if the write open is successful. The receiver then initiates +transfer of the file contents according to the standard XMODEM/CRC +protocol. If the file cannot be opened for writing, the receiver cancels +the transfer with CAN characters as described above. + +After the file contents have been transmitted, the receiver again asks for +the next pathname. Transmission of a null pathname terminates batch file +transmission. Note that transmission of no files is not necessarily an +error. This is possible if none of the files requested of the sender +could be opened for reading. + +In batch transmission, the receiver automatically requests CRC-16. + +The Unix programs sb(1) and rb(1) included in the source code file +RBSB.SHQ (rbsb.sh) should answer other questions about YMODEM batch +protocol. + + + +__________ + + 5. If, perchance, this information extends beyond 128 bytes (possible + with Unix 4.2 BSD extended file names), the packet should be sent as a + 1k packet as described above. + + + + +Chapter 4 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 12 + + + + Figure 3. Batch Transmission Session + + SENDER RECEIVER + "sb foo.*" + "sending in batch mode etc." + C (command:rb) + SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C + SOH 01 FE Data[128] CRC CRC + ACK + SOH 02 FD Data[1024] CRC CRC + ACK + SOH 03 FC Data[128] CRC CRC + ACK + SOH 04 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + NAK + EOT + ACK + C + SOH 00 FF NUL[128] CRC CRC + ACK + + Figure 4. Filename packet transmitted by sb + + -rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txt + + 00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.| + 10 36333437 20333331 34373432 35313320 |6347 3314742513 | + 20 31303036 34340000 00000000 00000000 |100644..........| + 30 00000000 00000000 00000000 00000000 + 80 000000CA 56 + + + + + + + + + + + + + + + + + + + + +Chapter 4 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 13 + + + + Figure 5. Header Information used by YMODEM Implementations + + +_____________________________________________________________________ +| Program | Batch | Length | Date | Mode | S/N | 1k-Blk | g-Option | +|___________|_______|________|______|______|_____|________|__________| +|Unix rb/sb | yes | yes | yes | yes | no | yes | sb only | +|___________|_______|________|______|______|_____|________|__________| +|VMS rb/sb | yes | yes | no | no | no | yes | no | +|___________|_______|________|______|______|_____|________|__________| +|Pro-YAM | yes | yes | yes | no | yes | yes | yes | +|___________|_______|________|______|______|_____|________|__________| +|CP/M YAM | yes | no | no | no | no | yes | no | +|___________|_______|________|______|______|_____|________|__________| +|KMD/IMP | yes | no | no | no | no | yes | no | +|___________|_______|________|______|______|_____|________|__________| +|MEX | no | no | no | no | no | yes | no | +|___________|_______|________|______|______|_____|________|__________| + +4.1 IMP/KMD Record Count + +Due to programming constraints, these programs do not send the file length +as described above. Instead, they send (and look for) the CP/M record +count stored in the last two bytes of the header packet. The least +significant bits are stored in the penultimate byte. + +KMD and IMP use the record count to allow the receiving program to display +the file size and estimated transmission time; the file length is +determined by the actual number of records sent. + + +5. g Option File Transmission + +Developing technology is providing phone line data transmission at ever +higher speeds using very specialized techniques. These high speed modems, +as well as session protocols such as X.PC, provide high speed, error free +communications at the expense of considerably increased delay time. + +This delay time is moderate compared to human interactions, but it +cripples the throughput of most error correcting protocols. + +The g option to YMODEM has proven effective under these circumstances. +The g option is driven by the receiver, which initiates the batch transfer +by transmitting a G instead of C. When the sender recognizes the G, it +bypasses the usual wait for an ACK to each transmitted packet, sending +succeeding packets at full speed, subject to XOFF/XON or other flow +control exerted by the medium. + +The sender expects an initial G to initiate the transmission of a +particular file, and also expects an ACK on the EOT sent at the end of +each file. This synchronization allows the receiver time to open and + + + +Chapter 5 XMODEM Protocol Enhancements + + + + + + + +X/YMODEM Protocol Reference 10-10-85 14 + + + +close files as necessary. + + + Figure 6. g Option Transmission Session + + SENDER RECEIVER + "sb foo.*" + "sending in batch mode etc..." + G (command:rb -g) + SOH 00 FF foo.c NUL[123] CRC CRC + G + SOH 01 FE Data[128] CRC CRC + SOH 02 FD Data[1024] CRC CRC + SOH 03 FC Data[128] CRC CRC + SOH 04 FB Data[100] CPMEOF[28] CRC CRC + EOT + ACK + G + SOH 00 FF NUL[128] CRC CRC + + +6. XMODEM PROTOCOL OVERVIEW + +8/9/82 by Ward Christensen. + +I will maintain a master copy of this. Please pass on changes or +suggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132 +or by voice at (312) 849-6279. + +6.1 Definitions + + 01H + 04H + 06H + 15H + 18H + 43H + + +6.2 Transmission Medium Level Protocol + +Asynchronous, 8 data bits, no parity, one stop bit. + +The protocol imposes no restrictions on the contents of the data being +transmitted. No control characters are looked for in the 128-byte data +messages. Absolutely any kind of data may be sent - binary, ASCII, etc. +The protocol has not formally been adopted to a 7-bit environment for the +transmission of ASCII-only (or unpacked-hex) data , although it could be +simply by having both ends agree to AND the protocol-dependent data with +7F hex before validating it. I specifically am referring to the checksum, +and the block numbers and their ones- complement. + + + +Chapter 6 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 15 + + + +Those wishing to maintain compatibility of the CP/M file structure, i.e. +to allow modemming ASCII files to or from CP/M systems should follow this +data format: + + + ASCII tabs used (09H); tabs set every 8. + + + Lines terminated by CR/LF (0DH 0AH) + + + End-of-file indicated by ^Z, 1AH. (one or more) + + + Data is variable length, i.e. should be considered a continuous + stream of data bytes, broken into 128-byte chunks purely for the + purpose of transmission. + + + A CP/M "peculiarity": If the data ends exactly on a 128-byte + boundary, i.e. CR in 127, and LF in 128, a subsequent sector + containing the ^Z EOF character(s) is optional, but is preferred. + Some utilities or user programs still do not handle EOF without ^Zs. + + + The last block sent is no different from others, i.e. there is no + "short block". + Figure 7. XMODEM Message Block Level Protocol + +Each block of the transfer looks like: + <255-blk #><--128 data bytes--> +in which: + = 01 hex + = binary number, starts at 01 increments by 1, and + wraps 0FFH to 00H (not to 01) +<255-blk #> = blk # after going thru 8080 "CMA" instr, i.e. + each bit complemented in the 8-bit block number. + Formally, this is the "ones complement". + = the sum of the data bytes only. Toss any carry. + +6.3 File Level Protocol + +6.3.1 Common_to_Both_Sender_and_Receiver +All errors are retried 10 times. For versions running with an operator +(i.e. NOT with XMODEM), a message is typed after 10 errors asking the +operator whether to "retry or quit". + +Some versions of the protocol use , ASCII ^X, to cancel transmission. +This was never adopted as a standard, as having a single "abort" character +makes the transmission susceptible to false termination due to an + or being corrupted into a and cancelling transmission. + +The protocol may be considered "receiver driven", that is, the sender need +not automatically re-transmit, although it does in the current +implementations. + + + + + +Chapter 6 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 16 + + + +6.3.2 Receive_Program_Considerations +The receiver has a 10-second timeout. It sends a every time it +times out. The receiver's first timeout, which sends a , signals the +transmitter to start. Optionally, the receiver could send a +immediately, in case the sender was ready. This would save the initial 10 +second timeout. However, the receiver MUST continue to timeout every 10 +seconds in case the sender wasn't ready. + +Once into a receiving a block, the receiver goes into a one-second timeout +for each character and the checksum. If the receiver wishes to a +block for any reason (invalid header, timeout receiving data), it must +wait for the line to clear. See "programming tips" for ideas + +Synchronizing: If a valid block number is received, it will be: 1) the +expected one, in which case everything is fine; or 2) a repeat of the +previously received block. This should be considered OK, and only +indicates that the receivers got glitched, and the sender re- +transmitted; 3) any other block number indicates a fatal loss of +synchronization, such as the rare case of the sender getting a line-glitch +that looked like an . Abort the transmission, sending a + + +6.3.3 Sending_program_considerations +While waiting for transmission to begin, the sender has only a single very +long timeout, say one minute. In the current protocol, the sender has a +10 second timeout before retrying. I suggest NOT doing this, and letting +the protocol be completely receiver-driven. This will be compatible with +existing programs. + +When the sender has no more data, it sends an , and awaits an , +resending the if it doesn't get one. Again, the protocol could be +receiver-driven, with the sender only having the high-level 1-minute +timeout to abort. + + +Here is a sample of the data flow, sending a 3-block message. It includes +the two most common line hits - a garbaged block, and an reply +getting garbaged. represents the checksum byte. + + + + + + + + + + + + + + + + +Chapter 6 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 17 + + + + Figure 8. Data flow including Error Recovery + +SENDER RECEIVER + times out after 10 seconds, + <--- + 01 FE -data- ---> + <--- + 02 FD -data- xx ---> (data gets line hit) + <--- + 02 FD -data- xx ---> + <--- + 03 FC -data- xx ---> +(ack gets garbaged) <--- + 03 FC -data- xx ---> + ---> + <--- + ---> + <--- +(finished) + +6.4 Programming Tips + + + The character-receive subroutine should be called with a parameter + specifying the number of seconds to wait. The receiver should first + call it with a time of 10, then and try again, 10 times. + + After receiving the , the receiver should call the character + receive subroutine with a 1-second timeout, for the remainder of the + message and the . Since they are sent as a continuous stream, + timing out of this implies a serious like glitch that caused, say, + 127 characters to be seen instead of 128. + + + When the receiver wishes to , it should call a "PURGE" + subroutine, to wait for the line to clear. Recall the sender tosses + any characters in its UART buffer immediately upon completing sending + a block, to ensure no glitches were mis- interpreted. + + The most common technique is for "PURGE" to call the character + receive subroutine, specifying a 1-second timeout,1 and looping back + to PURGE until a timeout occurs. The is then sent, ensuring + the other end will see it. + + + You may wish to add code recommended by John Mahr to your character + receive routine - to set an error flag if the UART shows framing + error, or overrun. This will help catch a few more glitches - the + + +__________ + + 1. These times should be adjusted for use with timesharing systems. + + + + +Chapter 6 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 18 + + + + most common of which is a hit in the high bits of the byte in two + consecutive bytes. The comes out OK since counting in 1-byte + produces the same result of adding 80H + 80H as with adding 00H + + 00H. + + + +7. XMODEM/CRC Overview + +1/13/85 by John Byrns -- CRC option. + +Please pass on any reports of errors in this document or suggestions for +improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312) +885-1105. + +The CRC used in the Modem Protocol is an alternate form of block check +which provides more robust error detection than the original checksum. +Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC- +CCITT used by the Modem Protocol will detect all single and double bit +errors, all errors with an odd number of bits, all burst errors of length +16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and +longer bursts. + +The changes to the Modem Protocol to replace the checksum with the CRC are +straight forward. If that were all that we did we would not be able to +communicate between a program using the old checksum protocol and one +using the new CRC protocol. An initial handshake was added to solve this +problem. The handshake allows a receiving program with CRC capability to +determine whether the sending program supports the CRC option, and to +switch it to CRC mode if it does. This handshake is designed so that it +will work properly with programs which implement only the original +protocol. A description of this handshake is presented in section 10. + + Figure 9. Message Block Level Protocol, CRC mode + +Each block of the transfer in CRC mode looks like: + <255-blk #><--128 data bytes--> +in which: + = 01 hex + = binary number, starts at 01 increments by 1, and + wraps 0FFH to 00H (not to 01) +<255-blk #> = ones complement of blk #. + = byte containing the 8 hi order coefficients of the CRC. + = byte containing the 8 lo order coefficients of the CRC. + +7.1 CRC Calculation + +7.1.1 Formal_Definition +To calculate the 16 bit CRC the message bits are considered to be the +coefficients of a polynomial. This message polynomial is first multiplied +by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 + + + + +Chapter 7 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 19 + + + +1) using modulo two arithmetic. The remainder left after the division is +the desired CRC. Since a message block in the Modem Protocol is 128 bytes +or 1024 bits, the message polynomial will be of order X^1023. The hi order +bit of the first byte of the message block is the coefficient of X^1023 in +the message polynomial. The lo order bit of the last byte of the message +block is the coefficient of X^0 in the message polynomial. + + Figure 10. Example of CRC Calculation written in C + +/* + * This function calculates the CRC used by the XMODEM/CRC Protocol + * The first argument is a pointer to the message block. + * The second argument is the number of bytes in the message block. + * The function returns an integer which contains the CRC. + * The low order 16 bits are the coefficients of the CRC. + */ +int calcrc(ptr, count) +char *ptr; +int count; +{ + int crc, i; + + crc = 0; + while (--count >= 0) { + crc = crc ^ (int)*ptr++ << 8; + for (i = 0; i < 8; ++i) + if (crc & 0x8000) + crc = crc << 1 ^ 0x1021; + else + crc = crc << 1; + } + return (crc & 0xFFFF); +} + +7.2 CRC File Level Protocol Changes + +7.2.1 Common_to_Both_Sender_and_Receiver +The only change to the File Level Protocol for the CRC option is the +initial handshake which is used to determine if both the sending and the +receiving programs support the CRC mode. All Modem Programs should support +the checksum mode for compatibility with older versions. A receiving +program that wishes to receive in CRC mode implements the mode setting +handshake by sending a in place of the initial . If the sending +program supports CRC mode it will recognize the and will set itself +into CRC mode, and respond by sending the first block as if a had +been received. If the sending program does not support CRC mode it will +not respond to the at all. After the receiver has sent the it will +wait up to 3 seconds for the that starts the first block. If it +receives a within 3 seconds it will assume the sender supports CRC +mode and will proceed with the file exchange in CRC mode. If no is +received within 3 seconds the receiver will switch to checksum mode, send + + + +Chapter 7 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 20 + + + +a , and proceed in checksum mode. If the receiver wishes to use +checksum mode it should send an initial and the sending program +should respond to the as defined in the original Modem Protocol. +After the mode has been set by the initial or the protocol +follows the original Modem Protocol and is identical whether the checksum +or CRC is being used. + + +7.2.2 Receive_Program_Considerations +There are at least 4 things that can go wrong with the mode setting +handshake. + + 1. the initial can be garbled or lost. + + 2. the initial can be garbled. + + 3. the initial can be changed to a . + + 4. the initial from a receiver which wants to receive in checksum + can be changed to a . + +The first problem can be solved if the receiver sends a second after +it times out the first time. This process can be repeated several times. +It must not be repeated too many times before sending a and +switching to checksum mode or a sending program without CRC support may +time out and abort. Repeating the will also fix the second problem if +the sending program cooperates by responding as if a were received +instead of ignoring the extra . + +It is possible to fix problems 3 and 4 but probably not worth the trouble +since they will occur very infrequently. They could be fixed by switching +modes in either the sending or the receiving program after a large number +of successive s. This solution would risk other problems however. + + +7.2.3 Sending_Program_Considerations +The sending program should start in the checksum mode. This will insure +compatibility with checksum only receiving programs. Anytime a is +received before the first or the sending program should set +itself into CRC mode and respond as if a were received. The sender +should respond to additional s as if they were s until the first + is received. This will assist the receiving program in determining +the correct mode when the is lost or garbled. After the first +is received the sending program should ignore s. + + + + + + + + + + +Chapter 7 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 21 + + + +7.3 Data Flow Examples with CRC Option + +Here is a data flow example for the case where the receiver requests +transmission in the CRC mode but the sender does not support the CRC +option. This example also includes various transmission errors. +represents the checksum byte. + + Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn't + +SENDER RECEIVER + <--- + times out after 3 seconds, + <--- + times out after 3 seconds, + <--- + times out after 3 seconds, + <--- + times out after 3 seconds, + <--- + 01 FE -data- ---> + <--- + 02 FD -data- ---> (data gets line hit) + <--- + 02 FD -data- ---> + <--- + 03 FC -data- ---> + (ack gets garbaged) <--- + times out after 10 seconds, + <--- + 03 FC -data- ---> + <--- + ---> + <--- + +Here is a data flow example for the case where the receiver requests +transmission in the CRC mode and the sender supports the CRC option. This +example also includes various transmission errors. represents the +2 CRC bytes. + + + + + + + + + + + + + + + + +Chapter 7 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 22 + + + + Figure 12. Receiver and Sender Both have CRC Option + +SENDER RECEIVER + <--- + 01 FE -data- ---> + <--- + 02 FD -data- ---> (data gets line hit) + <--- + 02 FD -data- ---> + <--- + 03 FC -data- ---> +(ack gets garbaged) <--- + times out after 10 seconds, + <--- + 03 FC -data- ---> + <--- + ---> + <--- + + +8. MORE INFORMATION + +More information may be obtained by calling Telegodzilla at 503-621-3746. +Hit RETURNs for baud rate detection. + +A version this file with boldface, underlining, and superscripts for +printing on Epson or Gemini printers is available on Telegodzilla as +"YMODEME.DOC" or "YMODEME.DQC". + +UUCP sites can obtain this file with + uucp omen!/usr/spool/uucppublic/ymodem.doc /tmp + +The following L.sys line calls Telegodzilla (Pro-YAM in host operation). +Telegodzilla waits for carriage returns to determine the incoming speed. +If none is detected, 1200 bps is assumed and a greeting is displayed. + +In response to "Name Please:" uucico gives the Pro-YAM "link" command as a +user name. The password (Giznoid) controls access to the Xenix system +connected to the IBM PC's other serial port. Communications between +Pro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed. + +Finally, the calling uucico logs in as uucp. + +omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp + +Contact omen!caf if you wish the troff sources. + + + + + + + + +Chapter 9 Xmodem Protocol Overview + + + + + + + +X/YMODEM Protocol Reference 10-10-85 23 + + + +9. YMODEM Programs + +A demonstration version of Professional-YAM is available as YAMDEMO.LQR (A +SQueezed Novosielski library). This may be used to test YMODEM +implementations. + +Unix programs supporting the YMODEM protocol are available on Telegodzilla +in the "upgrade" subdirectory as RBSB.SHQ (a SQueezed shell archive). +Most Unix like systems are supported, including V7, Sys III, 4.2 BSD, SYS +V, Idris, Coherent, and Regulus. + +A version for VAX-VMS is available in VRBSB.SHQ, in the same directory. + +A CP/M assembly version is available as MODEM76.AQM and MODEM7.LIB. + +Irv Hoff has added YMODEM 1k packets and YMODEM batch transfers to the KMD +and IMP series programs, which replace the XMODEM and MODEM7/MDM7xx series +respectively. Overlays are available for a wide variety of CP/M systems. + +MEX and MEX-PC also support some of the YMODEM extensions. + +Questions about YMODEM, the Professional-YAM communications program, and +requests for evaluation copies may be directed to: + Chuck Forsberg + Omen Technology Inc + 17505-V Sauvie Island Road + Portland Oregon 97231 + Voice: 503-621-3406 + Modem: 503-621-3746 Speed: 1200,300 + Usenet: ...!tektronix!reed!omen!caf + Compuserve: 70715,131 + Source: TCE022 + + + + + + + + + + + + + + + + + + + + + + +Chapter 9 Xmodem Protocol Overview + + + + + + + + + + + + CONTENTS + + +1. ROSETTA STONE..................................................... 2 + +2. YET ANOTHER PROTOCOL?............................................. 2 + 2.1 Some Messages from the Pioneer............................... 4 + +3. XMODEM PROTOCOL ENHANCEMENTS...................................... 5 + 3.1 Graceful Abort............................................... 6 + 3.2 CRC-16 Option................................................ 6 + 3.3 1024 Byte Packet Option...................................... 7 + +4. YMODEM Batch File Transmission.................................... 8 + 4.1 IMP/KMD Record Count......................................... 13 + +5. g Option File Transmission........................................ 13 + +6. XMODEM PROTOCOL OVERVIEW.......................................... 14 + 6.1 Definitions.................................................. 14 + 6.2 Transmission Medium Level Protocol........................... 14 + 6.3 File Level Protocol.......................................... 15 + 6.4 Programming Tips............................................. 17 + +7. XMODEM/CRC Overview............................................... 18 + 7.1 CRC Calculation.............................................. 18 + 7.2 CRC File Level Protocol Changes.............................. 19 + 7.3 Data Flow Examples with CRC Option........................... 21 + +8. MORE INFORMATION.................................................. 22 + +9. YMODEM Programs................................................... 23 + + + + + + + + + + + + + + + + + + + + + + + - i - + + + + + + + + + + + + + + + LIST OF FIGURES + + + Figure 1. 1024 byte Packets......................................... 7 + + Figure 2. Mixed 1024 and 128 byte Packets........................... 7 + + Figure 3. Batch Transmission Session................................ 11 + + Figure 4. Filename packet transmitted by sb......................... 11 + + Figure 5. Header Information used by YMODEM Implementations......... 13 + + Figure 6. g Option Transmission Session............................. 14 + + Figure 7. XMODEM Message Block Level Protocol....................... 15 + + Figure 8. Data flow including Error Recovery........................ 17 + + Figure 9. Message Block Level Protocol, CRC mode.................... 18 + +Figure 10. Example of CRC Calculation written in C................... 19 + +Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn't........ 21 + +Figure 12. Receiver and Sender Both have CRC Option.................. 22 + + + + + + + + + + + + + + + + + + + + + + + + + + - ii - + + + + diff --git a/emulog.log b/emulog.log new file mode 100644 index 0000000000..bdc93c76d0 --- /dev/null +++ b/emulog.log @@ -0,0 +1,1378 @@ +c[?7lSeaBIOS (version rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org) + + +iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+7EFD0D70+7EF30D70 CA00 +Press Ctrl-B to configure iPXE (PCI 00:03.0)... + + + +Booting from ROM..c[?7l[ 0.000000] Linux version 6.10.0 (dbydd@dbyddlaptop) (gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #12 SMP PREEMPT_DYNAMIC Wed Aug 7 13:21:41 HKT 2024 +[ 0.000000] Command line: root=/dev/root ro rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/bin/sh +[ 0.000000] BIOS-provided physical RAM map: +[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable +[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved +[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000007ffdffff] usable +[ 0.000000] BIOS-e820: [mem 0x000000007ffe0000-0x000000007fffffff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved +[ 0.000000] BIOS-e820: [mem 0x000000fd00000000-0x000000ffffffffff] reserved +[ 0.000000] NX (Execute Disable) protection: active +[ 0.000000] APIC: Static calls initialized +[ 0.000000] SMBIOS 2.8 present. +[ 0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 +[ 0.000000] DMI: Memory slots populated: 1/1 +[ 0.000000] tsc: Fast TSC calibration using PIT +[ 0.000000] tsc: Detected 2419.199 MHz processor +[ 0.009100] last_pfn = 0x7ffe0 max_arch_pfn = 0x400000000 +[ 0.010004] MTRR map: 4 entries (3 fixed + 1 variable; max 19), built from 8 variable MTRRs +[ 0.010201] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT +[ 0.025873] found SMP MP-table at [mem 0x000f5460-0x000f546f] +[ 0.031234] ACPI: Early table checksum verification disabled +[ 0.031546] ACPI: RSDP 0x00000000000F5280 000014 (v00 BOCHS ) +[ 0.031804] ACPI: RSDT 0x000000007FFE1CBA 000034 (v01 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.032302] ACPI: FACP 0x000000007FFE1B6E 000074 (v01 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.032913] ACPI: DSDT 0x000000007FFE0040 001B2E (v01 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.032995] ACPI: FACS 0x000000007FFE0000 000040 +[ 0.033040] ACPI: APIC 0x000000007FFE1BE2 000078 (v03 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.033057] ACPI: HPET 0x000000007FFE1C5A 000038 (v01 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.033072] ACPI: WAET 0x000000007FFE1C92 000028 (v01 BOCHS BXPC 00000001 BXPC 00000001) +[ 0.033142] ACPI: Reserving FACP table memory at [mem 0x7ffe1b6e-0x7ffe1be1] +[ 0.033187] ACPI: Reserving DSDT table memory at [mem 0x7ffe0040-0x7ffe1b6d] +[ 0.033194] ACPI: Reserving FACS table memory at [mem 0x7ffe0000-0x7ffe003f] +[ 0.033198] ACPI: Reserving APIC table memory at [mem 0x7ffe1be2-0x7ffe1c59] +[ 0.033203] ACPI: Reserving HPET table memory at [mem 0x7ffe1c5a-0x7ffe1c91] +[ 0.033207] ACPI: Reserving WAET table memory at [mem 0x7ffe1c92-0x7ffe1cb9] +[ 0.035626] No NUMA configuration found +[ 0.035647] Faking a node at [mem 0x0000000000000000-0x000000007ffdffff] +[ 0.036270] NODE_DATA(0) allocated [mem 0x7ffdc000-0x7ffdffff] +[ 0.038142] Zone ranges: +[ 0.038170] DMA [mem 0x0000000000001000-0x0000000000ffffff] +[ 0.038245] DMA32 [mem 0x0000000001000000-0x000000007ffdffff] +[ 0.038253] Normal empty +[ 0.038274] Movable zone start for each node +[ 0.038298] Early memory node ranges +[ 0.038338] node 0: [mem 0x0000000000001000-0x000000000009efff] +[ 0.038620] node 0: [mem 0x0000000000100000-0x000000007ffdffff] +[ 0.038815] Initmem setup node 0 [mem 0x0000000000001000-0x000000007ffdffff] +[ 0.039848] On node 0, zone DMA: 1 pages in unavailable ranges +[ 0.040020] On node 0, zone DMA: 97 pages in unavailable ranges +[ 0.062216] On node 0, zone DMA32: 32 pages in unavailable ranges +[ 0.062738] ACPI: PM-Timer IO Port: 0x608 +[ 0.063095] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1]) +[ 0.063676] IOAPIC[0]: apic_id 0, version 32, address 0xfec00000, GSI 0-23 +[ 0.063823] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl) +[ 0.064039] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level) +[ 0.064087] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level) +[ 0.064161] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level) +[ 0.064167] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level) +[ 0.064329] ACPI: Using ACPI (MADT) for SMP configuration information +[ 0.064360] ACPI: HPET id: 0x8086a201 base: 0xfed00000 +[ 0.064647] CPU topo: Max. logical packages: 1 +[ 0.064656] CPU topo: Max. logical dies: 1 +[ 0.064663] CPU topo: Max. dies per package: 1 +[ 0.064695] CPU topo: Max. threads per core: 1 +[ 0.064817] CPU topo: Num. cores per package: 1 +[ 0.064827] CPU topo: Num. threads per package: 1 +[ 0.064833] CPU topo: Allowing 1 present CPUs plus 0 hotplug CPUs +[ 0.065403] PM: hibernation: Registered nosave memory: [mem 0x00000000-0x00000fff] +[ 0.065435] PM: hibernation: Registered nosave memory: [mem 0x0009f000-0x0009ffff] +[ 0.065458] PM: hibernation: Registered nosave memory: [mem 0x000a0000-0x000effff] +[ 0.065463] PM: hibernation: Registered nosave memory: [mem 0x000f0000-0x000fffff] +[ 0.065596] [mem 0x80000000-0xfffbffff] available for PCI devices +[ 0.065648] Booting paravirtualized kernel on bare hardware +[ 0.065934] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1910969940391419 ns +[ 0.076895] setup_percpu: NR_CPUS:64 nr_cpumask_bits:1 nr_cpu_ids:1 nr_node_ids:1 +[ 0.078199] percpu: Embedded 58 pages/cpu s199384 r8192 d29992 u2097152 +[ 0.080398] Kernel command line: root=/dev/root ro rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/bin/sh +[ 0.081948] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear) +[ 0.082282] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear) +[ 0.085012] Fallback order for Node 0: 0 +[ 0.085490] Built 1 zonelists, mobility grouping on. Total pages: 524158 +[ 0.085512] Policy zone: DMA32 +[ 0.085796] mem auto-init: stack:off, heap alloc:off, heap free:off +[ 0.095947] Memory: 2016528K/2096632K available (20480K kernel code, 3086K rwdata, 7736K rodata, 2848K init, 2504K bss, 79844K reserved, 0K cma-reserved) +[ 0.099922] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 +[ 0.111380] Dynamic Preempt: voluntary +[ 0.115219] rcu: Preemptible hierarchical RCU implementation. +[ 0.115236] rcu: RCU event tracing is enabled. +[ 0.115259] rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1. +[ 0.115387] Trampoline variant of Tasks RCU enabled. +[ 0.115394] Tracing variant of Tasks RCU enabled. +[ 0.115471] rcu: RCU calculated value of scheduler-enlistment delay is 100 jiffies. +[ 0.115493] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 +[ 0.116376] RCU Tasks: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1. +[ 0.116405] RCU Tasks Trace: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1. +[ 0.128660] NR_IRQS: 4352, nr_irqs: 256, preallocated irqs: 16 +[ 0.137198] rcu: srcu_init: Setting srcu_struct sizes based on contention. +[ 0.142213] Console: colour VGA+ 80x25 +[ 0.143560] printk: legacy console [ttyS0] enabled +[ 0.151829] ACPI: Core revision 20240322 +[ 0.157580] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns +[ 0.164094] APIC: Switch to symmetric I/O mode setup +[ 0.168317] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 +[ 0.173568] clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x22df101993e, max_idle_ns: 440795226575 ns +[ 0.174072] Calibrating delay loop (skipped), value calculated using timer frequency.. 4838.39 BogoMIPS (lpj=2419199) +[ 0.177904] Last level iTLB entries: 4KB 512, 2MB 255, 4MB 127 +[ 0.178024] Last level dTLB entries: 4KB 512, 2MB 255, 4MB 127, 1GB 0 +[ 0.178497] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization +[ 0.178737] Spectre V2 : Mitigation: Retpolines +[ 0.178817] Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch +[ 0.178846] Spectre V2 : Spectre v2 / SpectreRSB : Filling RSB on VMEXIT +[ 0.182139] x86/fpu: x87 FPU will use FXSAVE +[ 0.488580] Freeing SMP alternatives memory: 52K +[ 0.489217] pid_max: default: 32768 minimum: 301 +[ 0.493452] LSM: initializing lsm=capability,selinux,bpf +[ 0.494138] SELinux: Initializing. +[ 0.494917] LSM support for eBPF active +[ 0.500305] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes, linear) +[ 0.500623] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes, linear) +[ 0.630817] smpboot: CPU0: AMD QEMU Virtual CPU version 2.5+ (family: 0xf, model: 0x6b, stepping: 0x1) +[ 0.639759] Performance Events: PMU not available due to virtualization, using software events only. +[ 0.640508] signal: max sigframe size: 1440 +[ 0.641401] rcu: Hierarchical SRCU implementation. +[ 0.641507] rcu: Max phase no-delay instances is 400. +[ 0.649706] smp: Bringing up secondary CPUs ... +[ 0.652389] smp: Brought up 1 node, 1 CPU +[ 0.652746] smpboot: Total of 1 processors activated (4838.39 BogoMIPS) +[ 0.668296] devtmpfs: initialized +[ 0.680128] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns +[ 0.680659] futex hash table entries: 256 (order: 2, 16384 bytes, linear) +[ 0.685958] PM: RTC time: 05:30:27, date: 2024-08-07 +[ 0.696589] NET: Registered PF_NETLINK/PF_ROUTE protocol family +[ 0.699817] audit: initializing netlink subsys (disabled) +[ 0.703242] audit: type=2000 audit(1723008626.539:1): state=initialized audit_enabled=0 res=1 +[ 0.706817] thermal_sys: Registered thermal governor 'step_wise' +[ 0.706817] thermal_sys: Registered thermal governor 'user_space' +[ 0.707910] cpuidle: using governor menu +[ 0.711378] PCI: Using configuration type 1 for base access +[ 0.713262] kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible. +[ 0.721305] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages +[ 0.721396] HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page +[ 0.723971] Demotion targets for Node 0: null +[ 0.730833] ACPI: Added _OSI(Module Device) +[ 0.733041] ACPI: Added _OSI(Processor Device) +[ 0.733153] ACPI: Added _OSI(3.0 _SCP Extensions) +[ 0.733210] ACPI: Added _OSI(Processor Aggregator Device) +[ 0.753825] ACPI: 1 ACPI AML tables successfully acquired and loaded +[ 0.785682] ACPI: Interpreter enabled +[ 0.789207] ACPI: PM: (supports S0 S3 S4 S5) +[ 0.789284] ACPI: Using IOAPIC for interrupt routing +[ 0.789607] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug +[ 0.789708] PCI: Using E820 reservations for host bridge windows +[ 0.790917] ACPI: Enabled 2 GPEs in block 00 to 0F +[ 0.843538] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff]) +[ 0.844261] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI HPX-Type3] +[ 0.844495] acpi PNP0A03:00: _OSC: not requesting OS control; OS requires [ExtendedConfig ASPM ClockPM MSI] +[ 0.845364] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended configuration space under this bridge +[ 0.848980] PCI host bridge to bus 0000:00 +[ 0.849178] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window] +[ 0.849557] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window] +[ 0.849642] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window] +[ 0.851635] pci_bus 0000:00: root bus resource [mem 0x80000000-0xfebfffff window] +[ 0.851703] pci_bus 0000:00: root bus resource [mem 0x100000000-0x17fffffff window] +[ 0.851901] pci_bus 0000:00: root bus resource [bus 00-ff] +[ 0.864987] pci 0000:00:00.0: [8086:1237] type 00 class 0x060000 conventional PCI endpoint +[ 0.869317] pci 0000:00:01.0: [8086:7000] type 00 class 0x060100 conventional PCI endpoint +[ 0.869974] pci 0000:00:01.1: [8086:7010] type 00 class 0x010180 conventional PCI endpoint +[ 0.871885] pci 0000:00:01.1: BAR 4 [io 0xc0a0-0xc0af] +[ 0.872607] pci 0000:00:01.1: BAR 0 [io 0x01f0-0x01f7]: legacy IDE quirk +[ 0.872693] pci 0000:00:01.1: BAR 1 [io 0x03f6]: legacy IDE quirk +[ 0.872770] pci 0000:00:01.1: BAR 2 [io 0x0170-0x0177]: legacy IDE quirk +[ 0.872817] pci 0000:00:01.1: BAR 3 [io 0x0376]: legacy IDE quirk +[ 0.873301] pci 0000:00:01.2: [8086:7020] type 00 class 0x0c0300 conventional PCI endpoint +[ 0.874837] pci 0000:00:01.2: BAR 4 [io 0xc080-0xc09f] +[ 0.886711] pci 0000:00:01.3: [8086:7113] type 00 class 0x068000 conventional PCI endpoint +[ 0.887189] pci 0000:00:01.3: quirk: [io 0x0600-0x063f] claimed by PIIX4 ACPI +[ 0.887342] pci 0000:00:01.3: quirk: [io 0x0700-0x070f] claimed by PIIX4 SMB +[ 0.888327] pci 0000:00:02.0: [1234:1111] type 00 class 0x030000 conventional PCI endpoint +[ 0.888836] pci 0000:00:02.0: BAR 0 [mem 0xfd000000-0xfdffffff pref] +[ 0.889838] pci 0000:00:02.0: BAR 2 [mem 0xfebf4000-0xfebf4fff] +[ 0.892380] pci 0000:00:02.0: ROM [mem 0xfebe0000-0xfebeffff pref] +[ 0.899750] pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff] +[ 0.900284] pci 0000:00:03.0: [8086:100e] type 00 class 0x020000 conventional PCI endpoint +[ 0.900817] pci 0000:00:03.0: BAR 0 [mem 0xfebc0000-0xfebdffff] +[ 0.901106] pci 0000:00:03.0: BAR 1 [io 0xc000-0xc03f] +[ 0.905134] pci 0000:00:03.0: ROM [mem 0xfeb80000-0xfebbffff pref] +[ 0.921930] pci 0000:00:04.0: [1b36:000d] type 00 class 0x0c0330 conventional PCI endpoint +[ 0.922594] pci 0000:00:04.0: BAR 0 [mem 0xfebf0000-0xfebf3fff 64bit] +[ 0.937045] pci 0000:00:05.0: [1af4:1009] type 00 class 0x000200 conventional PCI endpoint +[ 0.937854] pci 0000:00:05.0: BAR 0 [io 0xc040-0xc07f] +[ 0.939750] pci 0000:00:05.0: BAR 1 [mem 0xfebf5000-0xfebf5fff] +[ 0.941842] pci 0000:00:05.0: BAR 4 [mem 0xfe000000-0xfe003fff 64bit pref] +[ 0.957656] ACPI: PCI: Interrupt link LNKA configured for IRQ 10 +[ 0.958538] ACPI: PCI: Interrupt link LNKB configured for IRQ 10 +[ 0.967040] ACPI: PCI: Interrupt link LNKC configured for IRQ 11 +[ 0.967388] ACPI: PCI: Interrupt link LNKD configured for IRQ 11 +[ 0.967591] ACPI: PCI: Interrupt link LNKS configured for IRQ 9 +[ 0.970399] iommu: Default domain type: Translated +[ 0.970512] iommu: DMA domain TLB invalidation policy: lazy mode +[ 0.971460] SCSI subsystem initialized +[ 0.973135] ACPI: bus type USB registered +[ 0.973488] usbcore: registered new interface driver usbfs +[ 0.973879] usbcore: registered new interface driver hub +[ 0.974082] usbcore: registered new device driver usb +[ 0.974436] mc: Linux media interface: v0.10 +[ 0.974661] videodev: Linux video capture interface: v2.00 +[ 0.983303] pps_core: LinuxPPS API ver. 1 registered +[ 0.983497] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti +[ 0.983751] PTP clock support registered +[ 0.987216] Advanced Linux Sound Architecture Driver Initialized. +[ 1.010435] NetLabel: Initializing +[ 1.010529] NetLabel: domain hash size = 128 +[ 1.010607] NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO +[ 1.011558] NetLabel: unlabeled traffic allowed by default +[ 1.025272] PCI: Using ACPI for IRQ routing +[ 1.027817] pci 0000:00:02.0: vgaarb: setting as boot VGA device +[ 1.027817] pci 0000:00:02.0: vgaarb: bridge control possible +[ 1.027817] pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none +[ 1.027882] vgaarb: loaded +[ 1.029971] hpet: 3 channels of 0 reserved for per-cpu timers +[ 1.030306] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 +[ 1.030476] hpet0: 3 comparators, 64-bit 100.000000 MHz counter +[ 1.042745] clocksource: Switched to clocksource tsc-early +[ 1.045643] VFS: Disk quotas dquot_6.6.0 +[ 1.045811] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) +[ 1.048178] pnp: PnP ACPI init +[ 1.058503] pnp: PnP ACPI: found 6 devices +[ 1.093041] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns +[ 1.103488] NET: Registered PF_INET protocol family +[ 1.106403] IP idents hash table entries: 32768 (order: 6, 262144 bytes, linear) +[ 1.118035] tcp_listen_portaddr_hash hash table entries: 1024 (order: 2, 16384 bytes, linear) +[ 1.118232] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear) +[ 1.118365] TCP established hash table entries: 16384 (order: 5, 131072 bytes, linear) +[ 1.118656] TCP bind hash table entries: 16384 (order: 7, 524288 bytes, linear) +[ 1.118972] TCP: Hash tables configured (established 16384 bind 16384) +[ 1.119700] UDP hash table entries: 1024 (order: 3, 32768 bytes, linear) +[ 1.119933] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes, linear) +[ 1.121083] NET: Registered PF_UNIX/PF_LOCAL protocol family +[ 1.128776] RPC: Registered named UNIX socket transport module. +[ 1.128886] RPC: Registered udp transport module. +[ 1.128925] RPC: Registered tcp transport module. +[ 1.128962] RPC: Registered tcp-with-tls transport module. +[ 1.129007] RPC: Registered tcp NFSv4.1 backchannel transport module. +[ 1.131880] pci_bus 0000:00: resource 4 [io 0x0000-0x0cf7 window] +[ 1.132033] pci_bus 0000:00: resource 5 [io 0x0d00-0xffff window] +[ 1.132142] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window] +[ 1.132375] pci_bus 0000:00: resource 7 [mem 0x80000000-0xfebfffff window] +[ 1.132479] pci_bus 0000:00: resource 8 [mem 0x100000000-0x17fffffff window] +[ 1.140318] pci 0000:00:01.0: PIIX3: Enabling Passive Release +[ 1.140464] pci 0000:00:00.0: Limiting direct PCI/PCI transfers +[ 1.303727] ACPI: \_SB_.LNKD: Enabled at IRQ 11 +[ 1.477672] pci 0000:00:01.2: quirk_usb_early_handoff+0x0/0x7a0 took 329158 usecs +[ 1.714578] pci 0000:00:04.0: quirk_usb_early_handoff+0x0/0x7a0 took 230809 usecs +[ 1.714833] PCI: CLS 0 bytes, default 64 +[ 1.723629] Initialise system trusted keyrings +[ 1.725054] workingset: timestamp_bits=56 max_order=19 bucket_order=0 +[ 1.727850] NFS: Registering the id_resolver key type +[ 1.728238] Key type id_resolver registered +[ 1.728369] Key type id_legacy registered +[ 1.729092] 9p: Installing v9fs 9p2000 file system support +[ 1.784247] Key type asymmetric registered +[ 1.784695] Asymmetric key parser 'x509' registered +[ 1.785116] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 250) +[ 1.785625] io scheduler mq-deadline registered +[ 1.785716] io scheduler kyber registered +[ 1.788585] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 +[ 1.792222] ACPI: button: Power Button [PWRF] +[ 1.879543] ACPI: \_SB_.LNKA: Enabled at IRQ 10 +[ 1.882662] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled +[ 1.885927] 00:04: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A +[ 1.890700] Non-volatile memory driver v1.3 +[ 1.890990] Linux agpgart interface v0.103 +[ 1.893481] ACPI: bus type drm_connector registered +[ 1.912029] loop: module loaded +[ 1.919454] scsi host0: ata_piix +[ 1.921002] scsi host1: ata_piix +[ 1.921441] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc0a0 irq 14 lpm-pol 0 +[ 1.921612] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc0a8 irq 15 lpm-pol 0 +[ 1.928576] e100: Intel(R) PRO/100 Network Driver +[ 1.928666] e100: Copyright(c) 1999-2006 Intel Corporation +[ 1.928787] e1000: Intel(R) PRO/1000 Network Driver +[ 1.928843] e1000: Copyright (c) 1999-2006 Intel Corporation. +[ 2.006305] ACPI: \_SB_.LNKC: Enabled at IRQ 11 +[ 2.083938] ata2: found unknown device (class 0) +[ 2.091881] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100 +[ 2.113176] scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5 +[ 2.143100] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray +[ 2.143415] cdrom: Uniform CD-ROM driver Revision: 3.20 +[ 2.159744] sr 1:0:0:0: Attached scsi generic sg0 type 5 +[ 2.332599] e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 52:54:00:12:34:56 +[ 2.332988] e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection +[ 2.333492] e1000e: Intel(R) PRO/1000 Network Driver +[ 2.333551] e1000e: Copyright(c) 1999 - 2015 Intel Corporation. +[ 2.333649] sky2: driver version 1.30 +[ 2.410672] uhci_hcd 0000:00:01.2: UHCI Host Controller +[ 2.411956] uhci_hcd 0000:00:01.2: new USB bus registered, assigned bus number 1 +[ 2.412462] usb (null): enable endpoint +[ 2.412811] uhci_hcd 0000:00:01.2: detected 2 ports +[ 2.413601] uhci_hcd 0000:00:01.2: irq 11, io port 0x0000c080 +[ 2.417590] usb usb1: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 6.10 +[ 2.417767] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +[ 2.417878] usb usb1: Product: UHCI Host Controller +[ 2.417953] usb usb1: Manufacturer: Linux 6.10.0 uhci_hcd +[ 2.418026] usb usb1: SerialNumber: 0000:00:01.2 +[ 2.419022] usb usb1: set configuration 1 +[ 2.419388] usb usb1: enable endpoint +[ 2.420367] hub 1-0:1.0: USB hub found +[ 2.420792] hub 1-0:1.0: 2 ports detected +[ 2.497184] xhci_hcd 0000:00:04.0: xHCI Host Controller +[ 2.498345] xhci_hcd 0000:00:04.0: new USB bus registered, assigned bus number 2 +[ 2.498445] usb (null): enable endpoint +[ 2.499454] xhci_hcd 0000:00:04.0: xhci_reset +[ 2.501389] xhci_hcd 0000:00:04.0: hcc params 0x00087001 hci version 0x100 quirks 0x0000000000000010 +[ 2.506811] xhci_hcd 0000:00:04.0: xHCI Host Controller +[ 2.507039] xhci_hcd 0000:00:04.0: new USB bus registered, assigned bus number 3 +[ 2.507424] usb (null): enable endpoint +[ 2.507593] xhci_hcd 0000:00:04.0: Host supports USB 3.0 SuperSpeed +[ 2.507854] xhci_hcd 0000:00:04.0: xhci_start +[ 2.508427] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.10 +[ 2.508580] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +[ 2.508756] usb usb2: Product: xHCI Host Controller +[ 2.508871] usb usb2: Manufacturer: Linux 6.10.0 xhci-hcd +[ 2.509131] usb usb2: SerialNumber: 0000:00:04.0 +[ 2.509920] usb usb2: set configuration 1 +[ 2.510275] usb usb2: enable endpoint +[ 2.510466] xhci_hcd 0000:00:04.0: xhci_endpoint_reset +[ 2.510771] hub 2-0:1.0: USB hub found +[ 2.511089] hub 2-0:1.0: 4 ports detected +[ 2.513494] usb usb3: We don't know the algorithms for LPM for this host, disabling LPM. +[ 2.513951] usb usb3: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.10 +[ 2.514055] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +[ 2.514227] usb usb3: Product: xHCI Host Controller +[ 2.514296] usb usb3: Manufacturer: Linux 6.10.0 xhci-hcd +[ 2.514368] usb usb3: SerialNumber: 0000:00:04.0 +[ 2.514883] usb usb3: set configuration 1 +[ 2.514965] usb usb3: enable endpoint +[ 2.515026] xhci_hcd 0000:00:04.0: xhci_endpoint_reset +[ 2.515440] hub 3-0:1.0: USB hub found +[ 2.515734] hub 3-0:1.0: 4 ports detected +[ 2.517543] usbcore: registered new interface driver usblp +[ 2.517694] usbcore: registered new interface driver cdc_wdm +[ 2.517848] usbcore: registered new interface driver usbtmc +[ 2.518253] usbcore: registered new interface driver usb-storage +[ 2.518603] usbcore: registered new interface driver usbtest +[ 2.519455] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12 +[ 2.522615] serio: i8042 KBD port at 0x60,0x64 irq 1 +[ 2.522843] serio: i8042 AUX port at 0x60,0x64 irq 12 +[ 2.523947] mousedev: PS/2 mouse device common for all mice +[ 2.526357] usbcore: registered new interface driver synaptics_usb +[ 2.526636] rtc_cmos 00:05: RTC can wake from S4 +[ 2.528745] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1 +[ 2.532164] rtc_cmos 00:05: registered as rtc0 +[ 2.533862] rtc_cmos 00:05: alarms up to one day, y3k, 242 bytes nvram, hpet irqs +[ 2.535441] usbcore: registered new interface driver uvcvideo +[ 2.535594] fail to initialize ptp_kvm +[ 2.537713] device-mapper: ioctl: 4.48.0-ioctl (2023-03-01) initialised: dm-devel@lists.linux.dev +[ 2.538531] amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled +[ 2.538984] hid: raw HID events driver (C) Jiri Kosina +[ 2.541465] usbcore: registered new interface driver usbhid +[ 2.541652] usbhid: USB HID core driver +[ 2.551743] Initializing XFRM netlink socket +[ 2.552671] NET: Registered PF_INET6 protocol family +[ 2.560997] Segment Routing with IPv6 +[ 2.561134] In-situ OAM (IOAM) with IPv6 +[ 2.562570] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver +[ 2.566041] NET: Registered PF_PACKET protocol family +[ 2.567770] 9pnet: Installing 9P2000 support +[ 2.570983] Key type dns_resolver registered +[ 2.572937] IPI shorthand broadcast: enabled +[ 2.588660] sched_clock: Marking stable (2564087663, 24060212)->(2595772564, -7624689) +[ 2.590810] registered taskstats version 1 +[ 2.591876] Loading compiled-in X.509 certificates +[ 2.599670] Demotion targets for Node 0: null +[ 2.602804] PM: Magic number: 4:543:516 +[ 2.603545] printk: legacy console [netcon0] enabled +[ 2.603657] netconsole: network logging started +[ 2.605464] cfg80211: Loading compiled-in X.509 certificates for regulatory database +[ 2.613987] kworker/u4:0 (48) used greatest stack depth: 14512 bytes left +[ 2.623996] Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7' +[ 2.624886] Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600' +[ 2.629026] ALSA device list: +[ 2.629500] No soundcards found. +[ 2.631516] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2 +[ 2.631795] cfg80211: failed to load regulatory.db +[ 2.754593] tsc: Refined TSC clocksource calibration: 2419.201 MHz +[ 2.755408] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x22df11e194f, max_idle_ns: 440795284480 ns +[ 2.755681] clocksource: Switched to clocksource tsc +[ 3.164885] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3 +[ 3.166250] md: Waiting for all devices to be available before autodetect +[ 3.166438] md: If you don't use raid, use raid=noautodetect +[ 3.166552] md: Autodetecting RAID arrays. +[ 3.166635] md: autorun ... +[ 3.166718] md: ... autorun DONE. +[ 3.173750] VFS: Mounted root (9p filesystem) readonly on device 0:19. +[ 3.176489] devtmpfs: mounted +[ 3.230656] Freeing unused kernel image (initmem) memory: 2848K +[ 3.231019] Write protecting the kernel read-only data: 28672k +[ 3.231804] Freeing unused kernel image (rodata/data gap) memory: 456K +[ 3.346618] x86/mm: Checked W+X mappings: passed, no W+X pages found. +[ 3.347011] Run /bin/sh as init process +/bin/sh: 0: can't access tty; job control turned off +# ls /dev +autofs loop3 snapshot tty19 tty32 tty46 tty6 usbmon2 +bsg loop4 snd tty2 tty33 tty47 tty60 usbmon3 +bus loop5 sr0 tty20 tty34 tty48 tty61 vcs +console loop6 tty tty21 tty35 tty49 tty62 vcs1 +cpu loop7 tty0 tty22 tty36 tty5 tty63 vcsa +cpu_dma_latency mapper tty1 tty23 tty37 tty50 tty7 vcsa1 +full mem tty10 tty24 tty38 tty51 tty8 vcsu +hpet null tty11 tty25 tty39 tty52 tty9 vcsu1 +hwrng nvram tty12 tty26 tty4 tty53 ttyS0 vga_arbiter +input port tty13 tty27 tty40 tty54 ttyS1 zero +kmsg ptmx tty14 tty28 tty41 tty55 ttyS2 +loop-control random tty15 tty29 tty42 tty56 ttyS3 +loop0 rfkill tty16 tty3 tty43 tty57 urandom +loop1 rtc0 tty17 tty30 tty44 tty58 usbmon0 +loop2 sg0 tty18 tty31 tty45 tty59 usbmon1 +[ 8.554754] ls (53) used greatest stack depth: 13544 bytes left +# [ 15.915040] xhci_hcd 0000:00:04.0: dump trb: +[ 15.915139] xhci_hcd 0000:00:04.0: 0 +[ 15.915173] xhci_hcd 0000:00:04.0: 0 +[ 15.915199] xhci_hcd 0000:00:04.0: 0 +[ 15.915281] xhci_hcd 0000:00:04.0: 2401 +[ 15.916522] usb (null): enable endpoint +[ 16.032049] xhci_hcd 0000:00:04.0: reset device +[ 16.032981] usb 2-1: new high-speed USB device number 2 using xhci_hcd +[ 16.033631] xhci_hcd 0000:00:04.0: xhci_setup_device +[ 16.034612] xhci_hcd 0000:00:04.0: dump trb: +[ 16.034727] xhci_hcd 0000:00:04.0: 1fce000 +[ 16.034801] xhci_hcd 0000:00:04.0: 0 +[ 16.034853] xhci_hcd 0000:00:04.0: 0 +[ 16.034903] xhci_hcd 0000:00:04.0: 1002e01 +[ 16.036635] xhci_hcd 0000:00:04.0: dump trb: +[ 16.036723] xhci_hcd 0000:00:04.0: 1000680 +[ 16.036797] xhci_hcd 0000:00:04.0: 400000 +[ 16.036867] xhci_hcd 0000:00:04.0: 8 +[ 16.036926] xhci_hcd 0000:00:04.0: 30840 +[ 16.037099] xhci_hcd 0000:00:04.0: dump trb: +[ 16.037174] xhci_hcd 0000:00:04.0: 1fd9340 +[ 16.037221] xhci_hcd 0000:00:04.0: 0 +[ 16.037266] xhci_hcd 0000:00:04.0: 40 +[ 16.037316] xhci_hcd 0000:00:04.0: 10c05 +[ 16.037396] xhci_hcd 0000:00:04.0: dump trb: +[ 16.037450] xhci_hcd 0000:00:04.0: 0 +[ 16.037483] xhci_hcd 0000:00:04.0: 0 +[ 16.037511] xhci_hcd 0000:00:04.0: 0 +[ 16.037540] xhci_hcd 0000:00:04.0: 1021 +[ 16.153698] xhci_hcd 0000:00:04.0: reset device +[ 16.154143] xhci_hcd 0000:00:04.0: dump trb: +[ 16.154662] xhci_hcd 0000:00:04.0: 0 +[ 16.154815] xhci_hcd 0000:00:04.0: 0 +[ 16.154904] xhci_hcd 0000:00:04.0: 0 +[ 16.155003] xhci_hcd 0000:00:04.0: 1004401 +[ 16.156056] xhci_hcd 0000:00:04.0: xhci_setup_device +[ 16.156469] xhci_hcd 0000:00:04.0: dump trb: +[ 16.156606] xhci_hcd 0000:00:04.0: 1fce000 +[ 16.156741] xhci_hcd 0000:00:04.0: 0 +[ 16.156823] xhci_hcd 0000:00:04.0: 0 +[ 16.156896] xhci_hcd 0000:00:04.0: 1002c01 +[ 16.157390] usb 2-1: enable endpoint +[ 16.157504] xhci_hcd 0000:00:04.0: xhci_endpoint_reset +[ 16.169476] xhci_hcd 0000:00:04.0: dump trb: +[ 16.169557] xhci_hcd 0000:00:04.0: 1000680 +[ 16.169600] xhci_hcd 0000:00:04.0: 120000 +[ 16.169638] xhci_hcd 0000:00:04.0: 8 +[ 16.169671] xhci_hcd 0000:00:04.0: 30840 +[ 16.169714] xhci_hcd 0000:00:04.0: dump trb: +[ 16.169761] xhci_hcd 0000:00:04.0: 1de0a60 +[ 16.169807] xhci_hcd 0000:00:04.0: 0 +[ 16.169850] xhci_hcd 0000:00:04.0: 12 +[ 16.169918] xhci_hcd 0000:00:04.0: 10c05 +[ 16.170014] xhci_hcd 0000:00:04.0: dump trb: +[ 16.170097] xhci_hcd 0000:00:04.0: 0 +[ 16.170309] xhci_hcd 0000:00:04.0: 0 +[ 16.170376] xhci_hcd 0000:00:04.0: 0 +[ 16.170417] xhci_hcd 0000:00:04.0: 1021 +[ 16.171840] xhci_hcd 0000:00:04.0: dump trb: +[ 16.171909] xhci_hcd 0000:00:04.0: 2000680 +[ 16.171945] xhci_hcd 0000:00:04.0: 90000 +[ 16.171976] xhci_hcd 0000:00:04.0: 8 +[ 16.172004] xhci_hcd 0000:00:04.0: 30840 +[ 16.172038] xhci_hcd 0000:00:04.0: dump trb: +[ 16.172077] xhci_hcd 0000:00:04.0: 1f2fbe0 +[ 16.172128] xhci_hcd 0000:00:04.0: 0 +[ 16.172340] xhci_hcd 0000:00:04.0: 9 +[ 16.172419] xhci_hcd 0000:00:04.0: 10c05 +[ 16.172506] xhci_hcd 0000:00:04.0: dump trb: +[ 16.172588] xhci_hcd 0000:00:04.0: 0 +[ 16.172662] xhci_hcd 0000:00:04.0: 0 +[ 16.172731] xhci_hcd 0000:00:04.0: 0 +[ 16.172814] xhci_hcd 0000:00:04.0: 1021 +[ 16.174073] xhci_hcd 0000:00:04.0: dump trb: +[ 16.174184] xhci_hcd 0000:00:04.0: 2000680 +[ 16.174272] xhci_hcd 0000:00:04.0: 2b90000 +[ 16.174356] xhci_hcd 0000:00:04.0: 8 +[ 16.174438] xhci_hcd 0000:00:04.0: 30840 +[ 16.174521] xhci_hcd 0000:00:04.0: dump trb: +[ 16.174603] xhci_hcd 0000:00:04.0: 1d45000 +[ 16.174685] xhci_hcd 0000:00:04.0: 0 +[ 16.174726] xhci_hcd 0000:00:04.0: 2b9 +[ 16.174784] xhci_hcd 0000:00:04.0: 10c05 +[ 16.174854] xhci_hcd 0000:00:04.0: dump trb: +[ 16.174919] xhci_hcd 0000:00:04.0: 0 +[ 16.174976] xhci_hcd 0000:00:04.0: 0 +[ 16.175030] xhci_hcd 0000:00:04.0: 0 +[ 16.175092] xhci_hcd 0000:00:04.0: 1021 +[ 16.196635] xhci_hcd 0000:00:04.0: dump trb: +[ 16.196722] xhci_hcd 0000:00:04.0: 3000680 +[ 16.196761] xhci_hcd 0000:00:04.0: ff0000 +[ 16.196796] xhci_hcd 0000:00:04.0: 8 +[ 16.196844] xhci_hcd 0000:00:04.0: 30840 +[ 16.196906] xhci_hcd 0000:00:04.0: dump trb: +[ 16.196952] xhci_hcd 0000:00:04.0: 1fd5000 +[ 16.196993] xhci_hcd 0000:00:04.0: 0 +[ 16.197029] xhci_hcd 0000:00:04.0: ff +[ 16.197070] xhci_hcd 0000:00:04.0: 10c05 +[ 16.197112] xhci_hcd 0000:00:04.0: dump trb: +[ 16.197158] xhci_hcd 0000:00:04.0: 0 +[ 16.197197] xhci_hcd 0000:00:04.0: 0 +[ 16.197237] xhci_hcd 0000:00:04.0: 0 +[ 16.197279] xhci_hcd 0000:00:04.0: 1021 +[ 16.198456] xhci_hcd 0000:00:04.0: dump trb: +[ 16.198529] xhci_hcd 0000:00:04.0: 3010680 +[ 16.198603] xhci_hcd 0000:00:04.0: ff0409 +[ 16.198671] xhci_hcd 0000:00:04.0: 8 +[ 16.198732] xhci_hcd 0000:00:04.0: 30840 +[ 16.198806] xhci_hcd 0000:00:04.0: dump trb: +[ 16.198882] xhci_hcd 0000:00:04.0: 1fd5000 +[ 16.198959] xhci_hcd 0000:00:04.0: 0 +[ 16.199063] xhci_hcd 0000:00:04.0: ff +[ 16.199147] xhci_hcd 0000:00:04.0: 10c05 +[ 16.199412] xhci_hcd 0000:00:04.0: dump trb: +[ 16.199515] xhci_hcd 0000:00:04.0: 0 +[ 16.199592] xhci_hcd 0000:00:04.0: 0 +[ 16.199668] xhci_hcd 0000:00:04.0: 0 +[ 16.199765] xhci_hcd 0000:00:04.0: 1021 +[ 16.201678] xhci_hcd 0000:00:04.0: dump trb: +[ 16.201750] xhci_hcd 0000:00:04.0: 3020680 +[ 16.201807] xhci_hcd 0000:00:04.0: ff0409 +[ 16.201869] xhci_hcd 0000:00:04.0: 8 +[ 16.201927] xhci_hcd 0000:00:04.0: 30840 +[ 16.202001] xhci_hcd 0000:00:04.0: dump trb: +[ 16.202065] xhci_hcd 0000:00:04.0: 1fd5000 +[ 16.202129] xhci_hcd 0000:00:04.0: 0 +[ 16.202243] xhci_hcd 0000:00:04.0: ff +[ 16.202313] xhci_hcd 0000:00:04.0: 10c05 +[ 16.202382] xhci_hcd 0000:00:04.0: dump trb: +[ 16.202441] xhci_hcd 0000:00:04.0: 0 +[ 16.202500] xhci_hcd 0000:00:04.0: 0 +[ 16.202555] xhci_hcd 0000:00:04.0: 0 +[ 16.202592] xhci_hcd 0000:00:04.0: 1021 +[ 16.203625] xhci_hcd 0000:00:04.0: dump trb: +[ 16.203683] xhci_hcd 0000:00:04.0: 3030680 +[ 16.203735] xhci_hcd 0000:00:04.0: ff0409 +[ 16.203784] xhci_hcd 0000:00:04.0: 8 +[ 16.203835] xhci_hcd 0000:00:04.0: 30840 +[ 16.203886] xhci_hcd 0000:00:04.0: dump trb: +[ 16.203936] xhci_hcd 0000:00:04.0: 1fd5000 +[ 16.203992] xhci_hcd 0000:00:04.0: 0 +[ 16.204044] xhci_hcd 0000:00:04.0: ff +[ 16.204099] xhci_hcd 0000:00:04.0: 10c05 +[ 16.204155] xhci_hcd 0000:00:04.0: dump trb: +[ 16.204253] xhci_hcd 0000:00:04.0: 0 +[ 16.204307] xhci_hcd 0000:00:04.0: 0 +[ 16.204362] xhci_hcd 0000:00:04.0: 0 +[ 16.204421] xhci_hcd 0000:00:04.0: 1021 +[ 16.205596] usb 2-1: New USB device found, idVendor=328f, idProduct=0073, bcdDevice= 1.00 +[ 16.205678] usb 2-1: New USB device strings: Mfr=2, Product=1, SerialNumber=3 +[ 16.205750] usb 2-1: Product: HD Webcam eMeet C950 +[ 16.205806] usb 2-1: Manufacturer: EMEET +[ 16.205860] usb 2-1: SerialNumber: SN0001 +[ 16.206593] usb 2-1: set configuration 1 +[ 16.207225] xhci_hcd 0000:00:04.0: xhci_configure_endpoint +[ 16.207578] xhci_hcd 0000:00:04.0: slot ctx================================================================= +[ 16.207719] xhci_hcd 0000:00:04.0: slot_ctx:devinfo: 38300000 +[ 16.207812] xhci_hcd 0000:00:04.0: slot_ctx:devinfo2: 50000 +[ 16.207896] xhci_hcd 0000:00:04.0: slot_ctx:ttinfo: 0 +[ 16.207978] xhci_hcd 0000:00:04.0: slot_ctx:dev_state: 0 +[ 16.208062] xhci_hcd 0000:00:04.0: ctrl ctx================================================================= +[ 16.208171] xhci_hcd 0000:00:04.0: ctrl_ctx:add_flags: 81 +[ 16.208524] xhci_hcd 0000:00:04.0: ctrl_ctx:drop_flags: 0 +[ 16.208618] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 0: 0 +[ 16.208697] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 1: 0 +[ 16.208767] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 2: 0 +[ 16.208837] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 3: 0 +[ 16.208889] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 4: 0 +[ 16.208936] xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 5: 0 +[ 16.209022] xhci_hcd 0000:00:04.0: endpoint 0================================================================= +[ 16.209143] xhci_hcd 0000:00:04.0: deque_32: 1fd1031 +[ 16.209218] xhci_hcd 0000:00:04.0: ep_info2_32: 400026 +[ 16.209299] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.209479] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.209572] xhci_hcd 0000:00:04.0: deque_ptr_64: 1fd1031 +[ 16.209665] xhci_hcd 0000:00:04.0: endpoint 1================================================================= +[ 16.209768] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.209937] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.210045] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.210121] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.210186] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.210228] xhci_hcd 0000:00:04.0: endpoint 2================================================================= +[ 16.210296] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.210330] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.210437] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.210518] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.210582] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.210642] xhci_hcd 0000:00:04.0: endpoint 3================================================================= +[ 16.210715] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.210750] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.210786] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.210821] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.210856] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.211117] xhci_hcd 0000:00:04.0: endpoint 4================================================================= +[ 16.211265] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.211335] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.211383] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.211453] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.211532] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.211597] xhci_hcd 0000:00:04.0: endpoint 5================================================================= +[ 16.211695] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.211740] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.211787] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.211833] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.211874] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.211922] xhci_hcd 0000:00:04.0: endpoint 6================================================================= +[ 16.212014] xhci_hcd 0000:00:04.0: deque_32: 1fd8001 +[ 16.212065] xhci_hcd 0000:00:04.0: ep_info2_32: 10003e +[ 16.212125] xhci_hcd 0000:00:04.0: ep_info1_32: 50000 +[ 16.212180] xhci_hcd 0000:00:04.0: tx_info_32: 100010 +[ 16.212232] xhci_hcd 0000:00:04.0: deque_ptr_64: 1fd8001 +[ 16.212284] xhci_hcd 0000:00:04.0: endpoint 7================================================================= +[ 16.212373] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.212442] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.212520] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.212601] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.212684] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.212742] xhci_hcd 0000:00:04.0: endpoint 8================================================================= +[ 16.212877] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.212961] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.213025] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.213104] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.213162] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.213243] xhci_hcd 0000:00:04.0: endpoint 9================================================================= +[ 16.213341] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.213392] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.213447] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.213494] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.213539] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.213586] xhci_hcd 0000:00:04.0: endpoint 10================================================================= +[ 16.213679] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.213752] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.213830] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.213916] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.214001] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.214058] xhci_hcd 0000:00:04.0: endpoint 11================================================================= +[ 16.214154] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.214204] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.214254] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.214331] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.214386] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.214438] xhci_hcd 0000:00:04.0: endpoint 12================================================================= +[ 16.214538] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.214614] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.214678] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.214732] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.214786] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.214865] xhci_hcd 0000:00:04.0: endpoint 13================================================================= +[ 16.214963] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.215040] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.215100] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.215152] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.215203] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.215255] xhci_hcd 0000:00:04.0: endpoint 14================================================================= +[ 16.215356] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.215437] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.215536] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.215633] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.215727] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.215816] xhci_hcd 0000:00:04.0: endpoint 15================================================================= +[ 16.215920] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.215998] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.216082] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.216167] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.216242] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.216327] xhci_hcd 0000:00:04.0: endpoint 16================================================================= +[ 16.216426] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.216503] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.216589] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.216647] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.216726] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.216812] xhci_hcd 0000:00:04.0: endpoint 17================================================================= +[ 16.216939] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.217020] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.217075] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.217152] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.217203] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.217275] xhci_hcd 0000:00:04.0: endpoint 18================================================================= +[ 16.217370] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.217444] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.217498] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.217573] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.217629] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.217683] xhci_hcd 0000:00:04.0: endpoint 19================================================================= +[ 16.217799] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.217886] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.217940] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.217988] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.218034] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.218082] xhci_hcd 0000:00:04.0: endpoint 20================================================================= +[ 16.218156] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.218195] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.218232] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.218269] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.218305] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.218343] xhci_hcd 0000:00:04.0: endpoint 21================================================================= +[ 16.218411] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.218450] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.218491] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.218527] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.218564] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.218601] xhci_hcd 0000:00:04.0: endpoint 22================================================================= +[ 16.218669] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.218705] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.218741] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.218778] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.218814] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.218851] xhci_hcd 0000:00:04.0: endpoint 23================================================================= +[ 16.218923] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.218963] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.219000] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.219036] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.219072] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.219109] xhci_hcd 0000:00:04.0: endpoint 24================================================================= +[ 16.219178] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.219214] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.219250] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.219289] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.219324] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.219360] xhci_hcd 0000:00:04.0: endpoint 25================================================================= +[ 16.219426] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.219460] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.219496] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.219532] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.219575] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.219622] xhci_hcd 0000:00:04.0: endpoint 26================================================================= +[ 16.219737] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.219813] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.219893] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.219970] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.220047] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.220132] xhci_hcd 0000:00:04.0: endpoint 27================================================================= +[ 16.220247] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.220313] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.220377] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.220440] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.220486] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.220544] xhci_hcd 0000:00:04.0: endpoint 28================================================================= +[ 16.220638] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.220696] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.220759] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.220822] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.220884] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.220925] xhci_hcd 0000:00:04.0: endpoint 29================================================================= +[ 16.221018] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.221080] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.221143] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.221208] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.221252] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.221293] xhci_hcd 0000:00:04.0: endpoint 30================================================================= +[ 16.221383] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.221442] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.221502] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.221563] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.221623] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.221686] xhci_hcd 0000:00:04.0: endpoint 31================================================================= +[ 16.221780] xhci_hcd 0000:00:04.0: deque_32: 0 +[ 16.221840] xhci_hcd 0000:00:04.0: ep_info2_32: 0 +[ 16.221901] xhci_hcd 0000:00:04.0: ep_info1_32: 0 +[ 16.221961] xhci_hcd 0000:00:04.0: tx_info_32: 0 +[ 16.222001] xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +[ 16.222094] xhci_hcd 0000:00:04.0: queue configure endpoint +[ 16.222185] xhci_hcd 0000:00:04.0: dump trb: +[ 16.222244] xhci_hcd 0000:00:04.0: 1fce000 +[ 16.222301] xhci_hcd 0000:00:04.0: 0 +[ 16.222356] xhci_hcd 0000:00:04.0: 0 +[ 16.222410] xhci_hcd 0000:00:04.0: 1003001 +[ 16.223122] usb 2-1: enable endpoint +[ 16.223310] xhci_hcd 0000:00:04.0: xhci_endpoint_reset +[ 16.223628] xhci_hcd 0000:00:04.0: dump trb: +[ 16.223795] xhci_hcd 0000:00:04.0: 0 +[ 16.223887] xhci_hcd 0000:00:04.0: 0 +[ 16.223953] xhci_hcd 0000:00:04.0: 0 +[ 16.224004] xhci_hcd 0000:00:04.0: 1073c01 +[ 16.224401] xhci_hcd 0000:00:04.0: queue configure endpoint +[ 16.224480] xhci_hcd 0000:00:04.0: dump trb: +[ 16.224539] xhci_hcd 0000:00:04.0: 1fd0000 +[ 16.224599] xhci_hcd 0000:00:04.0: 0 +[ 16.224656] xhci_hcd 0000:00:04.0: 0 +[ 16.224712] xhci_hcd 0000:00:04.0: 1003001 +[ 16.225025] xhci_hcd 0000:00:04.0: dump trb: +[ 16.225087] xhci_hcd 0000:00:04.0: 10900 +[ 16.225146] xhci_hcd 0000:00:04.0: 0 +[ 16.225269] xhci_hcd 0000:00:04.0: 8 +[ 16.225310] xhci_hcd 0000:00:04.0: 840 +[ 16.225399] xhci_hcd 0000:00:04.0: dump trb: +[ 16.225460] xhci_hcd 0000:00:04.0: 0 +[ 16.225518] xhci_hcd 0000:00:04.0: 0 +[ 16.225576] xhci_hcd 0000:00:04.0: 0 +[ 16.225633] xhci_hcd 0000:00:04.0: 11021 +[ 16.226195] xhci_hcd 0000:00:04.0: dump trb: +[ 16.226264] xhci_hcd 0000:00:04.0: 3050680 +[ 16.226318] xhci_hcd 0000:00:04.0: ff0409 +[ 16.226390] xhci_hcd 0000:00:04.0: 8 +[ 16.226449] xhci_hcd 0000:00:04.0: 30840 +[ 16.226514] xhci_hcd 0000:00:04.0: dump trb: +[ 16.226579] xhci_hcd 0000:00:04.0: 1fd5700 +[ 16.226620] xhci_hcd 0000:00:04.0: 0 +[ 16.226654] xhci_hcd 0000:00:04.0: ff +[ 16.226686] xhci_hcd 0000:00:04.0: 10c05 +[ 16.226722] xhci_hcd 0000:00:04.0: dump trb: +[ 16.226758] xhci_hcd 0000:00:04.0: 0 +[ 16.226791] xhci_hcd 0000:00:04.0: 0 +[ 16.226823] xhci_hcd 0000:00:04.0: 0 +[ 16.226875] xhci_hcd 0000:00:04.0: 1021 +[ 16.229577] xhci_hcd 0000:00:04.0: dump trb: +[ 16.229661] xhci_hcd 0000:00:04.0: 3050680 +[ 16.229707] xhci_hcd 0000:00:04.0: ff0409 +[ 16.229769] xhci_hcd 0000:00:04.0: 8 +[ 16.229813] xhci_hcd 0000:00:04.0: 30840 +[ 16.229856] xhci_hcd 0000:00:04.0: dump trb: +[ 16.229899] xhci_hcd 0000:00:04.0: 1fd5700 +[ 16.229942] xhci_hcd 0000:00:04.0: 0 +[ 16.230011] xhci_hcd 0000:00:04.0: ff +[ 16.230087] xhci_hcd 0000:00:04.0: 10c05 +[ 16.230213] xhci_hcd 0000:00:04.0: dump trb: +[ 16.230298] xhci_hcd 0000:00:04.0: 0 +[ 16.230370] xhci_hcd 0000:00:04.0: 0 +[ 16.230439] xhci_hcd 0000:00:04.0: 0 +[ 16.230508] xhci_hcd 0000:00:04.0: 1021 +[ 16.235761] usb 2-1: Found UVC 1.00 device HD Webcam eMeet C950 (328f:0073) +[ 16.236812] xhci_hcd 0000:00:04.0: dump trb: +[ 16.236878] xhci_hcd 0000:00:04.0: 20086a1 get info +[ 16.236936] xhci_hcd 0000:00:04.0: 10200 +[ 16.236989] xhci_hcd 0000:00:04.0: 8 +[ 16.237038] xhci_hcd 0000:00:04.0: 30840 +[ 16.237090] xhci_hcd 0000:00:04.0: dump trb: +[ 16.237141] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.237195] xhci_hcd 0000:00:04.0: 0 +[ 16.237300] xhci_hcd 0000:00:04.0: 1 +[ 16.237336] xhci_hcd 0000:00:04.0: 10c05 +[ 16.237388] xhci_hcd 0000:00:04.0: dump trb: +[ 16.237444] xhci_hcd 0000:00:04.0: 0 +[ 16.237495] xhci_hcd 0000:00:04.0: 0 +[ 16.237549] xhci_hcd 0000:00:04.0: 0 +[ 16.237604] xhci_hcd 0000:00:04.0: 1021 +[ 16.238801] xhci_hcd 0000:00:04.0: dump trb: +[ 16.238873] xhci_hcd 0000:00:04.0: 30086a1 get info +[ 16.238908] xhci_hcd 0000:00:04.0: 10200 +[ 16.238938] xhci_hcd 0000:00:04.0: 8 +[ 16.238983] xhci_hcd 0000:00:04.0: 30840 +[ 16.239035] xhci_hcd 0000:00:04.0: dump trb: +[ 16.239091] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.239155] xhci_hcd 0000:00:04.0: 0 +[ 16.239207] xhci_hcd 0000:00:04.0: 1 +[ 16.239259] xhci_hcd 0000:00:04.0: 10c05 +[ 16.239314] xhci_hcd 0000:00:04.0: dump trb: +[ 16.239352] xhci_hcd 0000:00:04.0: 0 +[ 16.239381] xhci_hcd 0000:00:04.0: 0 +[ 16.239409] xhci_hcd 0000:00:04.0: 0 +[ 16.239437] xhci_hcd 0000:00:04.0: 1021 +[ 16.240070] xhci_hcd 0000:00:04.0: dump trb: +[ 16.240126] xhci_hcd 0000:00:04.0: 60086a1 get info +[ 16.240177] xhci_hcd 0000:00:04.0: 10200 +[ 16.240298] xhci_hcd 0000:00:04.0: 8 +[ 16.240352] xhci_hcd 0000:00:04.0: 30840 +[ 16.240408] xhci_hcd 0000:00:04.0: dump trb: +[ 16.240445] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.240481] xhci_hcd 0000:00:04.0: 0 +[ 16.240513] xhci_hcd 0000:00:04.0: 1 +[ 16.240572] xhci_hcd 0000:00:04.0: 10c05 +[ 16.240613] xhci_hcd 0000:00:04.0: dump trb: +[ 16.240677] xhci_hcd 0000:00:04.0: 0 +[ 16.240715] xhci_hcd 0000:00:04.0: 0 +[ 16.240747] xhci_hcd 0000:00:04.0: 0 +[ 16.240782] xhci_hcd 0000:00:04.0: 1021 +[ 16.241371] xhci_hcd 0000:00:04.0: dump trb: +[ 16.241444] xhci_hcd 0000:00:04.0: 70086a1 get info +[ 16.241500] xhci_hcd 0000:00:04.0: 10200 +[ 16.241552] xhci_hcd 0000:00:04.0: 8 +[ 16.241585] xhci_hcd 0000:00:04.0: 30840 +[ 16.241616] xhci_hcd 0000:00:04.0: dump trb: +[ 16.241649] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.241680] xhci_hcd 0000:00:04.0: 0 +[ 16.241708] xhci_hcd 0000:00:04.0: 1 +[ 16.241736] xhci_hcd 0000:00:04.0: 10c05 +[ 16.241766] xhci_hcd 0000:00:04.0: dump trb: +[ 16.241798] xhci_hcd 0000:00:04.0: 0 +[ 16.241827] xhci_hcd 0000:00:04.0: 0 +[ 16.241854] xhci_hcd 0000:00:04.0: 0 +[ 16.241882] xhci_hcd 0000:00:04.0: 1021 +[ 16.242998] xhci_hcd 0000:00:04.0: dump trb: +[ 16.243073] xhci_hcd 0000:00:04.0: 80086a1 +[ 16.243133] xhci_hcd 0000:00:04.0: 10200 +[ 16.243208] xhci_hcd 0000:00:04.0: 8 +[ 16.243265] xhci_hcd 0000:00:04.0: 30840 +[ 16.243324] xhci_hcd 0000:00:04.0: dump trb: +[ 16.243385] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.243445] xhci_hcd 0000:00:04.0: 0 +[ 16.243501] xhci_hcd 0000:00:04.0: 1 +[ 16.243558] xhci_hcd 0000:00:04.0: 10c05 +[ 16.243619] xhci_hcd 0000:00:04.0: dump trb: +[ 16.243679] xhci_hcd 0000:00:04.0: 0 +[ 16.243717] xhci_hcd 0000:00:04.0: 0 +[ 16.243749] xhci_hcd 0000:00:04.0: 0 +[ 16.243780] xhci_hcd 0000:00:04.0: 1021 +[ 16.244821] xhci_hcd 0000:00:04.0: dump trb: +[ 16.244898] xhci_hcd 0000:00:04.0: 90086a1 +[ 16.244962] xhci_hcd 0000:00:04.0: 10200 +[ 16.245034] xhci_hcd 0000:00:04.0: 8 +[ 16.245096] xhci_hcd 0000:00:04.0: 30840 +[ 16.245195] xhci_hcd 0000:00:04.0: dump trb: +[ 16.245257] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.245298] xhci_hcd 0000:00:04.0: 0 +[ 16.245330] xhci_hcd 0000:00:04.0: 1 +[ 16.245361] xhci_hcd 0000:00:04.0: 10c05 +[ 16.245395] xhci_hcd 0000:00:04.0: dump trb: +[ 16.245430] xhci_hcd 0000:00:04.0: 0 +[ 16.245461] xhci_hcd 0000:00:04.0: 0 +[ 16.245492] xhci_hcd 0000:00:04.0: 0 +[ 16.245523] xhci_hcd 0000:00:04.0: 1021 +[ 16.246244] xhci_hcd 0000:00:04.0: dump trb: +[ 16.246298] xhci_hcd 0000:00:04.0: a0086a1 +[ 16.246356] xhci_hcd 0000:00:04.0: 10200 +[ 16.246405] xhci_hcd 0000:00:04.0: 8 +[ 16.246451] xhci_hcd 0000:00:04.0: 30840 +[ 16.246500] xhci_hcd 0000:00:04.0: dump trb: +[ 16.246552] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.246606] xhci_hcd 0000:00:04.0: 0 +[ 16.246657] xhci_hcd 0000:00:04.0: 1 +[ 16.246710] xhci_hcd 0000:00:04.0: 10c05 +[ 16.246766] xhci_hcd 0000:00:04.0: dump trb: +[ 16.246825] xhci_hcd 0000:00:04.0: 0 +[ 16.246878] xhci_hcd 0000:00:04.0: 0 +[ 16.246933] xhci_hcd 0000:00:04.0: 0 +[ 16.246993] xhci_hcd 0000:00:04.0: 1021 +[ 16.247655] xhci_hcd 0000:00:04.0: dump trb: +[ 16.247716] xhci_hcd 0000:00:04.0: 10086a1 +[ 16.247767] xhci_hcd 0000:00:04.0: 10200 +[ 16.247817] xhci_hcd 0000:00:04.0: 8 +[ 16.247866] xhci_hcd 0000:00:04.0: 30840 +[ 16.247922] xhci_hcd 0000:00:04.0: dump trb: +[ 16.247995] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.248054] xhci_hcd 0000:00:04.0: 0 +[ 16.248111] xhci_hcd 0000:00:04.0: 1 +[ 16.248220] xhci_hcd 0000:00:04.0: 10c05 +[ 16.248277] xhci_hcd 0000:00:04.0: dump trb: +[ 16.248335] xhci_hcd 0000:00:04.0: 0 +[ 16.248399] xhci_hcd 0000:00:04.0: 0 +[ 16.248454] xhci_hcd 0000:00:04.0: 0 +[ 16.248508] xhci_hcd 0000:00:04.0: 1021 +[ 16.249174] xhci_hcd 0000:00:04.0: dump trb: +[ 16.249242] xhci_hcd 0000:00:04.0: 40086a1 +[ 16.249296] xhci_hcd 0000:00:04.0: 10200 +[ 16.249345] xhci_hcd 0000:00:04.0: 8 +[ 16.249397] xhci_hcd 0000:00:04.0: 30840 +[ 16.249451] xhci_hcd 0000:00:04.0: dump trb: +[ 16.249505] xhci_hcd 0000:00:04.0: 1dbe678 +[ 16.249560] xhci_hcd 0000:00:04.0: 0 +[ 16.249596] xhci_hcd 0000:00:04.0: 1 +[ 16.249627] xhci_hcd 0000:00:04.0: 10c05 +[ 16.249659] xhci_hcd 0000:00:04.0: dump trb: +[ 16.249694] xhci_hcd 0000:00:04.0: 0 +[ 16.249724] xhci_hcd 0000:00:04.0: 0 +[ 16.249754] xhci_hcd 0000:00:04.0: 0 +[ 16.249784] xhci_hcd 0000:00:04.0: 1021 +[ 16.250771] xhci_hcd 0000:00:04.0: dump trb: +[ 16.250833] xhci_hcd 0000:00:04.0: 50086a1 +[ 16.250889] xhci_hcd 0000:00:04.0: 10200 +[ 16.250944] xhci_hcd 0000:00:04.0: 8 +[ 16.250997] xhci_hcd 0000:00:04.0: 30840 +[ 16.251053] xhci_hcd 0000:00:04.0: dump trb: +[ 16.251109] xhci_hcd 0000:00:04.0: 1dbe680 +[ 16.251206] xhci_hcd 0000:00:04.0: 0 +[ 16.251263] xhci_hcd 0000:00:04.0: 1 +[ 16.251298] xhci_hcd 0000:00:04.0: 10c05 +[ 16.251331] xhci_hcd 0000:00:04.0: dump trb: +[ 16.251365] xhci_hcd 0000:00:04.0: 0 +[ 16.251397] xhci_hcd 0000:00:04.0: 0 +[ 16.251444] xhci_hcd 0000:00:04.0: 0 +[ 16.251497] xhci_hcd 0000:00:04.0: 1021 +[ 16.252606] xhci_hcd 0000:00:04.0: dump trb: +[ 16.252666] xhci_hcd 0000:00:04.0: b0086a1 +[ 16.252715] xhci_hcd 0000:00:04.0: 10200 +[ 16.252749] xhci_hcd 0000:00:04.0: 8 +[ 16.252784] xhci_hcd 0000:00:04.0: 30840 +[ 16.252823] xhci_hcd 0000:00:04.0: dump trb: +[ 16.252878] xhci_hcd 0000:00:04.0: 1dbe688 +[ 16.252968] xhci_hcd 0000:00:04.0: 0 +[ 16.253024] xhci_hcd 0000:00:04.0: 1 +[ 16.253089] xhci_hcd 0000:00:04.0: 10c05 +[ 16.253252] xhci_hcd 0000:00:04.0: dump trb: +[ 16.253327] xhci_hcd 0000:00:04.0: 0 +[ 16.253395] xhci_hcd 0000:00:04.0: 0 +[ 16.253452] xhci_hcd 0000:00:04.0: 0 +[ 16.253492] xhci_hcd 0000:00:04.0: 1021 +[ 16.254519] xhci_hcd 0000:00:04.0: dump trb: +[ 16.254588] xhci_hcd 0000:00:04.0: 20086a1 +[ 16.254645] xhci_hcd 0000:00:04.0: 10100 +[ 16.254700] xhci_hcd 0000:00:04.0: 8 +[ 16.254755] xhci_hcd 0000:00:04.0: 30840 +[ 16.254814] xhci_hcd 0000:00:04.0: dump trb: +[ 16.254873] xhci_hcd 0000:00:04.0: 1dbe690 +[ 16.254931] xhci_hcd 0000:00:04.0: 0 +[ 16.254986] xhci_hcd 0000:00:04.0: 1 +[ 16.255040] xhci_hcd 0000:00:04.0: 10c05 +[ 16.255098] xhci_hcd 0000:00:04.0: dump trb: +[ 16.255203] xhci_hcd 0000:00:04.0: 0 +[ 16.255262] xhci_hcd 0000:00:04.0: 0 +[ 16.255318] xhci_hcd 0000:00:04.0: 0 +[ 16.255375] xhci_hcd 0000:00:04.0: 1021 +[ 16.256187] xhci_hcd 0000:00:04.0: dump trb: +[ 16.256305] xhci_hcd 0000:00:04.0: 30086a1 +[ 16.256366] xhci_hcd 0000:00:04.0: 10100 +[ 16.256433] xhci_hcd 0000:00:04.0: 8 +[ 16.256492] xhci_hcd 0000:00:04.0: 30840 +[ 16.256554] xhci_hcd 0000:00:04.0: dump trb: +[ 16.256630] xhci_hcd 0000:00:04.0: 1dbe698 +[ 16.256693] xhci_hcd 0000:00:04.0: 0 +[ 16.256755] xhci_hcd 0000:00:04.0: 1 +[ 16.256827] xhci_hcd 0000:00:04.0: 10c05 +[ 16.256891] xhci_hcd 0000:00:04.0: dump trb: +[ 16.256950] xhci_hcd 0000:00:04.0: 0 +[ 16.256986] xhci_hcd 0000:00:04.0: 0 +[ 16.257021] xhci_hcd 0000:00:04.0: 0 +[ 16.257057] xhci_hcd 0000:00:04.0: 1021 +[ 16.257874] xhci_hcd 0000:00:04.0: dump trb: +[ 16.257965] xhci_hcd 0000:00:04.0: 40086a1 +[ 16.258036] xhci_hcd 0000:00:04.0: 10100 +[ 16.258106] xhci_hcd 0000:00:04.0: 8 +[ 16.258219] xhci_hcd 0000:00:04.0: 30840 +[ 16.258288] xhci_hcd 0000:00:04.0: dump trb: +[ 16.258360] xhci_hcd 0000:00:04.0: 1dbe698 +[ 16.258431] xhci_hcd 0000:00:04.0: 0 +[ 16.258496] xhci_hcd 0000:00:04.0: 1 +[ 16.258563] xhci_hcd 0000:00:04.0: 10c05 +[ 16.258627] xhci_hcd 0000:00:04.0: dump trb: +[ 16.258695] xhci_hcd 0000:00:04.0: 0 +[ 16.258760] xhci_hcd 0000:00:04.0: 0 +[ 16.258826] xhci_hcd 0000:00:04.0: 0 +[ 16.258893] xhci_hcd 0000:00:04.0: 1021 +[ 16.259735] xhci_hcd 0000:00:04.0: dump trb: +[ 16.259820] xhci_hcd 0000:00:04.0: f0086a1 +[ 16.259901] xhci_hcd 0000:00:04.0: 10100 +[ 16.259974] xhci_hcd 0000:00:04.0: 8 +[ 16.260046] xhci_hcd 0000:00:04.0: 30840 +[ 16.260122] xhci_hcd 0000:00:04.0: dump trb: +[ 16.260365] xhci_hcd 0000:00:04.0: 1dbe698 +[ 16.260450] xhci_hcd 0000:00:04.0: 0 +[ 16.260521] xhci_hcd 0000:00:04.0: 1 +[ 16.260592] xhci_hcd 0000:00:04.0: 10c05 +[ 16.260674] xhci_hcd 0000:00:04.0: dump trb: +[ 16.260752] xhci_hcd 0000:00:04.0: 0 +[ 16.260820] xhci_hcd 0000:00:04.0: 0 +[ 16.260888] xhci_hcd 0000:00:04.0: 0 +[ 16.260960] xhci_hcd 0000:00:04.0: 1021 +[ 16.262251] xhci_hcd 0000:00:04.0: dump trb: +[ 16.262340] xhci_hcd 0000:00:04.0: 100086a1 +[ 16.262415] xhci_hcd 0000:00:04.0: 10100 +[ 16.262461] xhci_hcd 0000:00:04.0: 8 +[ 16.262508] xhci_hcd 0000:00:04.0: 30840 +[ 16.262575] xhci_hcd 0000:00:04.0: dump trb: +[ 16.262666] xhci_hcd 0000:00:04.0: 1dbe698 +[ 16.262741] xhci_hcd 0000:00:04.0: 0 +[ 16.262847] xhci_hcd 0000:00:04.0: 1 +[ 16.262917] xhci_hcd 0000:00:04.0: 10c05 +[ 16.262992] xhci_hcd 0000:00:04.0: dump trb: +[ 16.263069] xhci_hcd 0000:00:04.0: 0 +[ 16.263141] xhci_hcd 0000:00:04.0: 0 +[ 16.263243] xhci_hcd 0000:00:04.0: 0 +[ 16.263290] xhci_hcd 0000:00:04.0: 1021 +[ 16.264280] usb 2-1: Failed to query (GET_INFO) UVC control 16 on unit 1: 0 (exp. 1). +[ 16.264533] usb 2-1: selecting interface 1, alternative0 +[ 16.264786] xhci_hcd 0000:00:04.0: dump trb: +[ 16.264843] xhci_hcd 0000:00:04.0: b01 +[ 16.264897] xhci_hcd 0000:00:04.0: 1 +[ 16.264949] xhci_hcd 0000:00:04.0: 8 +[ 16.265003] xhci_hcd 0000:00:04.0: 840 +[ 16.265054] xhci_hcd 0000:00:04.0: dump trb: +[ 16.265108] xhci_hcd 0000:00:04.0: 0 +[ 16.265142] xhci_hcd 0000:00:04.0: 0 +[ 16.265249] xhci_hcd 0000:00:04.0: 0 +[ 16.265302] xhci_hcd 0000:00:04.0: 11021 +[ 16.272227] xhci_hcd 0000:00:04.0: dump trb: +[ 16.272290] xhci_hcd 0000:00:04.0: 10087a1 +[ 16.272355] xhci_hcd 0000:00:04.0: 1a0001 +[ 16.272463] xhci_hcd 0000:00:04.0: 8 +[ 16.272526] xhci_hcd 0000:00:04.0: 30840 +[ 16.272590] xhci_hcd 0000:00:04.0: dump trb: +[ 16.272659] xhci_hcd 0000:00:04.0: 1de0b80 +[ 16.272723] xhci_hcd 0000:00:04.0: 0 +[ 16.272806] xhci_hcd 0000:00:04.0: 1a +[ 16.272869] xhci_hcd 0000:00:04.0: 10c05 +[ 16.272933] xhci_hcd 0000:00:04.0: dump trb: +[ 16.273005] xhci_hcd 0000:00:04.0: 0 +[ 16.273074] xhci_hcd 0000:00:04.0: 0 +[ 16.273134] xhci_hcd 0000:00:04.0: 0 +[ 16.273248] xhci_hcd 0000:00:04.0: 1021 +[ 16.274410] xhci_hcd 0000:00:04.0: dump trb: +[ 16.274489] xhci_hcd 0000:00:04.0: 1000121 +[ 16.274534] xhci_hcd 0000:00:04.0: 1a0001 +[ 16.274574] xhci_hcd 0000:00:04.0: 8 +[ 16.274637] xhci_hcd 0000:00:04.0: 20840 +[ 16.274785] xhci_hcd 0000:00:04.0: dump trb: +[ 16.274863] xhci_hcd 0000:00:04.0: 1de0b80 +[ 16.274943] xhci_hcd 0000:00:04.0: 0 +[ 16.275018] xhci_hcd 0000:00:04.0: 1a +[ 16.275093] xhci_hcd 0000:00:04.0: c01 +[ 16.275206] xhci_hcd 0000:00:04.0: dump trb: +[ 16.275288] xhci_hcd 0000:00:04.0: 0 +[ 16.275359] xhci_hcd 0000:00:04.0: 0 +[ 16.275432] xhci_hcd 0000:00:04.0: 0 +[ 16.275481] xhci_hcd 0000:00:04.0: 11021 +[ 16.276659] xhci_hcd 0000:00:04.0: dump trb: +[ 16.276744] xhci_hcd 0000:00:04.0: 10081a1 +[ 16.276789] xhci_hcd 0000:00:04.0: 1a0001 +[ 16.276832] xhci_hcd 0000:00:04.0: 8 +[ 16.276892] xhci_hcd 0000:00:04.0: 30840 +[ 16.276962] xhci_hcd 0000:00:04.0: dump trb: +[ 16.277036] xhci_hcd 0000:00:04.0: 1de0b80 +[ 16.277108] xhci_hcd 0000:00:04.0: 0 +[ 16.277211] xhci_hcd 0000:00:04.0: 1a +[ 16.277279] xhci_hcd 0000:00:04.0: 10c05 +[ 16.277353] xhci_hcd 0000:00:04.0: dump trb: +[ 16.277428] xhci_hcd 0000:00:04.0: 0 +[ 16.277510] xhci_hcd 0000:00:04.0: 0 +[ 16.277580] xhci_hcd 0000:00:04.0: 0 +[ 16.277650] xhci_hcd 0000:00:04.0: 1021 +[ 16.283264] input: HD Webcam eMeet C950: HD Webcam as /devices/pci0000:00/0000:00:04.0/usb2/2-1/2-1:1.0/input/input4 +[ 18.468281] xhci_hcd 0000:00:04.0: dump trb: +[ 18.468484] xhci_hcd 0000:00:04.0: 0 +[ 18.468602] xhci_hcd 0000:00:04.0: 0 +[ 18.468703] xhci_hcd 0000:00:04.0: 0 +[ 18.468763] xhci_hcd 0000:00:04.0: 1873c01 +[ 18.468919] xhci_hcd 0000:00:04.0: dump trb: +[ 18.469014] xhci_hcd 0000:00:04.0: 0 +[ 18.469109] xhci_hcd 0000:00:04.0: 0 +[ 18.469203] xhci_hcd 0000:00:04.0: 0 +[ 18.469296] xhci_hcd 0000:00:04.0: 1813c01 + +# ls /dev +autofs loop3 sg0 tty18 tty31 tty45 tty59 usbmon1 +bsg loop4 snapshot tty19 tty32 tty46 tty6 usbmon2 +bus loop5 snd tty2 tty33 tty47 tty60 usbmon3 +console loop6 sr0 tty20 tty34 tty48 tty61 vcs +cpu loop7 tty tty21 tty35 tty49 tty62 vcs1 +cpu_dma_latency mapper tty0 tty22 tty36 tty5 tty63 vcsa +full media0 tty1 tty23 tty37 tty50 tty7 vcsa1 +hpet mem tty10 tty24 tty38 tty51 tty8 vcsu +hwrng null tty11 tty25 tty39 tty52 tty9 vcsu1 +input nvram tty12 tty26 tty4 tty53 ttyS0 vga_arbiter +kmsg port tty13 tty27 tty40 tty54 ttyS1 video0 +loop-control ptmx tty14 tty28 tty41 tty55 ttyS2 video1 +loop0 random tty15 tty29 tty42 tty56 ttyS3 zero +loop1 rfkill tty16 tty3 tty43 tty57 urandom +loop2 rtc0 tty17 tty30 tty44 tty58 usbmon0 +# cat /dev/video- 0 +[ 47.371733] xhci_hcd 0000:00:04.0: dump trb: +[ 47.371924] xhci_hcd 0000:00:04.0: 80 +[ 47.371994] xhci_hcd 0000:00:04.0: 20000 +[ 47.372081] xhci_hcd 0000:00:04.0: 8 +[ 47.372174] xhci_hcd 0000:00:04.0: 30840 +[ 47.372281] xhci_hcd 0000:00:04.0: dump trb: +[ 47.372464] xhci_hcd 0000:00:04.0: 1dbe780 +[ 47.372567] xhci_hcd 0000:00:04.0: 0 +[ 47.372632] xhci_hcd 0000:00:04.0: 2 +[ 47.372720] xhci_hcd 0000:00:04.0: 10c05 +[ 47.372865] xhci_hcd 0000:00:04.0: dump trb: +[ 47.372966] xhci_hcd 0000:00:04.0: 0 +[ 47.373059] xhci_hcd 0000:00:04.0: 0 +[ 47.373153] xhci_hcd 0000:00:04.0: 0 +[ 47.373250] xhci_hcd 0000:00:04.0: 1021 +[ 47.375149] xhci_hcd 0000:00:04.0: dump trb: +[ 47.375257] xhci_hcd 0000:00:04.0: 10100 +[ 47.375328] xhci_hcd 0000:00:04.0: 0 +[ 47.375395] xhci_hcd 0000:00:04.0: 8 +[ 47.375461] xhci_hcd 0000:00:04.0: 840 +[ 47.375536] xhci_hcd 0000:00:04.0: dump trb: +[ 47.375607] xhci_hcd 0000:00:04.0: 0 +[ 47.375681] xhci_hcd 0000:00:04.0: 0 +[ 47.375723] xhci_hcd 0000:00:04.0: 0 +[ 47.375761] xhci_hcd 0000:00:04.0: 11021 +[ 47.376867] xhci_hcd 0000:00:04.0: dump trb: +[ 47.376955] xhci_hcd 0000:00:04.0: 0 +[ 47.377007] xhci_hcd 0000:00:04.0: 0 +[ 47.377058] xhci_hcd 0000:00:04.0: 0 +[ 47.377108] xhci_hcd 0000:00:04.0: 1013801 +[ 47.377578] xhci_hcd 0000:00:04.0: dump trb: +[ 47.377634] xhci_hcd 0000:00:04.0: 1fd1601 +[ 47.377665] xhci_hcd 0000:00:04.0: 0 +[ 47.377704] xhci_hcd 0000:00:04.0: 0 +[ 47.377737] xhci_hcd 0000:00:04.0: 1014001 +[ 47.378634] xhci_hcd 0000:00:04.0: submit interrupt in urb +[ 47.379101] xhci_hcd 0000:00:04.0: interrupt! +[ 47.379360] xhci_hcd 0000:00:04.0: dump trb: +[ 47.379410] xhci_hcd 0000:00:04.0: 1f2fc80 +[ 47.379443] xhci_hcd 0000:00:04.0: 0 +[ 47.379487] xhci_hcd 0000:00:04.0: 10 +[ 47.379536] xhci_hcd 0000:00:04.0: 424 +cat: /dev/video0: Invalid argument +[ 47.390295] xhci_hcd 0000:00:04.0: dump trb: +[ 47.390393] xhci_hcd 0000:00:04.0: 0 +[ 47.390464] xhci_hcd 0000:00:04.0: 0 +[ 47.390527] xhci_hcd 0000:00:04.0: 0 +[ 47.390590] xhci_hcd 0000:00:04.0: 1073c01 +[ 47.394264] cat (56) used greatest stack depth: 12928 bytes left +# [ 49.683537] xhci_hcd 0000:00:04.0: dump trb: +[ 49.683840] xhci_hcd 0000:00:04.0: 0 +[ 49.683988] xhci_hcd 0000:00:04.0: 0 +[ 49.684108] xhci_hcd 0000:00:04.0: 0 +[ 49.684195] xhci_hcd 0000:00:04.0: 1813c01 +qc +/bin/sh: 5: qc: not found +# cat /dev/video1 +cat: /dev/video1: Invalid argument +# ls .d  /dev +autofs loop3 sg0 tty18 tty31 tty45 tty59 usbmon1 +bsg loop4 snapshot tty19 tty32 tty46 tty6 usbmon2 +bus loop5 snd tty2 tty33 tty47 tty60 usbmon3 +console loop6 sr0 tty20 tty34 tty48 tty61 vcs +cpu loop7 tty tty21 tty35 tty49 tty62 vcs1 +cpu_dma_latency mapper tty0 tty22 tty36 tty5 tty63 vcsa +full media0 tty1 tty23 tty37 tty50 tty7 vcsa1 +hpet mem tty10 tty24 tty38 tty51 tty8 vcsu +hwrng null tty11 tty25 tty39 tty52 tty9 vcsu1 +input nvram tty12 tty26 tty4 tty53 ttyS0 vga_arbiter +kmsg port tty13 tty27 tty40 tty54 ttyS1 video0 +loop-control ptmx tty14 tty28 tty41 tty55 ttyS2 video1 +loop0 random tty15 tty29 tty42 tty56 ttyS3 zero +loop1 rfkill tty16 tty3 tty43 tty57 urandom +loop2 rtc0 tty17 tty30 tty44 tty58 usbmon0 +# cat /de v/video1 +cat: /dev/video1: Invalid argument +# +# ll /dev +/bin/sh: 10: ll: not found +# ls -a /de    l /dev +total 4 +drwxr-xr-x 8 root root 2400 Aug 7 13:30 . +drwxr-xr-x 25 root root 4096 Aug 7 13:04 .. +crw-r--r-- 1 root root 10, 235 Aug 7 13:30 autofs +drwxr-xr-x 2 root root 60 Aug 7 13:30 bsg +drwxr-xr-x 3 root root 60 Aug 7 13:30 bus +crw------- 1 root root 5, 1 Aug 7 13:30 console +drwxr-xr-x 3 root root 60 Aug 7 13:30 cpu +crw------- 1 root root 10, 126 Aug 7 13:30 cpu_dma_latency +crw-rw-rw- 1 root root 1, 7 Aug 7 13:30 full +crw------- 1 root root 10, 228 Aug 7 13:30 hpet +crw------- 1 root root 10, 183 Aug 7 13:30 hwrng +drwxr-xr-x 2 root root 160 Aug 7 13:30 input +crw-r--r-- 1 root root 1, 11 Aug 7 13:30 kmsg +crw------- 1 root root 10, 237 Aug 7 13:30 loop-control +brw------- 1 root root 7, 0 Aug 7 13:30 loop0 +brw------- 1 root root 7, 1 Aug 7 13:30 loop1 +brw------- 1 root root 7, 2 Aug 7 13:30 loop2 +brw------- 1 root root 7, 3 Aug 7 13:30 loop3 +brw------- 1 root root 7, 4 Aug 7 13:30 loop4 +brw------- 1 root root 7, 5 Aug 7 13:30 loop5 +brw------- 1 root root 7, 6 Aug 7 13:30 loop6 +brw------- 1 root root 7, 7 Aug 7 13:30 loop7 +drwxr-xr-x 2 root root 60 Aug 7 13:30 mapper +crw------- 1 root root 253, 0 Aug 7 13:30 media0 +crw------- 1 root root 1, 1 Aug 7 13:30 mem +crw-rw-rw- 1 root root 1, 3 Aug 7 13:30 null +crw------- 1 root root 10, 144 Aug 7 13:30 nvram +crw------- 1 root root 1, 4 Aug 7 13:30 port +crw-rw-rw- 1 root root 5, 2 Aug 7 13:30 ptmx +crw-rw-rw- 1 root root 1, 8 Aug 7 13:30 random +crw------- 1 root root 10, 242 Aug 7 13:30 rfkill +crw------- 1 root root 254, 0 Aug 7 13:30 rtc0 +crw------- 1 root root 21, 0 Aug 7 13:30 sg0 +crw------- 1 root root 10, 231 Aug 7 13:30 snapshot +drwxr-xr-x 2 root root 80 Aug 7 13:30 snd +brw------- 1 root root 11, 0 Aug 7 13:30 sr0 +crw-rw-rw- 1 root root 5, 0 Aug 7 13:30 tty +crw------- 1 root root 4, 0 Aug 7 13:30 tty0 +crw------- 1 root root 4, 1 Aug 7 13:30 tty1 +crw------- 1 root root 4, 10 Aug 7 13:30 tty10 +crw------- 1 root root 4, 11 Aug 7 13:30 tty11 +crw------- 1 root root 4, 12 Aug 7 13:30 tty12 +crw------- 1 root root 4, 13 Aug 7 13:30 tty13 +crw------- 1 root root 4, 14 Aug 7 13:30 tty14 +crw------- 1 root root 4, 15 Aug 7 13:30 tty15 +crw------- 1 root root 4, 16 Aug 7 13:30 tty16 +crw------- 1 root root 4, 17 Aug 7 13:30 tty17 +crw------- 1 root root 4, 18 Aug 7 13:30 tty18 +crw------- 1 root root 4, 19 Aug 7 13:30 tty19 +crw------- 1 root root 4, 2 Aug 7 13:30 tty2 +crw------- 1 root root 4, 20 Aug 7 13:30 tty20 +crw------- 1 root root 4, 21 Aug 7 13:30 tty21 +crw------- 1 root root 4, 22 Aug 7 13:30 tty22 +crw------- 1 root root 4, 23 Aug 7 13:30 tty23 +crw------- 1 root root 4, 24 Aug 7 13:30 tty24 +crw------- 1 root root 4, 25 Aug 7 13:30 tty25 +crw------- 1 root root 4, 26 Aug 7 13:30 tty26 +crw------- 1 root root 4, 27 Aug 7 13:30 tty27 +crw------- 1 root root 4, 28 Aug 7 13:30 tty28 +crw------- 1 root root 4, 29 Aug 7 13:30 tty29 +crw------- 1 root root 4, 3 Aug 7 13:30 tty3 +crw------- 1 root root 4, 30 Aug 7 13:30 tty30 +crw------- 1 root root 4, 31 Aug 7 13:30 tty31 +crw------- 1 root root 4, 32 Aug 7 13:30 tty32 +crw------- 1 root root 4, 33 Aug 7 13:30 tty33 +crw------- 1 root root 4, 34 Aug 7 13:30 tty34 +crw------- 1 root root 4, 35 Aug 7 13:30 tty35 +crw------- 1 root root 4, 36 Aug 7 13:30 tty36 +crw------- 1 root root 4, 37 Aug 7 13:30 tty37 +crw------- 1 root root 4, 38 Aug 7 13:30 tty38 +crw------- 1 root root 4, 39 Aug 7 13:30 tty39 +crw------- 1 root root 4, 4 Aug 7 13:30 tty4 +crw------- 1 root root 4, 40 Aug 7 13:30 tty40 +crw------- 1 root root 4, 41 Aug 7 13:30 tty41 +crw------- 1 root root 4, 42 Aug 7 13:30 tty42 +crw------- 1 root root 4, 43 Aug 7 13:30 tty43 +crw------- 1 root root 4, 44 Aug 7 13:30 tty44 +crw------- 1 root root 4, 45 Aug 7 13:30 tty45 +crw------- 1 root root 4, 46 Aug 7 13:30 tty46 +crw------- 1 root root 4, 47 Aug 7 13:30 tty47 +crw------- 1 root root 4, 48 Aug 7 13:30 tty48 +crw------- 1 root root 4, 49 Aug 7 13:30 tty49 +crw------- 1 root root 4, 5 Aug 7 13:30 tty5 +crw------- 1 root root 4, 50 Aug 7 13:30 tty50 +crw------- 1 root root 4, 51 Aug 7 13:30 tty51 +crw------- 1 root root 4, 52 Aug 7 13:30 tty52 +crw------- 1 root root 4, 53 Aug 7 13:30 tty53 +crw------- 1 root root 4, 54 Aug 7 13:30 tty54 +crw------- 1 root root 4, 55 Aug 7 13:30 tty55 +crw------- 1 root root 4, 56 Aug 7 13:30 tty56 +crw------- 1 root root 4, 57 Aug 7 13:30 tty57 +crw------- 1 root root 4, 58 Aug 7 13:30 tty58 +crw------- 1 root root 4, 59 Aug 7 13:30 tty59 +crw------- 1 root root 4, 6 Aug 7 13:30 tty6 +crw------- 1 root root 4, 60 Aug 7 13:30 tty60 +crw------- 1 root root 4, 61 Aug 7 13:30 tty61 +crw------- 1 root root 4, 62 Aug 7 13:30 tty62 +crw------- 1 root root 4, 63 Aug 7 13:30 tty63 +crw------- 1 root root 4, 7 Aug 7 13:30 tty7 +crw------- 1 root root 4, 8 Aug 7 13:30 tty8 +crw------- 1 root root 4, 9 Aug 7 13:30 tty9 +crw------- 1 root root 4, 64 Aug 7 13:30 ttyS0 +crw------- 1 root root 4, 65 Aug 7 13:30 ttyS1 +crw------- 1 root root 4, 66 Aug 7 13:30 ttyS2 +crw------- 1 root root 4, 67 Aug 7 13:30 ttyS3 +crw-rw-rw- 1 root root 1, 9 Aug 7 13:30 urandom +crw------- 1 root root 248, 0 Aug 7 13:30 usbmon0 +crw------- 1 root root 248, 1 Aug 7 13:30 usbmon1 +crw------- 1 root root 248, 2 Aug 7 13:30 usbmon2 +crw------- 1 root root 248, 3 Aug 7 13:30 usbmon3 +crw------- 1 root root 7, 0 Aug 7 13:30 vcs +crw------- 1 root root 7, 1 Aug 7 13:30 vcs1 +crw------- 1 root root 7, 128 Aug 7 13:30 vcsa +crw------- 1 root root 7, 129 Aug 7 13:30 vcsa1 +crw------- 1 root root 7, 64 Aug 7 13:30 vcsu +crw------- 1 root root 7, 65 Aug 7 13:30 vcsu1 +crw------- 1 root root 10, 127 Aug 7 13:30 vga_arbiter +crw------- 1 root root 81, 0 Aug 7 13:30 video0 +crw------- 1 root root 81, 1 Aug 7 13:30 video1 +crw-rw-rw- 1 root root 1, 5 Aug 7 13:30 zero +# ls  cat /dev/video1video1video1             +cat: /dev/video1: Invalid argument +# \ No newline at end of file diff --git a/emulog2.log b/emulog2.log new file mode 100644 index 0000000000..1b50b9bed3 --- /dev/null +++ b/emulog2.log @@ -0,0 +1,1076 @@ +c[?7lSeaBIOS (version rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org) + + +iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+7EFD0D70+7EF30D70 CA00 +Press Ctrl-B to configure iPXE (PCI 00:03.0)... + + + +Booting from ROM..c[?7l[ 0.000000] Linux version 6.10.0 (dbydd@dbyddlaptop) (gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #6 SMP PREEMPT_DYNAMIC Fri Jul 19 10:59:53 HKT 2024 +|| Command line: root=/dev/root ro rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/bin/sh +|| BIOS-provided physical RAM map: +|| BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable +|| BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved +|| BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved +|| BIOS-e820: [mem 0x0000000000100000-0x000000007ffdffff] usable +|| BIOS-e820: [mem 0x000000007ffe0000-0x000000007fffffff] reserved +|| BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved +|| BIOS-e820: [mem 0x000000fd00000000-0x000000ffffffffff] reserved +|| NX (Execute Disable) protection: active +|| APIC: Static calls initialized +|| SMBIOS 2.8 present. +|| DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 +|| DMI: Memory slots populated: 1/1 +|| tsc: Fast TSC calibration using PIT +|| tsc: Detected 2419.220 MHz processor +|| last_pfn = 0x7ffe0 max_arch_pfn = 0x400000000 +|| MTRR map: 4 entries (3 fixed + 1 variable; max 19), built from 8 variable MTRRs +|| x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT +|| found SMP MP-table at [mem 0x000f5460-0x000f546f] +|| ACPI: Early table checksum verification disabled +|| ACPI: RSDP 0x00000000000F5280 000014 (v00 BOCHS ) +|| ACPI: RSDT 0x000000007FFE1CBA 000034 (v01 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: FACP 0x000000007FFE1B6E 000074 (v01 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: DSDT 0x000000007FFE0040 001B2E (v01 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: FACS 0x000000007FFE0000 000040 +|| ACPI: APIC 0x000000007FFE1BE2 000078 (v03 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: HPET 0x000000007FFE1C5A 000038 (v01 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: WAET 0x000000007FFE1C92 000028 (v01 BOCHS BXPC 00000001 BXPC 00000001) +|| ACPI: Reserving FACP table memory at [mem 0x7ffe1b6e-0x7ffe1be1] +|| ACPI: Reserving DSDT table memory at [mem 0x7ffe0040-0x7ffe1b6d] +|| ACPI: Reserving FACS table memory at [mem 0x7ffe0000-0x7ffe003f] +|| ACPI: Reserving APIC table memory at [mem 0x7ffe1be2-0x7ffe1c59] +|| ACPI: Reserving HPET table memory at [mem 0x7ffe1c5a-0x7ffe1c91] +|| ACPI: Reserving WAET table memory at [mem 0x7ffe1c92-0x7ffe1cb9] +|| No NUMA configuration found +|| Faking a node at [mem 0x0000000000000000-0x000000007ffdffff] +|| NODE_DATA(0) allocated [mem 0x7ffdc000-0x7ffdffff] +|| Zone ranges: +|| DMA [mem 0x0000000000001000-0x0000000000ffffff] +|| DMA32 [mem 0x0000000001000000-0x000000007ffdffff] +|| Normal empty +|| Movable zone start for each node +|| Early memory node ranges +|| node 0: [mem 0x0000000000001000-0x000000000009efff] +|| node 0: [mem 0x0000000000100000-0x000000007ffdffff] +|| Initmem setup node 0 [mem 0x0000000000001000-0x000000007ffdffff] +|| On node 0, zone DMA: 1 pages in unavailable ranges +|| On node 0, zone DMA: 97 pages in unavailable ranges +|| On node 0, zone DMA32: 32 pages in unavailable ranges +|| ACPI: PM-Timer IO Port: 0x608 +|| ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1]) +|| IOAPIC[0]: apic_id 0, version 32, address 0xfec00000, GSI 0-23 +|| ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl) +|| ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level) +|| ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level) +|| ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level) +|| ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level) +|| ACPI: Using ACPI (MADT) for SMP configuration information +|| ACPI: HPET id: 0x8086a201 base: 0xfed00000 +|| CPU topo: Max. logical packages: 1 +|| CPU topo: Max. logical dies: 1 +|| CPU topo: Max. dies per package: 1 +|| CPU topo: Max. threads per core: 1 +|| CPU topo: Num. cores per package: 1 +|| CPU topo: Num. threads per package: 1 +|| CPU topo: Allowing 1 present CPUs plus 0 hotplug CPUs +|| PM: hibernation: Registered nosave memory: [mem 0x00000000-0x00000fff] +|| PM: hibernation: Registered nosave memory: [mem 0x0009f000-0x0009ffff] +|| PM: hibernation: Registered nosave memory: [mem 0x000a0000-0x000effff] +|| PM: hibernation: Registered nosave memory: [mem 0x000f0000-0x000fffff] +|| [mem 0x80000000-0xfffbffff] available for PCI devices +|| Booting paravirtualized kernel on bare hardware +|| clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1910969940391419 ns +|| setup_percpu: NR_CPUS:64 nr_cpumask_bits:1 nr_cpu_ids:1 nr_node_ids:1 +|| percpu: Embedded 58 pages/cpu s199384 r8192 d29992 u2097152 +|| Kernel command line: root=/dev/root ro rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/bin/sh +|| Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear) +|| Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear) +|| Fallback order for Node 0: 0 +|| Built 1 zonelists, mobility grouping on. Total pages: 524158 +|| Policy zone: DMA32 +|| mem auto-init: stack:off, heap alloc:off, heap free:off +|| Memory: 2018576K/2096632K available (18432K kernel code, 3068K rwdata, 7568K rodata, 2828K init, 2660K bss, 77796K reserved, 0K cma-reserved) +|| SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 +|| Dynamic Preempt: voluntary +|| rcu: Preemptible hierarchical RCU implementation. +|| rcu: RCU event tracing is enabled. +|| rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1. +|| Trampoline variant of Tasks RCU enabled. +|| Tracing variant of Tasks RCU enabled. +|| rcu: RCU calculated value of scheduler-enlistment delay is 100 jiffies. +|| rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 +|| RCU Tasks: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1. +|| RCU Tasks Trace: Setting shift to 0 and lim to 1 rcu_task_cb_adjust=1. +|| NR_IRQS: 4352, nr_irqs: 256, preallocated irqs: 16 +|| rcu: srcu_init: Setting srcu_struct sizes based on contention. +|| Console: colour VGA+ 80x25 +|| printk: legacy console [ttyS0] enabled +|| ACPI: Core revision 20240322 +|| clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns +|| APIC: Switch to symmetric I/O mode setup +|| ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 +|| clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x22df23fdaa4, max_idle_ns: 440795278047 ns +|| Calibrating delay loop (skipped), value calculated using timer frequency.. 4838.44 BogoMIPS (lpj=2419220) +|| Last level iTLB entries: 4KB 512, 2MB 255, 4MB 127 +|| Last level dTLB entries: 4KB 512, 2MB 255, 4MB 127, 1GB 0 +|| Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization +|| Spectre V2 : Mitigation: Retpolines +|| Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch +|| Spectre V2 : Spectre v2 / SpectreRSB : Filling RSB on VMEXIT +|| x86/fpu: x87 FPU will use FXSAVE +|| Freeing SMP alternatives memory: 52K +|| pid_max: default: 32768 minimum: 301 +|| LSM: initializing lsm=capability,selinux,bpf +|| SELinux: Initializing. +|| LSM support for eBPF active +|| Mount-cache hash table entries: 4096 (order: 3, 32768 bytes, linear) +|| Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes, linear) +|| smpboot: CPU0: AMD QEMU Virtual CPU version 2.5+ (family: 0xf, model: 0x6b, stepping: 0x1) +|| Performance Events: PMU not available due to virtualization, using software events only. +|| signal: max sigframe size: 1440 +|| rcu: Hierarchical SRCU implementation. +|| rcu: Max phase no-delay instances is 400. +|| smp: Bringing up secondary CPUs ... +|| smp: Brought up 1 node, 1 CPU +|| smpboot: Total of 1 processors activated (4838.44 BogoMIPS) +|| devtmpfs: initialized +|| clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns +|| futex hash table entries: 256 (order: 2, 16384 bytes, linear) +|| PM: RTC time: 05:40:41, date: 2024-07-19 +|| NET: Registered PF_NETLINK/PF_ROUTE protocol family +|| audit: initializing netlink subsys (disabled) +|| audit: type=2000 audit(1721367640.528:1): state=initialized audit_enabled=0 res=1 +|| thermal_sys: Registered thermal governor 'step_wise' +|| thermal_sys: Registered thermal governor 'user_space' +|| cpuidle: using governor menu +|| PCI: Using configuration type 1 for base access +|| kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible. +|| HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages +|| HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page +|| Demotion targets for Node 0: null +|| ACPI: Added _OSI(Module Device) +|| ACPI: Added _OSI(Processor Device) +|| ACPI: Added _OSI(3.0 _SCP Extensions) +|| ACPI: Added _OSI(Processor Aggregator Device) +|| ACPI: 1 ACPI AML tables successfully acquired and loaded +|| ACPI: Interpreter enabled +|| ACPI: PM: (supports S0 S3 S4 S5) +|| ACPI: Using IOAPIC for interrupt routing +|| PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug +|| PCI: Using E820 reservations for host bridge windows +|| ACPI: Enabled 2 GPEs in block 00 to 0F +|| ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff]) +|| acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI HPX-Type3] +|| acpi PNP0A03:00: _OSC: not requesting OS control; OS requires [ExtendedConfig ASPM ClockPM MSI] +|| acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended configuration space under this bridge +|| PCI host bridge to bus 0000:00 +|| pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window] +|| pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window] +|| pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window] +|| pci_bus 0000:00: root bus resource [mem 0x80000000-0xfebfffff window] +|| pci_bus 0000:00: root bus resource [mem 0x100000000-0x17fffffff window] +|| pci_bus 0000:00: root bus resource [bus 00-ff] +|| pci 0000:00:00.0: [8086:1237] type 00 class 0x060000 conventional PCI endpoint +|| pci 0000:00:01.0: [8086:7000] type 00 class 0x060100 conventional PCI endpoint +|| pci 0000:00:01.1: [8086:7010] type 00 class 0x010180 conventional PCI endpoint +|| pci 0000:00:01.1: BAR 4 [io 0xc0a0-0xc0af] +|| pci 0000:00:01.1: BAR 0 [io 0x01f0-0x01f7]: legacy IDE quirk +|| pci 0000:00:01.1: BAR 1 [io 0x03f6]: legacy IDE quirk +|| pci 0000:00:01.1: BAR 2 [io 0x0170-0x0177]: legacy IDE quirk +|| pci 0000:00:01.1: BAR 3 [io 0x0376]: legacy IDE quirk +|| pci 0000:00:01.2: [8086:7020] type 00 class 0x0c0300 conventional PCI endpoint +|| pci 0000:00:01.2: BAR 4 [io 0xc080-0xc09f] +|| pci 0000:00:01.3: [8086:7113] type 00 class 0x068000 conventional PCI endpoint +|| pci 0000:00:01.3: quirk: [io 0x0600-0x063f] claimed by PIIX4 ACPI +|| pci 0000:00:01.3: quirk: [io 0x0700-0x070f] claimed by PIIX4 SMB +|| pci 0000:00:02.0: [1234:1111] type 00 class 0x030000 conventional PCI endpoint +|| pci 0000:00:02.0: BAR 0 [mem 0xfd000000-0xfdffffff pref] +|| pci 0000:00:02.0: BAR 2 [mem 0xfebf4000-0xfebf4fff] +|| pci 0000:00:02.0: ROM [mem 0xfebe0000-0xfebeffff pref] +|| pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff] +|| pci 0000:00:03.0: [8086:100e] type 00 class 0x020000 conventional PCI endpoint +|| pci 0000:00:03.0: BAR 0 [mem 0xfebc0000-0xfebdffff] +|| pci 0000:00:03.0: BAR 1 [io 0xc000-0xc03f] +|| pci 0000:00:03.0: ROM [mem 0xfeb80000-0xfebbffff pref] +|| pci 0000:00:04.0: [1b36:000d] type 00 class 0x0c0330 conventional PCI endpoint +|| pci 0000:00:04.0: BAR 0 [mem 0xfebf0000-0xfebf3fff 64bit] +|| pci 0000:00:05.0: [1af4:1009] type 00 class 0x000200 conventional PCI endpoint +|| pci 0000:00:05.0: BAR 0 [io 0xc040-0xc07f] +|| pci 0000:00:05.0: BAR 1 [mem 0xfebf5000-0xfebf5fff] +|| pci 0000:00:05.0: BAR 4 [mem 0xfe000000-0xfe003fff 64bit pref] +|| ACPI: PCI: Interrupt link LNKA configured for IRQ 10 +|| ACPI: PCI: Interrupt link LNKB configured for IRQ 10 +|| ACPI: PCI: Interrupt link LNKC configured for IRQ 11 +|| ACPI: PCI: Interrupt link LNKD configured for IRQ 11 +|| ACPI: PCI: Interrupt link LNKS configured for IRQ 9 +|| iommu: Default domain type: Translated +|| iommu: DMA domain TLB invalidation policy: lazy mode +|| SCSI subsystem initialized +|| ACPI: bus type USB registered +|| usbcore: registered new interface driver usbfs +|| usbcore: registered new interface driver hub +|| usbcore: registered new device driver usb +|| pps_core: LinuxPPS API ver. 1 registered +|| pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti +|| PTP clock support registered +|| Advanced Linux Sound Architecture Driver Initialized. +|| NetLabel: Initializing +|| NetLabel: domain hash size = 128 +|| NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO +|| NetLabel: unlabeled traffic allowed by default +|| PCI: Using ACPI for IRQ routing +|| pci 0000:00:02.0: vgaarb: setting as boot VGA device +|| pci 0000:00:02.0: vgaarb: bridge control possible +|| pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none +|| vgaarb: loaded +|| hpet: 3 channels of 0 reserved for per-cpu timers +|| hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0 +|| hpet0: 3 comparators, 64-bit 100.000000 MHz counter +|| clocksource: Switched to clocksource tsc-early +|| VFS: Disk quotas dquot_6.6.0 +|| VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) +|| pnp: PnP ACPI init +|| pnp: PnP ACPI: found 6 devices +|| clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns +|| NET: Registered PF_INET protocol family +|| IP idents hash table entries: 32768 (order: 6, 262144 bytes, linear) +|| tcp_listen_portaddr_hash hash table entries: 1024 (order: 2, 16384 bytes, linear) +|| Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear) +|| TCP established hash table entries: 16384 (order: 5, 131072 bytes, linear) +|| TCP bind hash table entries: 16384 (order: 7, 524288 bytes, linear) +|| TCP: Hash tables configured (established 16384 bind 16384) +|| UDP hash table entries: 1024 (order: 3, 32768 bytes, linear) +|| UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes, linear) +|| NET: Registered PF_UNIX/PF_LOCAL protocol family +|| RPC: Registered named UNIX socket transport module. +|| RPC: Registered udp transport module. +|| RPC: Registered tcp transport module. +|| RPC: Registered tcp-with-tls transport module. +|| RPC: Registered tcp NFSv4.1 backchannel transport module. +|| pci_bus 0000:00: resource 4 [io 0x0000-0x0cf7 window] +|| pci_bus 0000:00: resource 5 [io 0x0d00-0xffff window] +|| pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window] +|| pci_bus 0000:00: resource 7 [mem 0x80000000-0xfebfffff window] +|| pci_bus 0000:00: resource 8 [mem 0x100000000-0x17fffffff window] +|| pci 0000:00:01.0: PIIX3: Enabling Passive Release +|| pci 0000:00:00.0: Limiting direct PCI/PCI transfers +|| ACPI: \_SB_.LNKD: Enabled at IRQ 11 +|| pci 0000:00:01.2: quirk_usb_early_handoff+0x0/0x7a0 took 370455 usecs +|| pci 0000:00:04.0: quirk_usb_early_handoff+0x0/0x7a0 took 210470 usecs +|| PCI: CLS 0 bytes, default 64 +|| Initialise system trusted keyrings +|| workingset: timestamp_bits=56 max_order=19 bucket_order=0 +|| NFS: Registering the id_resolver key type +|| Key type id_resolver registered +|| Key type id_legacy registered +|| 9p: Installing v9fs 9p2000 file system support +|| Key type asymmetric registered +|| Asymmetric key parser 'x509' registered +|| Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251) +|| io scheduler mq-deadline registered +|| io scheduler kyber registered +|| input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 +|| ACPI: button: Power Button [PWRF] +|| ACPI: \_SB_.LNKA: Enabled at IRQ 10 +|| Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled +|| 00:04: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A +|| Non-volatile memory driver v1.3 +|| Linux agpgart interface v0.103 +|| ACPI: bus type drm_connector registered +|| loop: module loaded +|| scsi host0: ata_piix +|| scsi host1: ata_piix +|| ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc0a0 irq 14 lpm-pol 0 +|| ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc0a8 irq 15 lpm-pol 0 +|| e100: Intel(R) PRO/100 Network Driver +|| e100: Copyright(c) 1999-2006 Intel Corporation +|| e1000: Intel(R) PRO/1000 Network Driver +|| e1000: Copyright (c) 1999-2006 Intel Corporation. +|| ACPI: \_SB_.LNKC: Enabled at IRQ 11 +|| ata2: found unknown device (class 0) +|| ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100 +|| scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5 +|| sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray +|| cdrom: Uniform CD-ROM driver Revision: 3.20 +|| sr 1:0:0:0: Attached scsi generic sg0 type 5 +|| e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 52:54:00:12:34:56 +|| e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection +|| e1000e: Intel(R) PRO/1000 Network Driver +|| e1000e: Copyright(c) 1999 - 2015 Intel Corporation. +|| sky2: driver version 1.30 +|| uhci_hcd 0000:00:01.2: UHCI Host Controller +|| uhci_hcd 0000:00:01.2: new USB bus registered, assigned bus number 1 +|| uhci_hcd 0000:00:01.2: detected 2 ports +|| uhci_hcd 0000:00:01.2: irq 11, io port 0x0000c080 +|| usb usb1: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 6.10 +|| usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +|| usb usb1: Product: UHCI Host Controller +|| usb usb1: Manufacturer: Linux 6.10.0 uhci_hcd +|| usb usb1: SerialNumber: 0000:00:01.2 +|| hub 1-0:1.0: USB hub found +|| hub 1-0:1.0: 2 ports detected +|| xhci_hcd 0000:00:04.0: xHCI Host Controller +|| xhci_hcd 0000:00:04.0: new USB bus registered, assigned bus number 2 +|| xhci_hcd 0000:00:04.0: hcc params 0x00087001 hci version 0x100 quirks 0x0000000000000010 +|| xhci_hcd 0000:00:04.0: xHCI Host Controller +|| xhci_hcd 0000:00:04.0: new USB bus registered, assigned bus number 3 +|| xhci_hcd 0000:00:04.0: Host supports USB 3.0 SuperSpeed +|| usb usb2: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.10 +|| usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +|| usb usb2: Product: xHCI Host Controller +|| usb usb2: Manufacturer: Linux 6.10.0 xhci-hcd +|| usb usb2: SerialNumber: 0000:00:04.0 +|| hub 2-0:1.0: USB hub found +|| hub 2-0:1.0: 4 ports detected +|| usb usb3: We don't know the algorithms for LPM for this host, disabling LPM. +|| usb usb3: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.10 +|| usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +|| usb usb3: Product: xHCI Host Controller +|| usb usb3: Manufacturer: Linux 6.10.0 xhci-hcd +|| usb usb3: SerialNumber: 0000:00:04.0 +|| hub 3-0:1.0: USB hub found +|| hub 3-0:1.0: 4 ports detected +|| usbcore: registered new interface driver usblp +|| usbcore: registered new interface driver cdc_wdm +|| usbcore: registered new interface driver usbtmc +|| usbcore: registered new interface driver usb-storage +|| usbcore: registered new interface driver usbtest +|| i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12 +|| serio: i8042 KBD port at 0x60,0x64 irq 1 +|| serio: i8042 AUX port at 0x60,0x64 irq 12 +|| mousedev: PS/2 mouse device common for all mice +|| usbcore: registered new interface driver synaptics_usb +|| rtc_cmos 00:05: RTC can wake from S4 +|| input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1 +|| rtc_cmos 00:05: registered as rtc0 +|| rtc_cmos 00:05: alarms up to one day, y3k, 242 bytes nvram, hpet irqs +|| fail to initialize ptp_kvm +|| device-mapper: ioctl: 4.48.0-ioctl (2023-03-01) initialised: dm-devel@lists.linux.dev +|| amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled +|| hid: raw HID events driver (C) Jiri Kosina +|| usbcore: registered new interface driver usbhid +|| usbhid: USB HID core driver +|| Initializing XFRM netlink socket +|| NET: Registered PF_INET6 protocol family +|| Segment Routing with IPv6 +|| In-situ OAM (IOAM) with IPv6 +|| sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver +|| NET: Registered PF_PACKET protocol family +|| 9pnet: Installing 9P2000 support +|| Key type dns_resolver registered +|| IPI shorthand broadcast: enabled +|| sched_clock: Marking stable (2580181518, 24717809)->(2610917431, -6018104) +|| registered taskstats version 1 +|| Loading compiled-in X.509 certificates +|| Demotion targets for Node 0: null +|| PM: Magic number: 0:96:669 +|| printk: legacy console [netcon0] enabled +|| netconsole: network logging started +|| cfg80211: Loading compiled-in X.509 certificates for regulatory database +|| kworker/u4:0 (48) used greatest stack depth: 14512 bytes left +|| Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7' +|| Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600' +|| ALSA device list: +|| No soundcards found. +|| platform regulatory.0: Direct firmware load for regulatory.db failed with error -2 +|| cfg80211: failed to load regulatory.db +|| tsc: Refined TSC clocksource calibration: 2419.185 MHz +|| clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x22df0309918, max_idle_ns: 440795278046 ns +|| clocksource: Switched to clocksource tsc +|| input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3 +|| md: Waiting for all devices to be available before autodetect +|| md: If you don't use raid, use raid=noautodetect +|| md: Autodetecting RAID arrays. +|| md: autorun ... +|| md: ... autorun DONE. +|| VFS: Mounted root (9p filesystem) readonly on device 0:19. +|| devtmpfs: mounted +|| Freeing unused kernel image (initmem) memory: 2828K +|| Write protecting the kernel read-only data: 26624k +|| Freeing unused kernel image (rodata/data gap) memory: 624K +|| x86/mm: Checked W+X mappings: passed, no W+X pages found. +|| Run /bin/sh as init process +/bin/sh: 0: can't access tty; job control turned off +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 2401 +|| usb 2-2: new full-speed USB device number 2 using xhci_hcd +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc7000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1002e01 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1000680 +|| xhci_hcd 0000:00:04.0: 400000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f9ed40 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 40 +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 //setup +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1004401 //reset device +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc7000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1002c01//address device +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1000680 +|| xhci_hcd 0000:00:04.0: 120000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840//setup +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f23a00 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 12 +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 6000680 +|| xhci_hcd 0000:00:04.0: a0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f2ab20 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: a +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1013801 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc8091 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1014001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 6000680 +|| xhci_hcd 0000:00:04.0: a0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f2ab20 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: a +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1013801 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc80c1 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1014001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 6000680 +|| xhci_hcd 0000:00:04.0: a0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f2ab20 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: a +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1013801 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc80f1 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1014001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 2000680 +|| xhci_hcd 0000:00:04.0: 90000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f2ab20 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 9 +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 2000680 +|| xhci_hcd 0000:00:04.0: 3b0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f9ed80 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 3b +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3000680 +|| xhci_hcd 0000:00:04.0: ff0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fba400 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3020680 +|| xhci_hcd 0000:00:04.0: ff0409 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fba400 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3010680 +|| xhci_hcd 0000:00:04.0: ff0409 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fba400 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3030680 +|| xhci_hcd 0000:00:04.0: ff0409 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fba400 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| usb 2-2: New USB device found, idVendor=3151, idProduct=3020, bcdDevice= 0.02 +|| usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +|| usb 2-2: Product: Wireless Device +|| usb 2-2: Manufacturer: YICHIP +|| usb 2-2: SerialNumber: b120300001 +|| xhci_hcd 0000:00:04.0: slot ctx================================================================= +|| xhci_hcd 0000:00:04.0: slot_ctx:devinfo: 28100000 +|| xhci_hcd 0000:00:04.0: slot_ctx:devinfo2: 60000 +|| xhci_hcd 0000:00:04.0: slot_ctx:ttinfo: 0 +|| xhci_hcd 0000:00:04.0: slot_ctx:dev_state: 0 +|| xhci_hcd 0000:00:04.0: ctrl ctx================================================================= +|| xhci_hcd 0000:00:04.0: ctrl_ctx:add_flags: 29 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:drop_flags: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 0: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 1: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 2: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 3: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 4: 0 +|| xhci_hcd 0000:00:04.0: ctrl_ctx:rsvd 5: 0 +|| xhci_hcd 0000:00:04.0: endpoint 0================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 1fc8031 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 400026 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 1fc8031 +|| xhci_hcd 0000:00:04.0: endpoint 1================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 2================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 1fcc001 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 40003e +|| xhci_hcd 0000:00:04.0: ep_info1_32: 40000 +|| xhci_hcd 0000:00:04.0: tx_info_32: 400040 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 1fcc001 +|| xhci_hcd 0000:00:04.0: endpoint 3================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 4================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 1fce001 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 40003e +|| xhci_hcd 0000:00:04.0: ep_info1_32: 40000 +|| xhci_hcd 0000:00:04.0: tx_info_32: 400040 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 1fce001 +|| xhci_hcd 0000:00:04.0: endpoint 5================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 6================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 7================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 8================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 9================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 10================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 11================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 12================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 13================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 14================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 15================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 16================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 17================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 18================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 19================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 20================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 21================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 22================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 23================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 24================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 25================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 26================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 27================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 28================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 29================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 30================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: endpoint 31================================================================= +|| xhci_hcd 0000:00:04.0: deque_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info2_32: 0 +|| xhci_hcd 0000:00:04.0: ep_info1_32: 0 +|| xhci_hcd 0000:00:04.0: tx_info_32: 0 +|| xhci_hcd 0000:00:04.0: deque_ptr_64: 0 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fc7000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1003001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1033c01 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd1000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1003001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1053c01 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd1000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1003001 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 10900 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 11021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3030680 +|| xhci_hcd 0000:00:04.0: ff0409 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fba500 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: a21 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 11021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 22000681 +|| xhci_hcd 0000:00:04.0: 3f0000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd0280 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 3f +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 2000921 +|| xhci_hcd 0000:00:04.0: 10000 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 20840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3100 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1 +|| xhci_hcd 0000:00:04.0: c01 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 11021 +|| input: YICHIP Wireless Device as /devices/pci0000:00/0000:00:04.0/usb2/2-2/2-2:1.0/0003:3151:3020.0001/input/input4 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3000 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 424 +|| hid-generic 0003:3151:3020.0001: input,hidraw0: USB HID v2.00 Keyboard [YICHIP Wireless Device] on usb-0000:00:04.0-2/input0 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 3030680 +|| xhci_hcd 0000:00:04.0: ff0409 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd9100 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: ff +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: a21 +|| xhci_hcd 0000:00:04.0: 1 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 11021 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 22000681 +|| xhci_hcd 0000:00:04.0: a30001 +|| xhci_hcd 0000:00:04.0: 8 +|| xhci_hcd 0000:00:04.0: 30840 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1f9de40 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: a3 +|| xhci_hcd 0000:00:04.0: 10c05 +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 1021 +|| input: YICHIP Wireless Device Mouse as /devices/pci0000:00/0000:00:04.0/usb2/2-2/2-2:1.1/0003:3151:3020.0002/input/input5 +|| input: YICHIP Wireless Device System Control as /devices/pci0000:00/0000:00:04.0/usb2/2-2/2-2:1.1/0003:3151:3020.0002/input/input6 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| input: YICHIP Wireless Device Consumer Control as /devices/pci0000:00/0000:00:04.0/usb2/2-2/2-2:1.1/0003:3151:3020.0002/input/input7 +|| hid-generic 0003:3151:3020.0002: input,hiddev96,hidraw1: USB HID v2.00 Mouse [YICHIP Wireless Device] on usb-0000:00:04.0-2/input1 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 +|| xhci_hcd 0000:00:04.0: submit interrupt in urb +|| xhci_hcd 0000:00:04.0: interrupt! +|| xhci_hcd 0000:00:04.0: dump trb: +|| xhci_hcd 0000:00:04.0: 1fd3180 +|| xhci_hcd 0000:00:04.0: 0 +|| xhci_hcd 0000:00:04.0: 20 +|| xhci_hcd 0000:00:04.0: 424 diff --git a/modules/axalloc/Cargo.toml b/modules/axalloc/Cargo.toml index 40eedf404f..5988fdc925 100644 --- a/modules/axalloc/Cargo.toml +++ b/modules/axalloc/Cargo.toml @@ -22,3 +22,4 @@ spinlock = { path = "../../crates/spinlock" } memory_addr = { path = "../../crates/memory_addr" } allocator = { path = "../../crates/allocator", features = ["bitmap"] } axerrno = { path = "../../crates/axerrno" } +lazy_static = {version="1.4", features=["spin_no_std"]} \ No newline at end of file diff --git a/modules/axalloc/src/lib.rs b/modules/axalloc/src/lib.rs index 096ce95ae7..9314e96617 100644 --- a/modules/axalloc/src/lib.rs +++ b/modules/axalloc/src/lib.rs @@ -6,19 +6,24 @@ //! be registered as the standard library’s default allocator. #![no_std] +#![feature(allocator_api)] #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; + extern crate alloc; mod page; +use alloc::sync::Arc; use allocator::{AllocResult, BaseAllocator, BitmapPageAllocator, ByteAllocator, PageAllocator}; -use core::alloc::{GlobalAlloc, Layout}; -use core::ptr::NonNull; +use core::alloc::{Allocator, GlobalAlloc, Layout}; +use core::ptr::{slice_from_raw_parts_mut, NonNull}; use spinlock::SpinNoIrq; -const PAGE_SIZE: usize = 0x1000; +pub const PAGE_SIZE: usize = 0x1000; const MIN_HEAP_SIZE: usize = 0x8000; // 32 K pub use page::GlobalPage; @@ -45,16 +50,16 @@ cfg_if::cfg_if! { /// /// [`TlsfByteAllocator`]: allocator::TlsfByteAllocator pub struct GlobalAllocator { - balloc: SpinNoIrq, - palloc: SpinNoIrq>, + balloc_free: SpinNoIrq, + palloc_free: SpinNoIrq>, } impl GlobalAllocator { /// Creates an empty [`GlobalAllocator`]. pub const fn new() -> Self { Self { - balloc: SpinNoIrq::new(DefaultByteAllocator::new()), - palloc: SpinNoIrq::new(BitmapPageAllocator::new()), + balloc_free: SpinNoIrq::new(DefaultByteAllocator::new()), + palloc_free: SpinNoIrq::new(BitmapPageAllocator::new()), } } @@ -76,21 +81,24 @@ impl GlobalAllocator { /// It firstly adds the whole region to the page allocator, then allocates /// a small region (32 KB) to initialize the byte allocator. Therefore, /// the given region must be larger than 32 KB. - pub fn init(&self, start_vaddr: usize, size: usize) { - assert!(size > MIN_HEAP_SIZE); - let init_heap_size = MIN_HEAP_SIZE; - self.palloc.lock().init(start_vaddr, size); - let heap_ptr = self - .alloc_pages(init_heap_size / PAGE_SIZE, PAGE_SIZE) - .unwrap(); - self.balloc.lock().init(heap_ptr, init_heap_size); + /// added nocache allocator-2024.1.23 + pub fn init(&self, (free_base, free_size): (usize, usize)) { + { + assert!(free_size > MIN_HEAP_SIZE); + let init_heap_size = MIN_HEAP_SIZE; + self.palloc_free.lock().init(free_base, free_size); + let heap_ptr = self + .alloc_pages(init_heap_size / PAGE_SIZE, PAGE_SIZE) + .unwrap(); + self.balloc_free.lock().init(heap_ptr, init_heap_size); + } } /// Add the given region to the allocator. /// /// It will add the whole region to the byte allocator. - pub fn add_memory(&self, start_vaddr: usize, size: usize) -> AllocResult { - self.balloc.lock().add_memory(start_vaddr, size) + pub fn add_free_memory(&self, start_vaddr: usize, size: usize) -> AllocResult { + self.balloc_free.lock().add_memory(start_vaddr, size) } /// Allocate arbitrary number of bytes. Returns the left bound of the @@ -104,7 +112,7 @@ impl GlobalAllocator { /// aligned to it. pub fn alloc(&self, layout: Layout) -> AllocResult> { // simple two-level allocator: if no heap memory, allocate from the page allocator. - let mut balloc = self.balloc.lock(); + let mut balloc = self.balloc_free.lock(); loop { if let Ok(ptr) = balloc.alloc(layout) { return Ok(ptr); @@ -133,7 +141,7 @@ impl GlobalAllocator { /// /// [`alloc`]: GlobalAllocator::alloc pub fn dealloc(&self, pos: NonNull, layout: Layout) { - self.balloc.lock().dealloc(pos, layout) + self.balloc_free.lock().dealloc(pos, layout) } /// Allocates contiguous pages. @@ -143,7 +151,7 @@ impl GlobalAllocator { /// `align_pow2` must be a power of 2, and the returned region bound will be /// aligned to it. pub fn alloc_pages(&self, num_pages: usize, align_pow2: usize) -> AllocResult { - self.palloc.lock().alloc_pages(num_pages, align_pow2) + self.palloc_free.lock().alloc_pages(num_pages, align_pow2) } /// Gives back the allocated pages starts from `pos` to the page allocator. @@ -154,27 +162,27 @@ impl GlobalAllocator { /// /// [`alloc_pages`]: GlobalAllocator::alloc_pages pub fn dealloc_pages(&self, pos: usize, num_pages: usize) { - self.palloc.lock().dealloc_pages(pos, num_pages) + self.palloc_free.lock().dealloc_pages(pos, num_pages) } /// Returns the number of allocated bytes in the byte allocator. pub fn used_bytes(&self) -> usize { - self.balloc.lock().used_bytes() + self.balloc_free.lock().used_bytes() } /// Returns the number of available bytes in the byte allocator. pub fn available_bytes(&self) -> usize { - self.balloc.lock().available_bytes() + self.balloc_free.lock().available_bytes() } /// Returns the number of allocated pages in the page allocator. pub fn used_pages(&self) -> usize { - self.palloc.lock().used_pages() + self.palloc_free.lock().used_pages() } /// Returns the number of available pages in the page allocator. pub fn available_pages(&self) -> usize { - self.palloc.lock().available_pages() + self.palloc_free.lock().available_pages() } } @@ -199,6 +207,70 @@ static GLOBAL_ALLOCATOR: GlobalAllocator = GlobalAllocator::new(); pub fn global_allocator() -> &'static GlobalAllocator { &GLOBAL_ALLOCATOR } +lazy_static! { + static ref GLOBAL_NO_CACHE_ALLOCATOR: GlobalNoCacheAllocator = GlobalNoCacheAllocator::new(); +} +// static GLOBAL_NO_CACHE_ALLOCATOR: SyncUnsafeCell< GlobalNoCacheAllocator> = LazyCell::new(|| GlobalNoCacheAllocator::new()); + +/// Returns the reference to the global allocator. +pub fn global_no_cache_allocator() -> GlobalNoCacheAllocator { + GLOBAL_NO_CACHE_ALLOCATOR.clone() +} + +#[derive(Clone)] +pub struct GlobalNoCacheAllocator { + balloc: Arc>, +} + +impl GlobalNoCacheAllocator { + /// Creates an empty [`GlobalAllocator`]. + pub fn new() -> Self { + Self { + balloc: Arc::new(SpinNoIrq::new(DefaultByteAllocator::new())), + } + } + /// Add the given region to the allocator. + /// + /// It will add the whole region to the byte allocator. + pub fn add_memory(&self, start_vaddr: usize, size: usize) -> AllocResult { + let mut g = self.balloc.lock(); + if g.total_bytes() == 0 { + return Err(allocator::AllocError::NoMemory); + } + g.add_memory(start_vaddr, size) + } + /// Initializes the allocator with the given region. + /// + /// It firstly adds the whole region to the page allocator, then allocates + /// a small region (32 KB) to initialize the byte allocator. Therefore, + /// the given region must be larger than 32 KB. + /// added nocache allocator-2024.1.23 + pub fn init(&self, (nocache_base, nocache_size): (usize, usize)) { + if nocache_size > 0 { + self.balloc.lock().init(nocache_base, nocache_size); + } + } +} + +unsafe impl Allocator for GlobalNoCacheAllocator { + fn allocate(&self, layout: Layout) -> Result, core::alloc::AllocError> { + let mut balloc = self.balloc.lock(); + let data = balloc.alloc(layout).map_err(|e| { + debug!("nocache allocator alloc error! {:?}", e); + core::alloc::AllocError + })?; + unsafe { + let ptr = data.as_ptr(); + let data = &mut *slice_from_raw_parts_mut(ptr, layout.size()); + let data = NonNull::from(data); + Ok(data) + } + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + self.balloc.lock().dealloc(ptr, layout) + } +} /// Initializes the global allocator with the given memory region. /// @@ -208,26 +280,41 @@ pub fn global_allocator() -> &'static GlobalAllocator { /// valid. /// /// This function should be called only once, and before any allocation. -pub fn global_init(start_vaddr: usize, size: usize) { +pub fn global_init(free: (usize, usize)) { debug!( - "initialize global allocator at: [{:#x}, {:#x})", - start_vaddr, - start_vaddr + size + "initialize global allocator at: free-[{:#x}, {:#x})", + free.0, + free.0 + free.1, ); - GLOBAL_ALLOCATOR.init(start_vaddr, size); + GLOBAL_ALLOCATOR.init(free); +} +/// Initializes the global allocator with the given memory region. +/// +/// Note that the memory region bounds are just numbers, and the allocator +/// does not actually access the region. Users should ensure that the region +/// is valid and not being used by others, so that the allocated memory is also +/// valid. +/// +/// This function should be called only once, and before any allocation. +pub fn global_nocache_init(nocache: (usize, usize)) { + debug!( + "initialize global allocator at: nocache-[{:#x},{:#x})", + nocache.0, + nocache.0 + nocache.1 + ); + GLOBAL_NO_CACHE_ALLOCATOR.init(nocache) } - /// Add the given memory region to the global allocator. /// /// Users should ensure that the region is valid and not being used by others, /// so that the allocated memory is also valid. /// /// It's similar to [`global_init`], but can be called multiple times. -pub fn global_add_memory(start_vaddr: usize, size: usize) -> AllocResult { +pub fn global_add_free_memory(start_vaddr: usize, size: usize) -> AllocResult { debug!( "add a memory region to global allocator: [{:#x}, {:#x})", start_vaddr, start_vaddr + size ); - GLOBAL_ALLOCATOR.add_memory(start_vaddr, size) + GLOBAL_ALLOCATOR.add_free_memory(start_vaddr, size) } diff --git a/modules/axconfig/defconfig.toml b/modules/axconfig/defconfig.toml index e13488d9e5..ecf2432bf2 100644 --- a/modules/axconfig/defconfig.toml +++ b/modules/axconfig/defconfig.toml @@ -9,6 +9,8 @@ family = "dummy" phys-memory-base = "0" # Size of the whole physical memory. phys-memory-size = "0" +# Size of the nocache memory region +nocache-memory-size = "0" # Base physical address of the kernel image. kernel-base-paddr = "0" # Base virtual address of the kernel image. diff --git a/modules/axconfig/src/lib.rs b/modules/axconfig/src/lib.rs index 8705b803fe..4e4fca35fd 100644 --- a/modules/axconfig/src/lib.rs +++ b/modules/axconfig/src/lib.rs @@ -16,4 +16,4 @@ mod config { pub use config::*; /// End address of the whole physical memory. -pub const PHYS_MEMORY_END: usize = PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE; +pub const PHYS_MEMORY_END: usize = PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE - NOCACHE_MEMORY_SIZE; diff --git a/modules/axdriver/Cargo.toml b/modules/axdriver/Cargo.toml index 87280a27ee..bff03ac2f0 100644 --- a/modules/axdriver/Cargo.toml +++ b/modules/axdriver/Cargo.toml @@ -27,6 +27,7 @@ virtio-gpu = ["display", "virtio", "driver_virtio/gpu"] ramdisk = ["block", "driver_block/ramdisk"] bcm2835-sdhci = ["block", "driver_block/bcm2835-sdhci"] ixgbe = ["net", "driver_net/ixgbe", "dep:axalloc", "dep:axhal"] +bcm2711 = ["driver_pci/bcm2711"] # more devices example: e1000 = ["net", "driver_net/e1000"] default = ["bus-mmio"] diff --git a/modules/axdriver/build.rs b/modules/axdriver/build.rs index d418d5ec19..e34a95d390 100644 --- a/modules/axdriver/build.rs +++ b/modules/axdriver/build.rs @@ -1,6 +1,7 @@ -const NET_DEV_FEATURES: &[&str] = &["ixgbe", "virtio-net"]; +const NET_DEV_FEATURES: &[&str] = &["ixgbe", "virtio-net", "phytium"]; const BLOCK_DEV_FEATURES: &[&str] = &["ramdisk", "bcm2835-sdhci", "virtio-blk"]; const DISPLAY_DEV_FEATURES: &[&str] = &["virtio-gpu"]; +const USB_HOST_DEV_FEATURES: &[&str] = &["phytium-xhci", "vl805"]; fn has_feature(feature: &str) -> bool { std::env::var(format!( @@ -17,10 +18,17 @@ fn enable_cfg(key: &str, value: &str) { fn main() { if has_feature("bus-pci") { enable_cfg("bus", "pci"); - } else { - enable_cfg("bus", "mmio"); } + // if has_feature("bus-mmio") { + // enable_cfg("bus", "mmio"); + // } + + // if #[cfg(platform = "aarch64-phytium-pi"{ + // if has_feature(feature) + // enable_cfg("bus", "mmio"); + // } + // Generate cfgs like `net_dev="virtio-net"`. if `dyn` is not enabled, only one device is // selected for each device category. If no device is selected, `dummy` is selected. let is_dyn = has_feature("dyn"); @@ -28,6 +36,7 @@ fn main() { ("net", NET_DEV_FEATURES), ("block", BLOCK_DEV_FEATURES), ("display", DISPLAY_DEV_FEATURES), + ("usb_host", USB_HOST_DEV_FEATURES), ] { if !has_feature(dev_kind) { continue; diff --git a/modules/axdriver/src/bus/mmio.rs b/modules/axdriver/src/bus/mmio.rs index 5a3573a6a6..4a400c4d86 100644 --- a/modules/axdriver/src/bus/mmio.rs +++ b/modules/axdriver/src/bus/mmio.rs @@ -4,6 +4,8 @@ use crate::{prelude::*, AllDevices}; impl AllDevices { pub(crate) fn probe_bus_devices(&mut self) { // TODO: parse device tree + //don't use cfg_if at here ramdomly!!!! might cause lld error + //waste time: 2days #[cfg(feature = "virtio")] for reg in axconfig::VIRTIO_MMIO_REGIONS { for_each_drivers!(type Driver, { diff --git a/modules/axdriver/src/bus/pci.rs b/modules/axdriver/src/bus/pci.rs index f47b2757e6..4c43039ede 100644 --- a/modules/axdriver/src/bus/pci.rs +++ b/modules/axdriver/src/bus/pci.rs @@ -1,122 +1,32 @@ use crate::{prelude::*, AllDevices}; use axhal::mem::phys_to_virt; -use driver_pci::{ - BarInfo, Cam, Command, DeviceFunction, HeaderType, MemoryBarType, PciRangeAllocator, PciRoot, -}; - -const PCI_BAR_NUM: u8 = 6; - -fn config_pci_device( - root: &mut PciRoot, - bdf: DeviceFunction, - allocator: &mut Option, -) -> DevResult { - let mut bar = 0; - while bar < PCI_BAR_NUM { - let info = root.bar_info(bdf, bar).unwrap(); - if let BarInfo::Memory { - address_type, - address, - size, - .. - } = info - { - // if the BAR address is not assigned, call the allocator and assign it. - if size > 0 && address == 0 { - let new_addr = allocator - .as_mut() - .expect("No memory ranges available for PCI BARs!") - .alloc(size as _) - .ok_or(DevError::NoMemory)?; - if address_type == MemoryBarType::Width32 { - root.set_bar_32(bdf, bar, new_addr as _); - } else if address_type == MemoryBarType::Width64 { - root.set_bar_64(bdf, bar, new_addr); - } - } - } - - // read the BAR info again after assignment. - let info = root.bar_info(bdf, bar).unwrap(); - match info { - BarInfo::IO { address, size } => { - if address > 0 && size > 0 { - debug!(" BAR {}: IO [{:#x}, {:#x})", bar, address, address + size); - } - } - BarInfo::Memory { - address_type, - prefetchable, - address, - size, - } => { - if address > 0 && size > 0 { - debug!( - " BAR {}: MEM [{:#x}, {:#x}){}{}", - bar, - address, - address + size as u64, - if address_type == MemoryBarType::Width64 { - " 64bit" - } else { - "" - }, - if prefetchable { " pref" } else { "" }, - ); - } - } - } - - bar += 1; - if info.takes_two_entries() { - bar += 1; - } - } - - // Enable the device. - let (_status, cmd) = root.get_status_command(bdf); - root.set_command( - bdf, - cmd | Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER, - ); - Ok(()) -} +use driver_pci::*; impl AllDevices { pub(crate) fn probe_bus_devices(&mut self) { let base_vaddr = phys_to_virt(axconfig::PCI_ECAM_BASE.into()); - let mut root = unsafe { PciRoot::new(base_vaddr.as_mut_ptr(), Cam::Ecam) }; - - // PCI 32-bit MMIO space - let mut allocator = axconfig::PCI_RANGES - .get(1) - .map(|range| PciRangeAllocator::new(range.0 as u64, range.1 as u64)); - - for bus in 0..=axconfig::PCI_BUS_END as u8 { - for (bdf, dev_info) in root.enumerate_bus(bus) { - debug!("PCI {}: {}", bdf, dev_info); - if dev_info.header_type != HeaderType::Standard { - continue; - } - match config_pci_device(&mut root, bdf, &mut allocator) { - Ok(_) => for_each_drivers!(type Driver, { - if let Some(dev) = Driver::probe_pci(&mut root, bdf, &dev_info) { - info!( - "registered a new {:?} device at {}: {:?}", - dev.device_type(), - bdf, - dev.device_name(), - ); - self.add_device(dev); - continue; // skip to the next device - } - }), - Err(e) => warn!( - "failed to enable PCI device at {}({}): {:?}", - bdf, dev_info, e - ), - } - } + let pci_range = axconfig::PCI_RANGES.get(1).unwrap(); + let mut root = driver_pci::new_root_complex( + base_vaddr.as_usize(), + pci_range.0 as u64..pci_range.1 as u64, + ); + + debug!("probing in pci.rs!"); + + for (bdf, dev_info, cfg) in root.enumerate_bus() { + debug!("PCI {}: {}", bdf, dev_info); + for_each_drivers!(type Driver,{ + if let Some(dev) = Driver::probe_pci(&mut root, bdf.clone(), &dev_info, &cfg) { + info!( + "registered a new {:?} device at {}: {:?}", + dev.device_type(), + bdf, + dev.device_name(), + ); + self.add_device(dev); + continue; // skip to the next device + } + }); } } } diff --git a/modules/axdriver/src/drivers.rs b/modules/axdriver/src/drivers.rs index 5ee6dcacdb..d011fce905 100644 --- a/modules/axdriver/src/drivers.rs +++ b/modules/axdriver/src/drivers.rs @@ -3,13 +3,19 @@ #![allow(unused_imports)] use crate::AxDeviceEnum; +use axalloc::{global_allocator, global_no_cache_allocator}; +use cfg_if::cfg_if; use driver_common::DeviceType; +// use driver_usb::OsDep; + +const VL805_VENDOR_ID: u16 = 0x1106; +const VL805_DEVICE_ID: u16 = 0x3483; #[cfg(feature = "virtio")] use crate::virtio::{self, VirtIoDevMeta}; #[cfg(feature = "bus-pci")] -use driver_pci::{DeviceFunction, DeviceFunctionInfo, PciRoot}; +use driver_pci::{types::ConfigSpace, DeviceFunction, DeviceFunctionInfo, PciAddress, PciRoot}; pub use super::dummy::*; @@ -28,7 +34,10 @@ pub trait DriverProbe { _root: &mut PciRoot, _bdf: DeviceFunction, _dev_info: &DeviceFunctionInfo, + _config: &ConfigSpace, ) -> Option { + use driver_pci::types::ConfigSpace; + None } } @@ -92,6 +101,7 @@ cfg_if::cfg_if! { root: &mut driver_pci::PciRoot, bdf: driver_pci::DeviceFunction, dev_info: &driver_pci::DeviceFunctionInfo, + _cfg: &ConfigSpace ) -> Option { use crate::ixgbe::IxgbeHalImpl; use driver_net::ixgbe::{INTEL_82599, INTEL_VEND, IxgbeNic}; @@ -105,7 +115,19 @@ cfg_if::cfg_if! { const QS: usize = 1024; let bar_info = root.bar_info(bdf, 0).unwrap(); match bar_info { - driver_pci::BarInfo::Memory { + driver_pci::BarInfo::Memory64 { + address, + size, + .. + } => { + let ixgbe_nic = IxgbeNic::::init( + phys_to_virt((address as usize).into()).into(), + size as usize + ) + .expect("failed to initialize ixgbe device"); + return Some(AxDeviceEnum::from_net(ixgbe_nic)); + } + driver_pci::BarInfo::Memory32 { address, size, .. @@ -117,7 +139,7 @@ cfg_if::cfg_if! { .expect("failed to initialize ixgbe device"); return Some(AxDeviceEnum::from_net(ixgbe_nic)); } - driver_pci::BarInfo::IO { .. } => { + driver_pci::BarInfo::Io { .. } => { error!("ixgbe: BAR0 is of I/O type"); return None; } @@ -128,3 +150,72 @@ cfg_if::cfg_if! { } } } + +// //todo maybe we should re arrange these code +// //------------------------------------------ +// use axalloc::GlobalNoCacheAllocator; +// use driver_usb::ax::USBHostDriverOps; +// use driver_usb::host::xhci::Xhci; +// use driver_usb::host::USBHost; +// pub struct XHCIUSBDriver; + +// #[derive(Clone)] +// pub struct OsDepImp; + +// impl OsDep for OsDepImp { +// const PAGE_SIZE: usize = axalloc::PAGE_SIZE; +// type DMA = GlobalNoCacheAllocator; +// fn dma_alloc(&self) -> Self::DMA { +// axalloc::global_no_cache_allocator() +// } + +// fn force_sync_cache() { +// cfg_if::cfg_if! { +// if #[cfg(usb_host_dev = "phytium-xhci")] { +// unsafe{ +// core::arch::asm!(" +// dc cisw +// ") +// } +// } +// } +// } +// } + +// cfg_match! { +// cfg(usb_host_dev = "vl805")=>{ +// register_usb_host_driver!(XHCIUSBDriver, VL805); +// } +// _=>{ +// register_usb_host_driver!(XHCIUSBDriver, USBHost); +// } +// } + +// impl DriverProbe for XHCIUSBDriver { +// #[cfg(bus = "pci")] +// cfg_match! { +// cfg(usb_host_dev = "vl805")=>{ +// use driver_usb::platform_spec::vl805::VL805; +// fn probe_pci( +// root: &mut PciRoot, +// bdf: DeviceFunction, +// dev_info: &DeviceFunctionInfo, +// config: &ConfigSpace, +// ) -> Option { +// let osdep = OsDepImp {}; +// VL805::probe_pci(config, osdep).map(|d| AxDeviceEnum::from_usb_host(d)) +// } +// } +// _=>{ +// fn probe_pci( +// root: &mut PciRoot, +// bdf: DeviceFunction, +// dev_info: &DeviceFunctionInfo, +// config: &ConfigSpace, +// ) -> Option { +// None +// } +// } +// } +// } +// //------------------------------------------ diff --git a/modules/axdriver/src/lib.rs b/modules/axdriver/src/lib.rs index 05b5d98524..94d3379a8d 100644 --- a/modules/axdriver/src/lib.rs +++ b/modules/axdriver/src/lib.rs @@ -57,6 +57,7 @@ #![no_std] #![feature(doc_auto_cfg)] #![feature(associated_type_defaults)] +#![feature(cfg_match)] #[macro_use] extern crate log; @@ -130,6 +131,7 @@ impl AllDevices { } }); + #[cfg(bus = "pci")] self.probe_bus_devices(); } diff --git a/modules/axdriver/src/macros.rs b/modules/axdriver/src/macros.rs index b90e813e70..e6753504d0 100644 --- a/modules/axdriver/src/macros.rs +++ b/modules/axdriver/src/macros.rs @@ -26,6 +26,14 @@ macro_rules! register_display_driver { }; } +macro_rules! register_usb_host_driver { + ($driver_type:ty, $device_type:ty) => { + /// The unified type of the NIC devices. + #[cfg(not(feature = "dyn"))] + pub type AxUSBHostDevice = $device_type; + }; +} + macro_rules! for_each_drivers { (type $drv_type:ident, $code:block) => {{ #[allow(unused_imports)] diff --git a/modules/axhal/src/arch/aarch64/mod.rs b/modules/axhal/src/arch/aarch64/mod.rs index 46d3fc7acb..7f45bd6336 100644 --- a/modules/axhal/src/arch/aarch64/mod.rs +++ b/modules/axhal/src/arch/aarch64/mod.rs @@ -67,6 +67,7 @@ pub unsafe fn write_page_table_root(root_paddr: PhysAddr) { trace!("set page table root: {:#x} => {:#x}", old_root, root_paddr); if old_root != root_paddr { // kernel space page table use TTBR1 (0xffff_0000_0000_0000..0xffff_ffff_ffff_ffff) + TTBR0_EL1.set(root_paddr.as_usize() as _); TTBR1_EL1.set(root_paddr.as_usize() as _); flush_tlb(None); } diff --git a/modules/axhal/src/lib.rs b/modules/axhal/src/lib.rs index 9fd27a1b1f..7645dda810 100644 --- a/modules/axhal/src/lib.rs +++ b/modules/axhal/src/lib.rs @@ -27,10 +27,9 @@ #![no_std] #![feature(asm_const)] #![feature(naked_functions)] -#![feature(const_maybe_uninit_zeroed)] #![feature(const_option)] #![feature(doc_auto_cfg)] - +#![allow(warnings)] #[allow(unused_imports)] #[macro_use] extern crate log; diff --git a/modules/axhal/src/mem.rs b/modules/axhal/src/mem.rs index ee96c4dc5d..48dfc07bee 100644 --- a/modules/axhal/src/mem.rs +++ b/modules/axhal/src/mem.rs @@ -129,8 +129,9 @@ pub(crate) fn default_mmio_regions() -> impl Iterator { /// Returns the default free memory regions (kernel image end to physical memory end). #[allow(dead_code)] pub(crate) fn default_free_regions() -> impl Iterator { - let start = virt_to_phys((_ekernel as usize).into()).align_up_4k(); - let end = PhysAddr::from(axconfig::PHYS_MEMORY_END).align_down_4k(); + let start = VirtAddr::from(_ekernel as usize + axconfig::NOCACHE_MEMORY_SIZE).align_up_4k(); + let start = virt_to_phys(start); + let end = PhysAddr::from(axconfig::PHYS_MEMORY_END); core::iter::once(MemRegion { paddr: start, size: end.as_usize() - start.as_usize(), @@ -139,6 +140,20 @@ pub(crate) fn default_free_regions() -> impl Iterator { }) } +/// Returns the default free memory regions (kernel image end to physical memory end). +#[allow(dead_code)] +pub(crate) fn default_nocache_regions() -> impl Iterator { + let start = VirtAddr::from(_ekernel as usize).align_up_4k(); + let start = virt_to_phys(start); + + core::iter::once(MemRegion { + paddr: start, + size: axconfig::NOCACHE_MEMORY_SIZE, + flags: MemRegionFlags::DEVICE | MemRegionFlags::READ | MemRegionFlags::WRITE, + name: "nocache memory", + }) +} + /// Fills the `.bss` section with zeros. #[allow(dead_code)] pub(crate) fn clear_bss() { diff --git a/modules/axhal/src/platform/aarch64_common/boot.rs b/modules/axhal/src/platform/aarch64_common/boot.rs index a944e18116..fd44574aa5 100644 --- a/modules/axhal/src/platform/aarch64_common/boot.rs +++ b/modules/axhal/src/platform/aarch64_common/boot.rs @@ -1,4 +1,5 @@ use aarch64_cpu::{asm, asm::barrier, registers::*}; +use core::ptr; use memory_addr::PhysAddr; use page_table_entry::aarch64::{MemAttr, A64PTE}; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; @@ -100,7 +101,6 @@ unsafe fn init_boot_page_table() { crate::platform::mem::init_boot_page_table(&mut BOOT_PT_L0, &mut BOOT_PT_L1); } -/// The earliest entry point for the primary CPU. #[naked] #[no_mangle] #[link_section = ".text.boot"] @@ -109,17 +109,23 @@ unsafe extern "C" fn _start() -> ! { // X0 = dtb core::arch::asm!(" mrs x19, mpidr_el1 + bl {debug} // put debug a and x19, x19, #0xffffff // get current CPU id mov x20, x0 // save DTB pointer adrp x8, {boot_stack} // setup boot stack add x8, x8, {boot_stack_size} mov sp, x8 + bl {debug} bl {switch_to_el1} // switch to EL1 + bl {debug} bl {init_boot_page_table} + bl {debug} bl {init_mmu} // setup MMU + bl {debug_paged} bl {enable_fp} // enable fp/neon + bl {debug_paged} mov x8, {phys_virt_offset} // set SP to the high address add sp, sp, x8 @@ -129,6 +135,9 @@ unsafe extern "C" fn _start() -> ! { ldr x8, ={entry} blr x8 b .", + // TODO consider add some light? + debug = sym put_debug, + debug_paged = sym put_debug_paged, switch_to_el1 = sym switch_to_el1, init_boot_page_table = sym init_boot_page_table, init_mmu = sym init_mmu, @@ -141,6 +150,30 @@ unsafe extern "C" fn _start() -> ! { ) } +#[cfg(all(target_arch = "aarch64"))] +#[no_mangle] +unsafe extern "C" fn put_debug() { + #[cfg(platform_family = "aarch64-phytium-pi")] + { + let state = (0x2800D018 as usize) as *mut u8; + let put = (0x2800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; + } +} + +#[cfg(all(target_arch = "aarch64"))] +#[no_mangle] +unsafe extern "C" fn put_debug_paged() { + #[cfg(platform_family = "aarch64-phytium-pi")] + { + let state = (0xFFFF00002800D018 as usize) as *mut u8; + let put = (0xFFFF00002800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; + } +} + /// The earliest entry point for the secondary CPUs. #[cfg(feature = "smp")] #[naked] diff --git a/modules/axhal/src/platform/aarch64_common/mod.rs b/modules/axhal/src/platform/aarch64_common/mod.rs index c585541fe8..85ace61042 100644 --- a/modules/axhal/src/platform/aarch64_common/mod.rs +++ b/modules/axhal/src/platform/aarch64_common/mod.rs @@ -1,7 +1,10 @@ mod boot; pub mod generic_timer; -#[cfg(not(platform_family = "aarch64-raspi"))] +#[cfg(not(any( + all(platform_family = "aarch64-raspi"), + all(platform_family = "aarch64-phytium-pi"), +)))] pub mod psci; #[cfg(feature = "irq")] diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs new file mode 100644 index 0000000000..75e6fc3dd7 --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mem.rs @@ -0,0 +1,47 @@ +use crate::mem::*; +use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags}; + +/// Returns platform-specific memory regions. +pub(crate) fn platform_regions() -> impl Iterator { + core::iter::once(MemRegion { + paddr: 0x0.into(), + size: 0x1000, + flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, + name: "spintable", + }) + .chain(crate::mem::default_nocache_regions()) + .chain(crate::mem::default_free_regions()) + .chain(crate::mem::default_mmio_regions()) +} + +pub(crate) unsafe fn init_boot_page_table( + boot_pt_l0: &mut [A64PTE; 512], + boot_pt_l1: &mut [A64PTE; 512], +) { + // 0x0000_0000_0000 ~ 0x0080_0000_0000, table + boot_pt_l0[0] = A64PTE::new_table(PhysAddr::from(boot_pt_l1.as_ptr() as usize)); + // 0x0000_0000_0000..0x0000_8000_0000, 1G block, device memory + boot_pt_l1[0] = A64PTE::new_page( + PhysAddr::from(0), + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, + true, + ); + // // 0x0000_4000_0000..0x0000_8000_0000, 1G block, normal memory + // boot_pt_l1[1] = A64PTE::new_page( + // PhysAddr::from(0x4000_0000), + // MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, + // true, + // ); + // 0x0000_8000_0000..0x0000_C000_0000, 2G block, normal memory + boot_pt_l1[2] = A64PTE::new_page( + PhysAddr::from(0x8000_0000), + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE, + true, + ); + // 0x0000_C000_0000..0x0001_0000_0000, 1G block, DEVICE memory + // boot_pt_l1[3] = A64PTE::new_page( + // PhysAddr::from(0xc000_0000), + // MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE, + // true, + // ); +} diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs new file mode 100644 index 0000000000..1bf18c4b8f --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mod.rs @@ -0,0 +1,100 @@ +pub mod mem; +use core::ptr; + +#[cfg(feature = "smp")] +pub mod mp; + +#[cfg(feature = "irq")] +pub mod irq { + pub use crate::platform::aarch64_common::gic::*; +} + +pub mod console { + pub use crate::platform::aarch64_common::pl011::*; +} + +pub mod time { + pub use crate::platform::aarch64_common::generic_timer::*; +} + +pub mod misc { + pub fn terminate() -> ! { + info!("Shutting down..."); + loop { + crate::arch::halt(); + } + } +} + +extern "C" { + fn exception_vector_base(); + fn rust_main(cpu_id: usize, dtb: usize); + #[cfg(feature = "smp")] + fn rust_main_secondary(cpu_id: usize); +} + +pub(crate) unsafe extern "C" fn rust_entry(cpu_id: usize, dtb: usize) { + crate::mem::clear_bss(); + put_debug2(); + crate::arch::set_exception_vector_base(exception_vector_base as usize); + put_debug2(); + crate::arch::write_page_table_root0(0.into()); // disable low address access + put_debug_paged2(); + crate::cpu::init_primary(cpu_id); + put_debug_paged2(); + super::aarch64_common::pl011::init_early(); + put_debug_paged2(); + super::aarch64_common::generic_timer::init_early(); + put_debug_paged2(); + rust_main(cpu_id, dtb); +} + +#[cfg(all(target_arch = "aarch64"))] +#[no_mangle] +unsafe extern "C" fn put_debug2() { + #[cfg(platform_family = "aarch64-phytium-pi")] + { + let state = (0x2800D018 as usize) as *mut u8; + let put = (0x2800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; + } +} + +#[cfg(all(target_arch = "aarch64"))] +#[no_mangle] +unsafe extern "C" fn put_debug_paged2() { + #[cfg(platform_family = "aarch64-phytium-pi")] + { + let state = (0xFFFF00002800D018 as usize) as *mut u8; + let put = (0xFFFF00002800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'a'; + } +} + +#[cfg(feature = "smp")] +pub(crate) unsafe extern "C" fn rust_entry_secondary(cpu_id: usize) { + crate::arch::set_exception_vector_base(exception_vector_base as usize); + crate::arch::write_page_table_root0(0.into()); // disable low address access + crate::cpu::init_secondary(cpu_id); + rust_main_secondary(cpu_id); +} + +/// Initializes the platform devices for the primary CPU. +/// +/// For example, the interrupt controller and the timer. +pub fn platform_init() { + #[cfg(feature = "irq")] + super::aarch64_common::gic::init_primary(); + super::aarch64_common::generic_timer::init_percpu(); + super::aarch64_common::pl011::init(); +} + +/// Initializes the platform devices for secondary CPUs. +#[cfg(feature = "smp")] +pub fn platform_init_secondary() { + #[cfg(feature = "irq")] + super::aarch64_common::gic::init_secondary(); + super::aarch64_common::generic_timer::init_percpu(); +} diff --git a/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs b/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs new file mode 100644 index 0000000000..23549c01f1 --- /dev/null +++ b/modules/axhal/src/platform/aarch64_phytium_pi/mp.rs @@ -0,0 +1,49 @@ +use crate::mem::{phys_to_virt, virt_to_phys, PhysAddr, VirtAddr}; + +static mut SECONDARY_STACK_TOP: usize = 0; + +extern "C" { + fn _start_secondary(); +} + +#[naked] +#[link_section = ".text.boot"] +unsafe extern "C" fn modify_stack_and_start() { + core::arch::asm!(" + ldr x21, ={secondary_boot_stack} // the secondary CPU hasn't set the TTBR1 + mov x8, {phys_virt_offset} // minus the offset to get the phys addr of the boot stack + sub x21, x21, x8 + ldr x21, [x21] + mov x0, x21 // x0 will be set to SP in the beginning of _start_secondary + b _start_secondary", + secondary_boot_stack = sym SECONDARY_STACK_TOP, + phys_virt_offset = const axconfig::PHYS_VIRT_OFFSET, + options(noreturn) + ); +} + +pub static CPU_SPIN_TABLE: [PhysAddr; 4] = [ + PhysAddr::from(0xd8), + PhysAddr::from(0xe0), + PhysAddr::from(0xe8), + PhysAddr::from(0xf0), +]; + +/// Starts the given secondary CPU with its boot stack. +pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { + let entry_paddr = virt_to_phys(VirtAddr::from(modify_stack_and_start as usize)).as_usize(); + unsafe { + // set the boot code address of the given secondary CPU + let spintable_vaddr = phys_to_virt(CPU_SPIN_TABLE[cpu_id]); + let release_ptr = spintable_vaddr.as_mut_ptr() as *mut usize; + release_ptr.write_volatile(entry_paddr); + crate::arch::flush_dcache_line(spintable_vaddr); + + // set the boot stack of the given secondary CPU + SECONDARY_STACK_TOP = stack_top.as_usize(); + crate::arch::flush_dcache_line(VirtAddr::from( + (&SECONDARY_STACK_TOP as *const usize) as usize, + )); + } + aarch64_cpu::asm::sev(); +} diff --git a/modules/axhal/src/platform/aarch64_raspi/mem.rs b/modules/axhal/src/platform/aarch64_raspi/mem.rs index 7c426e08f9..0e838e1a16 100644 --- a/modules/axhal/src/platform/aarch64_raspi/mem.rs +++ b/modules/axhal/src/platform/aarch64_raspi/mem.rs @@ -9,6 +9,7 @@ pub(crate) fn platform_regions() -> impl Iterator { flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, name: "spintable", }) + .chain(crate::mem::default_nocache_regions()) .chain(crate::mem::default_free_regions()) .chain(crate::mem::default_mmio_regions()) } diff --git a/modules/axhal/src/platform/mod.rs b/modules/axhal/src/platform/mod.rs index a39151c47f..8923b5dec2 100644 --- a/modules/axhal/src/platform/mod.rs +++ b/modules/axhal/src/platform/mod.rs @@ -19,6 +19,9 @@ cfg_if::cfg_if! { } else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-raspi"))] { mod aarch64_raspi; pub use self::aarch64_raspi::*; + } else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-phytium-pi"))] { + mod aarch64_phytium_pi; + pub use self::aarch64_phytium_pi::*; } else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-bsta1000b"))] { mod aarch64_bsta1000b; pub use self::aarch64_bsta1000b::*; diff --git a/modules/axruntime/Cargo.toml b/modules/axruntime/Cargo.toml index ccd000b1d4..7be2028b9d 100644 --- a/modules/axruntime/Cargo.toml +++ b/modules/axruntime/Cargo.toml @@ -22,6 +22,8 @@ multitask = ["axtask/multitask"] fs = ["axdriver", "axfs"] net = ["axdriver", "axnet"] display = ["axdriver", "axdisplay"] +usb = ["axdriver"] + [dependencies] axhal = { path = "../axhal" } diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index a62c3055cb..5e254f9099 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -18,6 +18,9 @@ #![cfg_attr(not(test), no_std)] #![feature(doc_auto_cfg)] +#![allow(unused_imports)] +#![allow(unexpected_cfgs)] +#![allow(dead_code)] #[macro_use] extern crate axlog; @@ -92,6 +95,16 @@ fn is_init_ok() -> bool { INITED_CPUS.load(Ordering::Acquire) == axconfig::SMP } +unsafe extern "C" fn put_debug_paged3() { + #[cfg(platform_family = "aarch64-phytium-pi")] + { + let state = (0xFFFF00002800D018 as usize) as *mut u8; + let put = (0xFFFF00002800D000 as usize) as *mut u8; + while (ptr::read_volatile(state) & (0x20 as u8)) != 0 {} + *put = b'c'; + } +} + /// The main entry point of the ArceOS runtime. /// /// It is called from the bootstrapping code in [axhal]. `cpu_id` is the ID of @@ -103,7 +116,8 @@ fn is_init_ok() -> bool { /// and the secondary CPUs call [`rust_main_secondary`]. #[cfg_attr(not(test), no_mangle)] pub extern "C" fn rust_main(cpu_id: usize, dtb: usize) -> ! { - ax_println!("{}", LOGO); + // ax_println!("{}", LOGO); + unsafe { put_debug_paged3() } ax_println!( "\ arch = {}\n\ @@ -120,13 +134,17 @@ pub extern "C" fn rust_main(cpu_id: usize, dtb: usize) -> ! { option_env!("AX_MODE").unwrap_or(""), option_env!("AX_LOG").unwrap_or(""), ); + unsafe { put_debug_paged3() } axlog::init(); + unsafe { put_debug_paged3() } axlog::set_max_level(option_env!("AX_LOG").unwrap_or("")); // no effect if set `log-level-*` features + unsafe { put_debug_paged3() } info!("Logging is enabled."); info!("Primary CPU {} started, dtb = {:#x}.", cpu_id, dtb); info!("Found physcial memory regions:"); + unsafe { put_debug_paged3() } for r in axhal::mem::memory_regions() { info!( " [{:x?}, {:x?}) {} ({:?})", @@ -146,13 +164,16 @@ pub extern "C" fn rust_main(cpu_id: usize, dtb: usize) -> ! { remap_kernel_memory().expect("remap kernel memoy failed"); } + #[cfg(feature = "alloc")] + init_allocator_no_cache(); + info!("Initialize platform devices..."); axhal::platform_init(); #[cfg(feature = "multitask")] axtask::init_scheduler(); - #[cfg(any(feature = "fs", feature = "net", feature = "display"))] + #[cfg(any(feature = "fs", feature = "net", feature = "display", feature = "usb"))] { #[allow(unused_variables)] let all_devices = axdriver::init_drivers(); @@ -215,23 +236,47 @@ fn init_allocator() { max_region_paddr = r.paddr; } } - for r in memory_regions() { - if r.flags.contains(MemRegionFlags::FREE) && r.paddr == max_region_paddr { - axalloc::global_init(phys_to_virt(r.paddr).as_usize(), r.size); - break; + + { + let mut free_init: (usize, usize) = (0, 0); + for r in memory_regions() { + if r.flags.contains(MemRegionFlags::FREE) && r.paddr == max_region_paddr { + // axalloc::global_init(phys_to_virt(r.paddr).as_usize(), r.size); + free_init = (phys_to_virt(r.paddr).as_usize(), r.size); + break; + } } + axalloc::global_init(free_init); } + for r in memory_regions() { if r.flags.contains(MemRegionFlags::FREE) && r.paddr != max_region_paddr { - axalloc::global_add_memory(phys_to_virt(r.paddr).as_usize(), r.size) + axalloc::global_add_free_memory(phys_to_virt(r.paddr).as_usize(), r.size) .expect("add heap memory region failed"); } } } +#[cfg(feature = "alloc")] +fn init_allocator_no_cache() { + use axhal::mem::memory_regions; + + info!("Initialize global no cache memory allocator..."); + + { + let mut nocache_init: (usize, usize) = (0, 0); + for r in memory_regions() { + if r.name == "nocache memory" { + nocache_init = (r.paddr.as_usize(), r.size); + break; + } + } + axalloc::global_nocache_init(nocache_init); + } +} #[cfg(feature = "paging")] fn remap_kernel_memory() -> Result<(), axhal::paging::PagingError> { - use axhal::mem::{memory_regions, phys_to_virt}; + use axhal::mem::{memory_regions, phys_to_virt, VirtAddr}; use axhal::paging::PageTable; use lazy_init::LazyInit; @@ -240,13 +285,13 @@ fn remap_kernel_memory() -> Result<(), axhal::paging::PagingError> { if axhal::cpu::this_cpu_is_bsp() { let mut kernel_page_table = PageTable::try_new()?; for r in memory_regions() { - kernel_page_table.map_region( - phys_to_virt(r.paddr), - r.paddr, - r.size, - r.flags.into(), - true, - )?; + // mailbox 需要物理地址和虚拟地址一致 + let vaddr = if r.name == "nocache memory" { + VirtAddr::from(r.paddr.as_usize()) + } else { + phys_to_virt(r.paddr) + }; + kernel_page_table.map_region(vaddr, r.paddr, r.size, r.flags.into(), true)?; } KERNEL_PAGE_TABLE.init_by(kernel_page_table); } diff --git a/modules/axtask/src/run_queue.rs b/modules/axtask/src/run_queue.rs index 9c31f4384c..ddf3592cf3 100644 --- a/modules/axtask/src/run_queue.rs +++ b/modules/axtask/src/run_queue.rs @@ -69,11 +69,11 @@ impl AxRunQueue { // locking the run queue. let can_preempt = curr.can_preempt(1); - debug!( - "current task is to be preempted: {}, allow={}", - curr.id_name(), - can_preempt - ); + // debug!( + // "current task is to be preempted: {}, allow={}", + // curr.id_name(), + // can_preempt + // ); if can_preempt { self.resched(true); } else { diff --git a/platforms/aarch64-phytium-pi.toml b/platforms/aarch64-phytium-pi.toml new file mode 100644 index 0000000000..e1089f288d --- /dev/null +++ b/platforms/aarch64-phytium-pi.toml @@ -0,0 +1,71 @@ +# Architecture identifier. +arch = "aarch64" +# Platform identifier. +platform = "aarch64-phytium-pi" +# Platform family. +family = "aarch64-phytium-pi" + +# Base address of the whole physical memory. +phys-memory-base = "0x8000_0000" +# Size of the whole physical memory. +phys-memory-size = "0x8000_0000" # 2G +# Base physical address of the kernel image. +kernel-base-paddr = "0x9010_0000" +# Base virtual address of the kernel image. +kernel-base-vaddr = "0xffff_0000_9010_0000" +# kernel-base-vaddr = "0x9010_0000" +# Linear mapping offset, for quick conversions between physical and virtual +# addresses. + phys-virt-offset = "0xffff_0000_0000_0000" +#phys-virt-offset = "0x0000_0000_0000_0000" +# MMIO regions with format (`base_paddr`, `size`). +mmio-regions = [ + # ["0xFE00_B000", "0x1000"], # mailbox + # ["0xFE20_1000", "0x1000"], # PL011 UART + # ["0xFF84_1000", "0x8000"], # GICv2 + #["0x40000000", "0xfff_ffff"], # pcie ecam + + + # ["0x6_0000_0000", "0x4000_0000"] # pcie control + + + ["0x2800_C000", "0x1000"], # UART 0 + ["0x2800_D000", "0x1000"], # UART 1 + ["0x2800_E000", "0x1000"], # UART 2 + ["0x2800_F000", "0x1000"], # UART 3 + # ["0x32a0_0000", "0x2_0000"], # usb0 + # ["0x32a2_0000", "0x2_0000"], # usb0 + # ["0x3200_C000", "0x2000"], #Ethernet1 + # ["0x3200_E000", "0x2000"], #Ethernet2 + # ["0x3080_0000", "0x8000"], # GICv2 + ["0x3000_0000","0x800_0000"], #other devices + ["0x4000_0000","0x4000_0000"], # pcie + ["0x10_0000_0000", "0x20_0000_0000"], # pcie mmio 64 + + # ["0x6_0000_0000", "0x6_3fff_ffff"] # pcie control +] +virtio-mmio-regions = [] +# UART Address +uart-paddr = "0x2800_D000" +uart-irq = "24" + +# GIC Address +gicc-paddr = "0xFF84_2000" +gicd-paddr = "0xFF84_1000" + +# Base physical address of the PCIe ECAM space. +pci-ecam-base = "0x4000_0000" +# End PCI bus number. +pci-bus-end = "0x100" +# PCI device memory ranges. +pci-ranges = [ + ["0x58000000", "0x27ffffff"], # pcie mmio 32 + ["0x10_0000_0000", "0x30_0000_0000"], # pcie mmio 64 + # ["0x5800_0000", "0x7fff_ffff"], + + # ["0x6_0000_0000", "0x6_3fff_ffff"] +] + +# Size of the nocache memory region +nocache-memory-size = "0x70_0000" + diff --git a/platforms/aarch64-raspi4.toml b/platforms/aarch64-raspi4.toml index f204d1d1a0..21a93c1c4d 100644 --- a/platforms/aarch64-raspi4.toml +++ b/platforms/aarch64-raspi4.toml @@ -18,8 +18,13 @@ kernel-base-vaddr = "0xffff_0000_0008_0000" phys-virt-offset = "0xffff_0000_0000_0000" # MMIO regions with format (`base_paddr`, `size`). mmio-regions = [ + ["0xFE00_B000", "0x1000"], # mailbox ["0xFE20_1000", "0x1000"], # PL011 UART - ["0xFF84_1000", "0x8000"], # GICv2 + ["0xFF84_1000", "0x8000"], # GICv2 + ["0xFD50_0000", "0x20_0000"], # pcie ecam + + + ["0x6_0000_0000", "0x4000_0000"] # pcie control ] virtio-mmio-regions = [] # UART Address @@ -29,3 +34,24 @@ uart-irq = "0x79" # GIC Address gicc-paddr = "0xFF84_2000" gicd-paddr = "0xFF84_1000" + + +# Base physical address of the PCIe ECAM space. +pci-ecam-base = "0xfd50_0000" +# End PCI bus number. +pci-bus-end = "0x2" #? +# PCI device memory ranges. +pci-ranges = [ + # just for known config structure, not real address + # copy from virt.toml or something + # ["0x3ef_f0000", "0x1_0000"], # PIO space + # ["0x1000_0000", "0x2eff_0000"], # 32-bit MMIO space + ["0x00","0x3800000"], + # ["0x6_0000_0000", "0x7_FFFF_FFFF"], # 64-bit MMIO space + ["0x6_0000_0000", "0x6_3fff_ffff"], # xhci space: https://blog.csdn.net/qq_26989627/article/details/122024901 + # ["0xFD50_0000", "0xFD50_9310"], # pcie + # ["0x04","0x7c000000"], +] #TODO: findout ranges + +# Size of the nocache memory region +nocache-memory-size = "0x20_0000" \ No newline at end of file diff --git a/pyvenv.cfg b/pyvenv.cfg new file mode 100644 index 0000000000..648747c658 --- /dev/null +++ b/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /usr/sbin +include-system-site-packages = false +version = 3.11.8 +executable = /usr/bin/python3.11 +command = /usr/sbin/python -m venv /home/dbydd/gitRepos/arceos_experiment diff --git a/scripts/make/phytium-pi.mk b/scripts/make/phytium-pi.mk new file mode 100644 index 0000000000..fab138980c --- /dev/null +++ b/scripts/make/phytium-pi.mk @@ -0,0 +1,13 @@ +phytium: build + gzip -9 -cvf $(OUT_BIN) > arceos-phytium-pi.bin.gz + mkimage -f tools/phytium-pi/phytium-pi.its arceos-phytiym-pi.itb + @echo 'Built the FIT-uImage arceos-phytium-pi.itb' + +chainboot: build + tools/phytium-pi/yet_another_uboot_transfer.py /dev/ttyUSB0 115200 $(OUT_BIN) + echo ' ' > minicom_output.log + minicom -D /dev/ttyUSB0 -b 115200 -C minicom_output.log +# python tools/phytium-pi/uboot_transfer.py /dev/ttyUSB0 115200 $(OUT_BIN) +# python tools/phytium-pi/uboot_test_send.py /dev/ttyUSB0 115200 $(OUT_BIN) +#ruby tools/phytium-pi/uboot_transfer.rb /dev/ttyUSB0 115200 $(OUT_BIN) + diff --git a/scripts/make/qemu.mk b/scripts/make/qemu.mk index c8acab2578..39abf2e87f 100644 --- a/scripts/make/qemu.mk +++ b/scripts/make/qemu.mk @@ -45,9 +45,18 @@ qemu_args-$(NET) += \ ifeq ($(NET_DEV), user) qemu_args-$(NET) += -netdev user,id=net0,hostfwd=tcp::5555-:5555,hostfwd=udp::5555-:5555 else ifeq ($(NET_DEV), tap) - qemu_args-$(NET) += -netdev tap,id=net0,ifname=tap0,script=no,downscript=no + qemu_args-$(NET) += -netdev tap,id=net0,script=scripts/net/qemu-ifup.sh,downscript=no,vhost=$(VHOST),vhostforce=$(VHOST) + QEMU := sudo $(QEMU) +else ifeq ($(NET_DEV), bridge) + qemu_args-$(NET) += -netdev bridge,id=net0,br=virbr0 + QEMU := sudo $(QEMU) else - $(error "NET_DEV" must be one of "user" or "tap") + $(error "NET_DEV" must be one of "user", "tap", or "bridge") +endif + +ifneq ($(VFIO_PCI),) + qemu_args-y += --device vfio-pci,host=$(VFIO_PCI) + QEMU := sudo $(QEMU) endif ifeq ($(NET_DUMP), y) diff --git a/scripts/make/raspi4.mk b/scripts/make/raspi4.mk index 66eea697b5..6d8b8c6e27 100644 --- a/scripts/make/raspi4.mk +++ b/scripts/make/raspi4.mk @@ -23,8 +23,10 @@ ifeq ($(BSP),rpi4) OBJDUMP_BINARY = aarch64-none-elf-objdump NM_BINARY = aarch64-none-elf-nm READELF_BINARY = aarch64-none-elf-readelf - OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi4.cfg - JTAG_BOOT_IMAGE = tools/raspi4/X1_JTAG_boot/jtag_boot_rpi4.img + # OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi4.cfg + OPENOCD_ARG = -f /openocd/tcl/interface/jlink.cfg -f /openocd/rpi4.cfg + # JTAG_BOOT_IMAGE = tools/raspi4/X1_JTAG_boot/jtag_boot_rpi4.img + JTAG_BOOT_IMAGE := $(OUT_BIN) RUSTC_MISC_ARGS = -C target-cpu=cortex-a72 endif @@ -33,12 +35,13 @@ EXEC_MINIPUSH = ruby tools/raspi4/common/serial/minipush.rb ##------------------------------------------------------------------------------ ## Dockerization ##------------------------------------------------------------------------------ -DOCKER_CMD = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial +DOCKER_CMD = sudo docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/tools/raspi4/common:/work/common DOCKER_ARG_DIR_JTAG = -v $(shell pwd)/tools/raspi4/X1_JTAG_boot:/work/X1_JTAG_boot DOCKER_ARG_DEV = --privileged -v /dev:/dev -DOCKER_ARG_NET = --network host +# DOCKER_ARG_NET = --network host +DOCKER_ARG_NET = --expose 3333 # DOCKER_IMAGE defined in include file (see top of this file). DOCKER_GDB = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_NET) $(DOCKER_IMAGE) @@ -48,7 +51,7 @@ ifeq ($(shell uname -s),Linux) DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV) DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE) DOCKER_JTAGBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_ARG_DIR_JTAG) $(DOCKER_IMAGE) - DOCKER_OPENOCD = $(DOCKER_CMD_DEV) $(DOCKER_ARG_NET) $(DOCKER_IMAGE) + DOCKER_OPENOCD = $(DOCKER_CMD_DEV) $(DOCKER_ARG_NET) $(DOCKER_IMAGE) else DOCKER_OPENOCD = echo "Not yet supported on non-Linux systems."; \# endif @@ -88,7 +91,8 @@ openocd: ##------------------------------------------------------------------------------ ## Start GDB session ##------------------------------------------------------------------------------ +KERNEL_ELF := $(patsubst %.bin,%.elf,$(KERNEL_BIN)) gdb: RUSTC_MISC_ARGS += -C debuginfo=2 gdb: $(KERNEL_ELF) - $(call color_header, "Launching GDB") + $(call color_header, "Launching GDB kernel: $(KERNEL_ELF)") @$(DOCKER_GDB) gdb-multiarch -q $(KERNEL_ELF) diff --git a/scripts/net/create-bridge.sh b/scripts/net/create-bridge.sh new file mode 100755 index 0000000000..3ed9cb01c2 --- /dev/null +++ b/scripts/net/create-bridge.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Create virtual bridge for QEMU. +# +# sudo ./create-bridge.sh [virbr0] + +BR=$1 +IP=10.0.2.2 + +if [ -z "$BR" ]; then + BR=virbr0 +fi + +echo "Deleting old virtual bridge $BR ..." + +ip link set dev $BR down 2> /dev/null +brctl delbr $BR 2> /dev/null + +echo "Setting up virtual bridge $BR ..." + +brctl addbr $BR +ip addr add $IP/24 dev $BR +ip link set dev $BR up +brctl show $BR + +ifconfig $BR diff --git a/scripts/net/del-iface.sh b/scripts/net/del-iface.sh new file mode 100755 index 0000000000..7d679b0a2c --- /dev/null +++ b/scripts/net/del-iface.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# +# Delete virtual interface (e.g. virtual bridge). +# +# sudo ./del-iface.sh + +IFACE=$1 + +if [ -z "$IFACE" ]; then + echo "Usage: $0 " + exit 1 +fi + +ip link del $IFACE diff --git a/scripts/net/pci-bind.sh b/scripts/net/pci-bind.sh new file mode 100755 index 0000000000..d2479328bc --- /dev/null +++ b/scripts/net/pci-bind.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Bind a PCI device to the `vfio-pci` driver for PCI passthrough. +# +# Bind: sudo ./pci-bind.sh vfio-pci 02:00.0 +# Unbind: sudo ./pci-bind.sh ixgbe 02:00.0 + +new_drv=$1 +bdf=$2 + +if [ -z "$bdf" -o -z "$new_drv" ]; then + echo "Usage: $0 " + exit 1 +fi + +bdf=0000:$bdf +old_drv=$(readlink /sys/bus/pci/devices/$bdf/driver | awk -F/ '{print $NF}') + +echo "Bind $bdf from $old_drv to $new_drv" + +echo $bdf > /sys/bus/pci/drivers/$old_drv/unbind +echo $new_drv > /sys/bus/pci/devices/$bdf/driver_override +echo $bdf > /sys/bus/pci/drivers/$new_drv/bind diff --git a/scripts/net/qemu-ifup.sh b/scripts/net/qemu-ifup.sh new file mode 100755 index 0000000000..b3e2c21b2b --- /dev/null +++ b/scripts/net/qemu-ifup.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Create a TAP interface and add it to the bridge. +# +# It's used for the startup script of QEMU netdev, DO NOT run it manually. + +br=virbr0 +if [ -n "$1" ]; then + #create a TAP interface; qemu will handle it automatically. + #tunctl -u $(whoami) -t $1 + #start up the TAP interface + ip link set "$1" up + brctl addif $br "$1" + exit +else + echo "Error: no interface specified" + exit 1 +fi diff --git a/scripts/net/qemu-tap-ifdown.sh b/scripts/net/qemu-tap-ifdown.sh deleted file mode 100755 index 12622a36b4..0000000000 --- a/scripts/net/qemu-tap-ifdown.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -HOST_IF=$1 - -if [ -z "$HOST_IF" ]; then - echo "Usage: $0 " - exit 1 -fi - -echo "Deleting tap interface for QEMU" - -ip link del tap0 -sysctl -w net.ipv4.ip_forward=0 -iptables -t nat -D POSTROUTING -s 10.0.2.0/24 -o ${HOST_IF} -j MASQUERADE diff --git a/scripts/net/qemu-tap-ifup.sh b/scripts/net/qemu-tap-ifup.sh deleted file mode 100755 index 1adabc9b88..0000000000 --- a/scripts/net/qemu-tap-ifup.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -HOST_IF=$1 - -if [ -z "$HOST_IF" ]; then - echo "Usage: $0 " - exit 1 -fi - -echo "Setting up tap interface for QEMU" - -ip tuntap add tap0 mode tap -ip addr add 10.0.2.2/24 dev tap0 -ip link set up dev tap0 - -sysctl -w net.ipv4.ip_forward=1 -iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -o ${HOST_IF} -j MASQUERADE diff --git a/scripts/net/set-ip-forward.sh b/scripts/net/set-ip-forward.sh new file mode 100755 index 0000000000..3ccb8bf507 --- /dev/null +++ b/scripts/net/set-ip-forward.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Setup IP forwarding to allow Internet access in the VM. + +WLAN_IF=$1 +BR=virbr0 +IP_RANGE=10.0.2.0/24 + +if [ -z "$WLAN_IF" ]; then + echo "Usage: $0 " + exit 1 +fi + +sysctl -w net.ipv4.ip_forward=1 + +iptables -t nat -A POSTROUTING -s $IP_RANGE -o $WLAN_IF -j MASQUERADE +iptables -A FORWARD -i $BR -j ACCEPT +iptables -A FORWARD -o $BR -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/scripts/net/unset-ip-forward.sh b/scripts/net/unset-ip-forward.sh new file mode 100755 index 0000000000..c361b64438 --- /dev/null +++ b/scripts/net/unset-ip-forward.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Disable IP forwarding and restore iptables rules. + +WLAN_IF=$1 +BR=virbr0 +IP_RANGE=10.0.2.0/24 + +if [ -z "$WLAN_IF" ]; then + echo "Usage: $0 " + exit 1 +fi + +sysctl -w net.ipv4.ip_forward=0 + +iptables -t nat -D POSTROUTING -s $IP_RANGE -o $WLAN_IF -j MASQUERADE +iptables -D FORWARD -i $BR -j ACCEPT +iptables -D FORWARD -o $BR -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/tools/.gitignore b/tools/.gitignore index 632baf2a00..6d9144fdc8 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -2,4 +2,6 @@ deptool/Cargo.lock deptool/target deptool/output.txt bwbench_client/target -bwbench_client/Cargo.lock \ No newline at end of file +bwbench_client/Cargo.lock +!raspi4/common/image/*/* +!raspi4/X1_JTAG_boot/* \ No newline at end of file diff --git a/tools/PCI_SYMBOLS.c b/tools/PCI_SYMBOLS.c new file mode 100644 index 0000000000..e9a4155309 --- /dev/null +++ b/tools/PCI_SYMBOLS.c @@ -0,0 +1,3133 @@ + +#define PCI_CLASS_NOT_DEFINED 0x0000 +#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 + +#define PCI_BASE_CLASS_STORAGE 0x01 +#define PCI_CLASS_STORAGE_SCSI 0x0100 +#define PCI_CLASS_STORAGE_IDE 0x0101 +#define PCI_CLASS_STORAGE_FLOPPY 0x0102 +#define PCI_CLASS_STORAGE_IPI 0x0103 +#define PCI_CLASS_STORAGE_RAID 0x0104 +#define PCI_CLASS_STORAGE_SATA 0x0106 +#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 +#define PCI_CLASS_STORAGE_SAS 0x0107 +#define PCI_CLASS_STORAGE_EXPRESS 0x010802 +#define PCI_CLASS_STORAGE_OTHER 0x0180 + + +#define PCI_BASE_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x0200 +#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 +#define PCI_CLASS_NETWORK_FDDI 0x0202 +#define PCI_CLASS_NETWORK_ATM 0x0203 +#define PCI_CLASS_NETWORK_OTHER 0x0280 + +#define PCI_BASE_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_VGA 0x0300 +#define PCI_CLASS_DISPLAY_XGA 0x0301 +#define PCI_CLASS_DISPLAY_3D 0x0302 +#define PCI_CLASS_DISPLAY_OTHER 0x0380 + +#define PCI_BASE_CLASS_MULTIMEDIA 0x04 +#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 +#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 +#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402 +#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 +#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 + +#define PCI_BASE_CLASS_MEMORY 0x05 +#define PCI_CLASS_MEMORY_RAM 0x0500 +#define PCI_CLASS_MEMORY_FLASH 0x0501 +#define PCI_CLASS_MEMORY_OTHER 0x0580 + +#define PCI_BASE_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x0600 +#define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_CLASS_BRIDGE_EISA 0x0602 +#define PCI_CLASS_BRIDGE_MC 0x0603 +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#define PCI_CLASS_BRIDGE_PCI_NORMAL 0x060400 +#define PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE 0x060401 +#define PCI_CLASS_BRIDGE_PCMCIA 0x0605 +#define PCI_CLASS_BRIDGE_NUBUS 0x0606 +#define PCI_CLASS_BRIDGE_CARDBUS 0x0607 +#define PCI_CLASS_BRIDGE_RACEWAY 0x0608 +#define PCI_CLASS_BRIDGE_OTHER 0x0680 + +#define PCI_BASE_CLASS_COMMUNICATION 0x07 +#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 +#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701 +#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702 +#define PCI_CLASS_COMMUNICATION_MODEM 0x0703 +#define PCI_CLASS_COMMUNICATION_OTHER 0x0780 + +#define PCI_BASE_CLASS_SYSTEM 0x08 +#define PCI_CLASS_SYSTEM_PIC 0x0800 +#define PCI_CLASS_SYSTEM_PIC_IOAPIC 0x080010 +#define PCI_CLASS_SYSTEM_PIC_IOXAPIC 0x080020 +#define PCI_CLASS_SYSTEM_DMA 0x0801 +#define PCI_CLASS_SYSTEM_TIMER 0x0802 +#define PCI_CLASS_SYSTEM_RTC 0x0803 +#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804 +#define PCI_CLASS_SYSTEM_SDHCI 0x0805 +#define PCI_CLASS_SYSTEM_RCEC 0x0807 +#define PCI_CLASS_SYSTEM_OTHER 0x0880 + +#define PCI_BASE_CLASS_INPUT 0x09 +#define PCI_CLASS_INPUT_KEYBOARD 0x0900 +#define PCI_CLASS_INPUT_PEN 0x0901 +#define PCI_CLASS_INPUT_MOUSE 0x0902 +#define PCI_CLASS_INPUT_SCANNER 0x0903 +#define PCI_CLASS_INPUT_GAMEPORT 0x0904 +#define PCI_CLASS_INPUT_OTHER 0x0980 + +#define PCI_BASE_CLASS_DOCKING 0x0a +#define PCI_CLASS_DOCKING_GENERIC 0x0a00 +#define PCI_CLASS_DOCKING_OTHER 0x0a80 + +#define PCI_BASE_CLASS_PROCESSOR 0x0b +#define PCI_CLASS_PROCESSOR_386 0x0b00 +#define PCI_CLASS_PROCESSOR_486 0x0b01 +#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02 +#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10 +#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 +#define PCI_CLASS_PROCESSOR_MIPS 0x0b30 +#define PCI_CLASS_PROCESSOR_CO 0x0b40 + +#define PCI_BASE_CLASS_SERIAL 0x0c +#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00 +#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010 +#define PCI_CLASS_SERIAL_ACCESS 0x0c01 +#define PCI_CLASS_SERIAL_SSA 0x0c02 +#define PCI_CLASS_SERIAL_USB 0x0c03 +#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300 +#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310 +#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320 +#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330 +#define PCI_CLASS_SERIAL_USB_DEVICE 0x0c03fe +#define PCI_CLASS_SERIAL_FIBER 0x0c04 +#define PCI_CLASS_SERIAL_SMBUS 0x0c05 +#define PCI_CLASS_SERIAL_IPMI 0x0c07 +#define PCI_CLASS_SERIAL_IPMI_SMIC 0x0c0700 +#define PCI_CLASS_SERIAL_IPMI_KCS 0x0c0701 +#define PCI_CLASS_SERIAL_IPMI_BT 0x0c0702 + +#define PCI_BASE_CLASS_WIRELESS 0x0d +#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10 +#define PCI_CLASS_WIRELESS_WHCI 0x0d1010 + +#define PCI_BASE_CLASS_INTELLIGENT 0x0e +#define PCI_CLASS_INTELLIGENT_I2O 0x0e00 + +#define PCI_BASE_CLASS_SATELLITE 0x0f +#define PCI_CLASS_SATELLITE_TV 0x0f00 +#define PCI_CLASS_SATELLITE_AUDIO 0x0f01 +#define PCI_CLASS_SATELLITE_VOICE 0x0f03 +#define PCI_CLASS_SATELLITE_DATA 0x0f04 + +#define PCI_BASE_CLASS_CRYPT 0x10 +#define PCI_CLASS_CRYPT_NETWORK 0x1000 +#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001 +#define PCI_CLASS_CRYPT_OTHER 0x1080 + +#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11 +#define PCI_CLASS_SP_DPIO 0x1100 +#define PCI_CLASS_SP_OTHER 0x1180 + +#define PCI_CLASS_OTHERS 0xff + +/* Vendors and devices. Sort key: vendor first, device next. */ + +#define PCI_VENDOR_ID_LOONGSON 0x0014 + +#define PCI_VENDOR_ID_TTTECH 0x0357 +#define PCI_DEVICE_ID_TTTECH_MC322 0x000a + +#define PCI_VENDOR_ID_DYNALINK 0x0675 +#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702 + +#define PCI_VENDOR_ID_UBIQUITI 0x0777 + +#define PCI_VENDOR_ID_BERKOM 0x0871 +#define PCI_DEVICE_ID_BERKOM_A1T 0xffa1 +#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xffa2 +#define PCI_DEVICE_ID_BERKOM_A4T 0xffa4 +#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xffa8 + +#define PCI_VENDOR_ID_COMPAQ 0x0e11 +#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508 +#define PCI_DEVICE_ID_COMPAQ_TACHYON 0xa0fc +#define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10 +#define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32 +#define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34 +#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33 +#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35 +#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40 +#define PCI_DEVICE_ID_COMPAQ_NETEL100PI 0xae43 +#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011 +#define PCI_DEVICE_ID_COMPAQ_CISS 0xb060 +#define PCI_DEVICE_ID_COMPAQ_CISSB 0xb178 +#define PCI_DEVICE_ID_COMPAQ_CISSC 0x46 +#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130 +#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150 + +#define PCI_VENDOR_ID_NCR 0x1000 +#define PCI_VENDOR_ID_LSI_LOGIC 0x1000 +#define PCI_DEVICE_ID_NCR_53C810 0x0001 +#define PCI_DEVICE_ID_NCR_53C820 0x0002 +#define PCI_DEVICE_ID_NCR_53C825 0x0003 +#define PCI_DEVICE_ID_NCR_53C815 0x0004 +#define PCI_DEVICE_ID_LSI_53C810AP 0x0005 +#define PCI_DEVICE_ID_NCR_53C860 0x0006 +#define PCI_DEVICE_ID_LSI_53C1510 0x000a +#define PCI_DEVICE_ID_NCR_53C896 0x000b +#define PCI_DEVICE_ID_NCR_53C895 0x000c +#define PCI_DEVICE_ID_NCR_53C885 0x000d +#define PCI_DEVICE_ID_NCR_53C875 0x000f +#define PCI_DEVICE_ID_NCR_53C1510 0x0010 +#define PCI_DEVICE_ID_LSI_53C895A 0x0012 +#define PCI_DEVICE_ID_LSI_53C875A 0x0013 +#define PCI_DEVICE_ID_LSI_53C1010_33 0x0020 +#define PCI_DEVICE_ID_LSI_53C1010_66 0x0021 +#define PCI_DEVICE_ID_LSI_53C1030 0x0030 +#define PCI_DEVICE_ID_LSI_1030_53C1035 0x0032 +#define PCI_DEVICE_ID_LSI_53C1035 0x0040 +#define PCI_DEVICE_ID_NCR_53C875J 0x008f +#define PCI_DEVICE_ID_LSI_FC909 0x0621 +#define PCI_DEVICE_ID_LSI_FC929 0x0622 +#define PCI_DEVICE_ID_LSI_FC929_LAN 0x0623 +#define PCI_DEVICE_ID_LSI_FC919 0x0624 +#define PCI_DEVICE_ID_LSI_FC919_LAN 0x0625 +#define PCI_DEVICE_ID_LSI_FC929X 0x0626 +#define PCI_DEVICE_ID_LSI_FC939X 0x0642 +#define PCI_DEVICE_ID_LSI_FC949X 0x0640 +#define PCI_DEVICE_ID_LSI_FC949ES 0x0646 +#define PCI_DEVICE_ID_LSI_FC919X 0x0628 +#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 +#define PCI_DEVICE_ID_LSI_61C102 0x0901 +#define PCI_DEVICE_ID_LSI_63C815 0x1000 +#define PCI_DEVICE_ID_LSI_SAS1064 0x0050 +#define PCI_DEVICE_ID_LSI_SAS1064R 0x0411 +#define PCI_DEVICE_ID_LSI_SAS1066 0x005E +#define PCI_DEVICE_ID_LSI_SAS1068 0x0054 +#define PCI_DEVICE_ID_LSI_SAS1064A 0x005C +#define PCI_DEVICE_ID_LSI_SAS1064E 0x0056 +#define PCI_DEVICE_ID_LSI_SAS1066E 0x005A +#define PCI_DEVICE_ID_LSI_SAS1068E 0x0058 +#define PCI_DEVICE_ID_LSI_SAS1078 0x0060 + +#define PCI_VENDOR_ID_ATI 0x1002 +/* Mach64 */ +#define PCI_DEVICE_ID_ATI_68800 0x4158 +#define PCI_DEVICE_ID_ATI_215CT222 0x4354 +#define PCI_DEVICE_ID_ATI_210888CX 0x4358 +#define PCI_DEVICE_ID_ATI_215ET222 0x4554 +/* Mach64 / Rage */ +#define PCI_DEVICE_ID_ATI_215GB 0x4742 +#define PCI_DEVICE_ID_ATI_215GD 0x4744 +#define PCI_DEVICE_ID_ATI_215GI 0x4749 +#define PCI_DEVICE_ID_ATI_215GP 0x4750 +#define PCI_DEVICE_ID_ATI_215GQ 0x4751 +#define PCI_DEVICE_ID_ATI_215XL 0x4752 +#define PCI_DEVICE_ID_ATI_215GT 0x4754 +#define PCI_DEVICE_ID_ATI_215GTB 0x4755 +#define PCI_DEVICE_ID_ATI_215_IV 0x4756 +#define PCI_DEVICE_ID_ATI_215_IW 0x4757 +#define PCI_DEVICE_ID_ATI_215_IZ 0x475A +#define PCI_DEVICE_ID_ATI_210888GX 0x4758 +#define PCI_DEVICE_ID_ATI_215_LB 0x4c42 +#define PCI_DEVICE_ID_ATI_215_LD 0x4c44 +#define PCI_DEVICE_ID_ATI_215_LG 0x4c47 +#define PCI_DEVICE_ID_ATI_215_LI 0x4c49 +#define PCI_DEVICE_ID_ATI_215_LM 0x4c4D +#define PCI_DEVICE_ID_ATI_215_LN 0x4c4E +#define PCI_DEVICE_ID_ATI_215_LR 0x4c52 +#define PCI_DEVICE_ID_ATI_215_LS 0x4c53 +#define PCI_DEVICE_ID_ATI_264_LT 0x4c54 +/* Mach64 VT */ +#define PCI_DEVICE_ID_ATI_264VT 0x5654 +#define PCI_DEVICE_ID_ATI_264VU 0x5655 +#define PCI_DEVICE_ID_ATI_264VV 0x5656 +/* Rage128 GL */ +#define PCI_DEVICE_ID_ATI_RAGE128_RE 0x5245 +#define PCI_DEVICE_ID_ATI_RAGE128_RF 0x5246 +#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x5247 +/* Rage128 VR */ +#define PCI_DEVICE_ID_ATI_RAGE128_RK 0x524b +#define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c +#define PCI_DEVICE_ID_ATI_RAGE128_SE 0x5345 +#define PCI_DEVICE_ID_ATI_RAGE128_SF 0x5346 +#define PCI_DEVICE_ID_ATI_RAGE128_SG 0x5347 +#define PCI_DEVICE_ID_ATI_RAGE128_SH 0x5348 +#define PCI_DEVICE_ID_ATI_RAGE128_SK 0x534b +#define PCI_DEVICE_ID_ATI_RAGE128_SL 0x534c +#define PCI_DEVICE_ID_ATI_RAGE128_SM 0x534d +#define PCI_DEVICE_ID_ATI_RAGE128_SN 0x534e +/* Rage128 Ultra */ +#define PCI_DEVICE_ID_ATI_RAGE128_TF 0x5446 +#define PCI_DEVICE_ID_ATI_RAGE128_TL 0x544c +#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452 +#define PCI_DEVICE_ID_ATI_RAGE128_TS 0x5453 +#define PCI_DEVICE_ID_ATI_RAGE128_TT 0x5454 +#define PCI_DEVICE_ID_ATI_RAGE128_TU 0x5455 +/* Rage128 M3 */ +#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45 +#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46 +/* Rage128 M4 */ +#define PCI_DEVICE_ID_ATI_RAGE128_MF 0x4d46 +#define PCI_DEVICE_ID_ATI_RAGE128_ML 0x4d4c +/* Rage128 Pro GL */ +#define PCI_DEVICE_ID_ATI_RAGE128_PA 0x5041 +#define PCI_DEVICE_ID_ATI_RAGE128_PB 0x5042 +#define PCI_DEVICE_ID_ATI_RAGE128_PC 0x5043 +#define PCI_DEVICE_ID_ATI_RAGE128_PD 0x5044 +#define PCI_DEVICE_ID_ATI_RAGE128_PE 0x5045 +#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046 +/* Rage128 Pro VR */ +#define PCI_DEVICE_ID_ATI_RAGE128_PG 0x5047 +#define PCI_DEVICE_ID_ATI_RAGE128_PH 0x5048 +#define PCI_DEVICE_ID_ATI_RAGE128_PI 0x5049 +#define PCI_DEVICE_ID_ATI_RAGE128_PJ 0x504A +#define PCI_DEVICE_ID_ATI_RAGE128_PK 0x504B +#define PCI_DEVICE_ID_ATI_RAGE128_PL 0x504C +#define PCI_DEVICE_ID_ATI_RAGE128_PM 0x504D +#define PCI_DEVICE_ID_ATI_RAGE128_PN 0x504E +#define PCI_DEVICE_ID_ATI_RAGE128_PO 0x504F +#define PCI_DEVICE_ID_ATI_RAGE128_PP 0x5050 +#define PCI_DEVICE_ID_ATI_RAGE128_PQ 0x5051 +#define PCI_DEVICE_ID_ATI_RAGE128_PR 0x5052 +#define PCI_DEVICE_ID_ATI_RAGE128_PS 0x5053 +#define PCI_DEVICE_ID_ATI_RAGE128_PT 0x5054 +#define PCI_DEVICE_ID_ATI_RAGE128_PU 0x5055 +#define PCI_DEVICE_ID_ATI_RAGE128_PV 0x5056 +#define PCI_DEVICE_ID_ATI_RAGE128_PW 0x5057 +#define PCI_DEVICE_ID_ATI_RAGE128_PX 0x5058 +/* Rage128 M4 */ +/* Radeon R100 */ +#define PCI_DEVICE_ID_ATI_RADEON_QD 0x5144 +#define PCI_DEVICE_ID_ATI_RADEON_QE 0x5145 +#define PCI_DEVICE_ID_ATI_RADEON_QF 0x5146 +#define PCI_DEVICE_ID_ATI_RADEON_QG 0x5147 +/* Radeon RV100 (VE) */ +#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 +#define PCI_DEVICE_ID_ATI_RADEON_QZ 0x515a +/* Radeon R200 (8500) */ +#define PCI_DEVICE_ID_ATI_RADEON_QL 0x514c +#define PCI_DEVICE_ID_ATI_RADEON_QN 0x514e +#define PCI_DEVICE_ID_ATI_RADEON_QO 0x514f +#define PCI_DEVICE_ID_ATI_RADEON_Ql 0x516c +#define PCI_DEVICE_ID_ATI_RADEON_BB 0x4242 +/* Radeon R200 (9100) */ +#define PCI_DEVICE_ID_ATI_RADEON_QM 0x514d +/* Radeon RV200 (7500) */ +#define PCI_DEVICE_ID_ATI_RADEON_QW 0x5157 +#define PCI_DEVICE_ID_ATI_RADEON_QX 0x5158 +/* Radeon NV-100 */ +/* Radeon RV250 (9000) */ +#define PCI_DEVICE_ID_ATI_RADEON_Id 0x4964 +#define PCI_DEVICE_ID_ATI_RADEON_Ie 0x4965 +#define PCI_DEVICE_ID_ATI_RADEON_If 0x4966 +#define PCI_DEVICE_ID_ATI_RADEON_Ig 0x4967 +/* Radeon RV280 (9200) */ +#define PCI_DEVICE_ID_ATI_RADEON_Ya 0x5961 +#define PCI_DEVICE_ID_ATI_RADEON_Yd 0x5964 +/* Radeon R300 (9500) */ +/* Radeon R300 (9700) */ +#define PCI_DEVICE_ID_ATI_RADEON_ND 0x4e44 +#define PCI_DEVICE_ID_ATI_RADEON_NE 0x4e45 +#define PCI_DEVICE_ID_ATI_RADEON_NF 0x4e46 +#define PCI_DEVICE_ID_ATI_RADEON_NG 0x4e47 +/* Radeon R350 (9800) */ +/* Radeon RV350 (9600) */ +/* Radeon M6 */ +#define PCI_DEVICE_ID_ATI_RADEON_LY 0x4c59 +#define PCI_DEVICE_ID_ATI_RADEON_LZ 0x4c5a +/* Radeon M7 */ +#define PCI_DEVICE_ID_ATI_RADEON_LW 0x4c57 +#define PCI_DEVICE_ID_ATI_RADEON_LX 0x4c58 +/* Radeon M9 */ +#define PCI_DEVICE_ID_ATI_RADEON_Ld 0x4c64 +#define PCI_DEVICE_ID_ATI_RADEON_Le 0x4c65 +#define PCI_DEVICE_ID_ATI_RADEON_Lf 0x4c66 +#define PCI_DEVICE_ID_ATI_RADEON_Lg 0x4c67 +/* Radeon */ +/* RadeonIGP */ +#define PCI_DEVICE_ID_ATI_RS100 0xcab0 +#define PCI_DEVICE_ID_ATI_RS200 0xcab2 +#define PCI_DEVICE_ID_ATI_RS200_B 0xcbb2 +#define PCI_DEVICE_ID_ATI_RS250 0xcab3 +#define PCI_DEVICE_ID_ATI_RS300_100 0x5830 +#define PCI_DEVICE_ID_ATI_RS300_133 0x5831 +#define PCI_DEVICE_ID_ATI_RS300_166 0x5832 +#define PCI_DEVICE_ID_ATI_RS300_200 0x5833 +#define PCI_DEVICE_ID_ATI_RS350_100 0x7830 +#define PCI_DEVICE_ID_ATI_RS350_133 0x7831 +#define PCI_DEVICE_ID_ATI_RS350_166 0x7832 +#define PCI_DEVICE_ID_ATI_RS350_200 0x7833 +#define PCI_DEVICE_ID_ATI_RS400_100 0x5a30 +#define PCI_DEVICE_ID_ATI_RS400_133 0x5a31 +#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32 +#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33 +#define PCI_DEVICE_ID_ATI_RS480 0x5950 +/* ATI IXP Chipset */ +#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 +#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 +#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 +#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 +#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e +#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 +#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 +#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 +#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a +#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380 +#define PCI_DEVICE_ID_ATI_SBX00_SMBUS 0x4385 +#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c +#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390 +#define PCI_DEVICE_ID_ATI_IXP700_IDE 0x439c + +#define PCI_VENDOR_ID_VLSI 0x1004 +#define PCI_DEVICE_ID_VLSI_82C592 0x0005 +#define PCI_DEVICE_ID_VLSI_82C593 0x0006 +#define PCI_DEVICE_ID_VLSI_82C594 0x0007 +#define PCI_DEVICE_ID_VLSI_82C597 0x0009 +#define PCI_DEVICE_ID_VLSI_82C541 0x000c +#define PCI_DEVICE_ID_VLSI_82C543 0x000d +#define PCI_DEVICE_ID_VLSI_82C532 0x0101 +#define PCI_DEVICE_ID_VLSI_82C534 0x0102 +#define PCI_DEVICE_ID_VLSI_82C535 0x0104 +#define PCI_DEVICE_ID_VLSI_82C147 0x0105 +#define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 + +/* AMD RD890 Chipset */ +#define PCI_DEVICE_ID_RD890_IOMMU 0x5a23 + +#define PCI_VENDOR_ID_ADL 0x1005 +#define PCI_DEVICE_ID_ADL_2301 0x2301 + +#define PCI_VENDOR_ID_NS 0x100b +#define PCI_DEVICE_ID_NS_87415 0x0002 +#define PCI_DEVICE_ID_NS_87560_LIO 0x000e +#define PCI_DEVICE_ID_NS_87560_USB 0x0012 +#define PCI_DEVICE_ID_NS_83815 0x0020 +#define PCI_DEVICE_ID_NS_83820 0x0022 +#define PCI_DEVICE_ID_NS_CS5535_ISA 0x002b +#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d +#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e +#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f +#define PCI_DEVICE_ID_NS_GX_VIDEO 0x0030 +#define PCI_DEVICE_ID_NS_SATURN 0x0035 +#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500 +#define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501 +#define PCI_DEVICE_ID_NS_SCx200_IDE 0x0502 +#define PCI_DEVICE_ID_NS_SCx200_AUDIO 0x0503 +#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504 +#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505 +#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510 +#define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 +#define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 +#define PCI_DEVICE_ID_NS_87410 0xd001 + +#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE 0x0028 + +#define PCI_VENDOR_ID_TSENG 0x100c +#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 +#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205 +#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206 +#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207 +#define PCI_DEVICE_ID_TSENG_ET6000 0x3208 + +#define PCI_VENDOR_ID_WEITEK 0x100e +#define PCI_DEVICE_ID_WEITEK_P9000 0x9001 +#define PCI_DEVICE_ID_WEITEK_P9100 0x9100 + +#define PCI_VENDOR_ID_DEC 0x1011 +#define PCI_DEVICE_ID_DEC_BRD 0x0001 +#define PCI_DEVICE_ID_DEC_TULIP 0x0002 +#define PCI_DEVICE_ID_DEC_TGA 0x0004 +#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 +#define PCI_DEVICE_ID_DEC_TGA2 0x000D +#define PCI_DEVICE_ID_DEC_FDDI 0x000F +#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 +#define PCI_DEVICE_ID_DEC_21142 0x0019 +#define PCI_DEVICE_ID_DEC_21052 0x0021 +#define PCI_DEVICE_ID_DEC_21150 0x0022 +#define PCI_DEVICE_ID_DEC_21152 0x0024 +#define PCI_DEVICE_ID_DEC_21153 0x0025 +#define PCI_DEVICE_ID_DEC_21154 0x0026 +#define PCI_DEVICE_ID_DEC_21285 0x1065 +#define PCI_DEVICE_ID_COMPAQ_42XX 0x0046 + +#define PCI_VENDOR_ID_CIRRUS 0x1013 +#define PCI_DEVICE_ID_CIRRUS_7548 0x0038 +#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 +#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4 +#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8 +#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac +#define PCI_DEVICE_ID_CIRRUS_5446 0x00b8 +#define PCI_DEVICE_ID_CIRRUS_5480 0x00bc +#define PCI_DEVICE_ID_CIRRUS_5462 0x00d0 +#define PCI_DEVICE_ID_CIRRUS_5464 0x00d4 +#define PCI_DEVICE_ID_CIRRUS_5465 0x00d6 +#define PCI_DEVICE_ID_CIRRUS_6729 0x1100 +#define PCI_DEVICE_ID_CIRRUS_6832 0x1110 +#define PCI_DEVICE_ID_CIRRUS_7543 0x1202 +#define PCI_DEVICE_ID_CIRRUS_4610 0x6001 +#define PCI_DEVICE_ID_CIRRUS_4612 0x6003 +#define PCI_DEVICE_ID_CIRRUS_4615 0x6004 + +#define PCI_VENDOR_ID_IBM 0x1014 +#define PCI_DEVICE_ID_IBM_TR 0x0018 +#define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e +#define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc +#define PCI_DEVICE_ID_IBM_SNIPE 0x0180 +#define PCI_DEVICE_ID_IBM_CITRINE 0x028C +#define PCI_DEVICE_ID_IBM_GEMSTONE 0xB166 +#define PCI_DEVICE_ID_IBM_OBSIDIAN 0x02BD +#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1 0x0031 +#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2 0x0219 +#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX 0x021A +#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251 +#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361 +#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252 + +#define PCI_SUBVENDOR_ID_IBM 0x1014 +#define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4 + +#define PCI_VENDOR_ID_UNISYS 0x1018 +#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C + +#define PCI_VENDOR_ID_COMPEX2 0x101a /* pci.ids says "AT&T GIS (NCR)" */ +#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005 + +#define PCI_VENDOR_ID_WD 0x101c +#define PCI_DEVICE_ID_WD_90C 0xc24a + +#define PCI_VENDOR_ID_AMI 0x101e +#define PCI_DEVICE_ID_AMI_MEGARAID3 0x1960 +#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010 +#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 + +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_K8_NB 0x1100 +#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP 0x1101 +#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102 +#define PCI_DEVICE_ID_AMD_K8_NB_MISC 0x1103 +#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200 +#define PCI_DEVICE_ID_AMD_10H_NB_MAP 0x1201 +#define PCI_DEVICE_ID_AMD_10H_NB_DRAM 0x1202 +#define PCI_DEVICE_ID_AMD_10H_NB_MISC 0x1203 +#define PCI_DEVICE_ID_AMD_10H_NB_LINK 0x1204 +#define PCI_DEVICE_ID_AMD_11H_NB_HT 0x1300 +#define PCI_DEVICE_ID_AMD_11H_NB_MAP 0x1301 +#define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 +#define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 +#define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 +#define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573 +#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574 +#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 +#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 +#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 +#define PCI_DEVICE_ID_AMD_15H_NB_F3 0x1603 +#define PCI_DEVICE_ID_AMD_15H_NB_F4 0x1604 +#define PCI_DEVICE_ID_AMD_15H_NB_F5 0x1605 +#define PCI_DEVICE_ID_AMD_16H_NB_F3 0x1533 +#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534 +#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F3 0x1583 +#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F4 0x1584 +#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 +#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb +#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F3 0x1493 +#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F3 0x144b +#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F3 0x1443 +#define PCI_DEVICE_ID_AMD_VANGOGH_USB 0x163a +#define PCI_DEVICE_ID_AMD_19H_DF_F3 0x1653 +#define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 +#define PCI_DEVICE_ID_AMD_LANCE 0x2000 +#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 +#define PCI_DEVICE_ID_AMD_SCSI 0x2020 +#define PCI_DEVICE_ID_AMD_SERENADE 0x36c0 +#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 +#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007 +#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C +#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E +#define PCI_DEVICE_ID_AMD_COBRA_7401 0x7401 +#define PCI_DEVICE_ID_AMD_VIPER_7409 0x7409 +#define PCI_DEVICE_ID_AMD_VIPER_740B 0x740B +#define PCI_DEVICE_ID_AMD_VIPER_7410 0x7410 +#define PCI_DEVICE_ID_AMD_VIPER_7411 0x7411 +#define PCI_DEVICE_ID_AMD_VIPER_7413 0x7413 +#define PCI_DEVICE_ID_AMD_VIPER_7440 0x7440 +#define PCI_DEVICE_ID_AMD_OPUS_7441 0x7441 +#define PCI_DEVICE_ID_AMD_OPUS_7443 0x7443 +#define PCI_DEVICE_ID_AMD_VIPER_7443 0x7443 +#define PCI_DEVICE_ID_AMD_OPUS_7445 0x7445 +#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 +#define PCI_DEVICE_ID_AMD_8111_PCI 0x7460 +#define PCI_DEVICE_ID_AMD_8111_LPC 0x7468 +#define PCI_DEVICE_ID_AMD_8111_IDE 0x7469 +#define PCI_DEVICE_ID_AMD_8111_SMBUS2 0x746a +#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b +#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d +#define PCI_DEVICE_ID_AMD_8151_0 0x7454 +#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 +#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451 +#define PCI_DEVICE_ID_AMD_8132_BRIDGE 0x7458 +#define PCI_DEVICE_ID_AMD_NL_USB 0x7912 +#define PCI_DEVICE_ID_AMD_CS5535_IDE 0x208F +#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 +#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 +#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 +#define PCI_DEVICE_ID_AMD_CS5536_OHC 0x2094 +#define PCI_DEVICE_ID_AMD_CS5536_EHC 0x2095 +#define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096 +#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 +#define PCI_DEVICE_ID_AMD_CS5536_DEV_IDE 0x2092 +#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A +#define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 +#define PCI_DEVICE_ID_AMD_LX_AES 0x2082 +#define PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE 0x7800 +#define PCI_DEVICE_ID_AMD_HUDSON2_SMBUS 0x780b +#define PCI_DEVICE_ID_AMD_HUDSON2_IDE 0x780c +#define PCI_DEVICE_ID_AMD_KERNCZ_SMBUS 0x790b + +#define PCI_VENDOR_ID_TRIDENT 0x1023 +#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 +#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 +#define PCI_DEVICE_ID_TRIDENT_9320 0x9320 +#define PCI_DEVICE_ID_TRIDENT_9388 0x9388 +#define PCI_DEVICE_ID_TRIDENT_9397 0x9397 +#define PCI_DEVICE_ID_TRIDENT_939A 0x939A +#define PCI_DEVICE_ID_TRIDENT_9520 0x9520 +#define PCI_DEVICE_ID_TRIDENT_9525 0x9525 +#define PCI_DEVICE_ID_TRIDENT_9420 0x9420 +#define PCI_DEVICE_ID_TRIDENT_9440 0x9440 +#define PCI_DEVICE_ID_TRIDENT_9660 0x9660 +#define PCI_DEVICE_ID_TRIDENT_9750 0x9750 +#define PCI_DEVICE_ID_TRIDENT_9850 0x9850 +#define PCI_DEVICE_ID_TRIDENT_9880 0x9880 +#define PCI_DEVICE_ID_TRIDENT_8400 0x8400 +#define PCI_DEVICE_ID_TRIDENT_8420 0x8420 +#define PCI_DEVICE_ID_TRIDENT_8500 0x8500 + +#define PCI_VENDOR_ID_AI 0x1025 +#define PCI_DEVICE_ID_AI_M1435 0x1435 + +#define PCI_VENDOR_ID_DELL 0x1028 +#define PCI_DEVICE_ID_DELL_RACIII 0x0008 +#define PCI_DEVICE_ID_DELL_RAC4 0x0012 +#define PCI_DEVICE_ID_DELL_PERC5 0x0015 + +#define PCI_VENDOR_ID_MATROX 0x102B +#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 +#define PCI_DEVICE_ID_MATROX_MIL 0x0519 +#define PCI_DEVICE_ID_MATROX_MYS 0x051A +#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b +#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e +#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f +#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 +#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 +#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 +#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 +#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521 +#define PCI_DEVICE_ID_MATROX_G400 0x0525 +#define PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530 +#define PCI_DEVICE_ID_MATROX_G550 0x2527 +#define PCI_DEVICE_ID_MATROX_VIA 0x4536 + +#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS 0x14f2 + +#define PCI_VENDOR_ID_CT 0x102c +#define PCI_DEVICE_ID_CT_69000 0x00c0 +#define PCI_DEVICE_ID_CT_65545 0x00d8 +#define PCI_DEVICE_ID_CT_65548 0x00dc +#define PCI_DEVICE_ID_CT_65550 0x00e0 +#define PCI_DEVICE_ID_CT_65554 0x00e4 +#define PCI_DEVICE_ID_CT_65555 0x00e5 + +#define PCI_VENDOR_ID_MIRO 0x1031 +#define PCI_DEVICE_ID_MIRO_36050 0x5601 +#define PCI_DEVICE_ID_MIRO_DC10PLUS 0x7efe +#define PCI_DEVICE_ID_MIRO_DC30PLUS 0xd801 + +#define PCI_VENDOR_ID_NEC 0x1033 +#define PCI_DEVICE_ID_NEC_CBUS_1 0x0001 /* PCI-Cbus Bridge */ +#define PCI_DEVICE_ID_NEC_LOCAL 0x0002 /* Local Bridge */ +#define PCI_DEVICE_ID_NEC_ATM 0x0003 /* ATM LAN Controller */ +#define PCI_DEVICE_ID_NEC_R4000 0x0004 /* R4000 Bridge */ +#define PCI_DEVICE_ID_NEC_486 0x0005 /* 486 Like Peripheral Bus Bridge */ +#define PCI_DEVICE_ID_NEC_ACCEL_1 0x0006 /* Graphic Accelerator */ +#define PCI_DEVICE_ID_NEC_UXBUS 0x0007 /* UX-Bus Bridge */ +#define PCI_DEVICE_ID_NEC_ACCEL_2 0x0008 /* Graphic Accelerator */ +#define PCI_DEVICE_ID_NEC_GRAPH 0x0009 /* PCI-CoreGraph Bridge */ +#define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */ +#define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */ +#define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */ +#define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */ +#define PCI_DEVICE_ID_NEC_CBUS_3 0x003b +#define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e +#define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */ +#define PCI_DEVICE_ID_NEC_VRC5476 0x009b +#define PCI_DEVICE_ID_NEC_VRC4173 0x00a5 +#define PCI_DEVICE_ID_NEC_VRC5477_AC97 0x00a6 +#define PCI_DEVICE_ID_NEC_PC9821CS01 0x800c /* PC-9821-CS01 */ +#define PCI_DEVICE_ID_NEC_PC9821NRB06 0x800d /* PC-9821NR-B06 */ + +#define PCI_VENDOR_ID_FD 0x1036 +#define PCI_DEVICE_ID_FD_36C70 0x0000 + +#define PCI_VENDOR_ID_SI 0x1039 +#define PCI_DEVICE_ID_SI_5591_AGP 0x0001 +#define PCI_DEVICE_ID_SI_6202 0x0002 +#define PCI_DEVICE_ID_SI_503 0x0008 +#define PCI_DEVICE_ID_SI_ACPI 0x0009 +#define PCI_DEVICE_ID_SI_SMBUS 0x0016 +#define PCI_DEVICE_ID_SI_LPC 0x0018 +#define PCI_DEVICE_ID_SI_5597_VGA 0x0200 +#define PCI_DEVICE_ID_SI_6205 0x0205 +#define PCI_DEVICE_ID_SI_501 0x0406 +#define PCI_DEVICE_ID_SI_496 0x0496 +#define PCI_DEVICE_ID_SI_300 0x0300 +#define PCI_DEVICE_ID_SI_315H 0x0310 +#define PCI_DEVICE_ID_SI_315 0x0315 +#define PCI_DEVICE_ID_SI_315PRO 0x0325 +#define PCI_DEVICE_ID_SI_530 0x0530 +#define PCI_DEVICE_ID_SI_540 0x0540 +#define PCI_DEVICE_ID_SI_550 0x0550 +#define PCI_DEVICE_ID_SI_540_VGA 0x5300 +#define PCI_DEVICE_ID_SI_550_VGA 0x5315 +#define PCI_DEVICE_ID_SI_620 0x0620 +#define PCI_DEVICE_ID_SI_630 0x0630 +#define PCI_DEVICE_ID_SI_633 0x0633 +#define PCI_DEVICE_ID_SI_635 0x0635 +#define PCI_DEVICE_ID_SI_640 0x0640 +#define PCI_DEVICE_ID_SI_645 0x0645 +#define PCI_DEVICE_ID_SI_646 0x0646 +#define PCI_DEVICE_ID_SI_648 0x0648 +#define PCI_DEVICE_ID_SI_650 0x0650 +#define PCI_DEVICE_ID_SI_651 0x0651 +#define PCI_DEVICE_ID_SI_655 0x0655 +#define PCI_DEVICE_ID_SI_661 0x0661 +#define PCI_DEVICE_ID_SI_730 0x0730 +#define PCI_DEVICE_ID_SI_733 0x0733 +#define PCI_DEVICE_ID_SI_630_VGA 0x6300 +#define PCI_DEVICE_ID_SI_735 0x0735 +#define PCI_DEVICE_ID_SI_740 0x0740 +#define PCI_DEVICE_ID_SI_741 0x0741 +#define PCI_DEVICE_ID_SI_745 0x0745 +#define PCI_DEVICE_ID_SI_746 0x0746 +#define PCI_DEVICE_ID_SI_755 0x0755 +#define PCI_DEVICE_ID_SI_760 0x0760 +#define PCI_DEVICE_ID_SI_900 0x0900 +#define PCI_DEVICE_ID_SI_961 0x0961 +#define PCI_DEVICE_ID_SI_962 0x0962 +#define PCI_DEVICE_ID_SI_963 0x0963 +#define PCI_DEVICE_ID_SI_965 0x0965 +#define PCI_DEVICE_ID_SI_966 0x0966 +#define PCI_DEVICE_ID_SI_968 0x0968 +#define PCI_DEVICE_ID_SI_1180 0x1180 +#define PCI_DEVICE_ID_SI_5511 0x5511 +#define PCI_DEVICE_ID_SI_5513 0x5513 +#define PCI_DEVICE_ID_SI_5517 0x5517 +#define PCI_DEVICE_ID_SI_5518 0x5518 +#define PCI_DEVICE_ID_SI_5571 0x5571 +#define PCI_DEVICE_ID_SI_5581 0x5581 +#define PCI_DEVICE_ID_SI_5582 0x5582 +#define PCI_DEVICE_ID_SI_5591 0x5591 +#define PCI_DEVICE_ID_SI_5596 0x5596 +#define PCI_DEVICE_ID_SI_5597 0x5597 +#define PCI_DEVICE_ID_SI_5598 0x5598 +#define PCI_DEVICE_ID_SI_5600 0x5600 +#define PCI_DEVICE_ID_SI_7012 0x7012 +#define PCI_DEVICE_ID_SI_7013 0x7013 +#define PCI_DEVICE_ID_SI_7016 0x7016 +#define PCI_DEVICE_ID_SI_7018 0x7018 + +#define PCI_VENDOR_ID_HP 0x103c +#define PCI_VENDOR_ID_HP_3PAR 0x1590 +#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 +#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a +#define PCI_DEVICE_ID_HP_TACHYON 0x1028 +#define PCI_DEVICE_ID_HP_TACHLITE 0x1029 +#define PCI_DEVICE_ID_HP_J2585A 0x1030 +#define PCI_DEVICE_ID_HP_J2585B 0x1031 +#define PCI_DEVICE_ID_HP_J2973A 0x1040 +#define PCI_DEVICE_ID_HP_J2970A 0x1042 +#define PCI_DEVICE_ID_HP_DIVA 0x1048 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A +#define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 +#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b +#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 +#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 +#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 +#define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a +#define PCI_DEVICE_ID_HP_PCIX_LBA 0x122e +#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c +#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 +#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 +#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 +#define PCI_DEVICE_ID_HP_DIVA_HURRICANE 0x132a +#define PCI_DEVICE_ID_HP_CISSA 0x3220 +#define PCI_DEVICE_ID_HP_CISSC 0x3230 +#define PCI_DEVICE_ID_HP_CISSD 0x3238 +#define PCI_DEVICE_ID_HP_CISSE 0x323a +#define PCI_DEVICE_ID_HP_CISSF 0x323b +#define PCI_DEVICE_ID_HP_CISSH 0x323c +#define PCI_DEVICE_ID_HP_CISSI 0x3239 +#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 + +#define PCI_VENDOR_ID_PCTECH 0x1042 +#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 +#define PCI_DEVICE_ID_PCTECH_RZ1001 0x1001 +#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020 + +#define PCI_VENDOR_ID_ASUSTEK 0x1043 +#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675 + +#define PCI_VENDOR_ID_DPT 0x1044 +#define PCI_DEVICE_ID_DPT 0xa400 + +#define PCI_VENDOR_ID_OPTI 0x1045 +#define PCI_DEVICE_ID_OPTI_82C558 0xc558 +#define PCI_DEVICE_ID_OPTI_82C621 0xc621 +#define PCI_DEVICE_ID_OPTI_82C700 0xc700 +#define PCI_DEVICE_ID_OPTI_82C825 0xd568 + +#define PCI_VENDOR_ID_ELSA 0x1048 +#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000 +#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 + +#define PCI_VENDOR_ID_STMICRO 0x104A +#define PCI_DEVICE_ID_STMICRO_USB_HOST 0xCC00 +#define PCI_DEVICE_ID_STMICRO_USB_OHCI 0xCC01 +#define PCI_DEVICE_ID_STMICRO_USB_OTG 0xCC02 +#define PCI_DEVICE_ID_STMICRO_UART_HWFC 0xCC03 +#define PCI_DEVICE_ID_STMICRO_UART_NO_HWFC 0xCC04 +#define PCI_DEVICE_ID_STMICRO_SOC_DMA 0xCC05 +#define PCI_DEVICE_ID_STMICRO_SATA 0xCC06 +#define PCI_DEVICE_ID_STMICRO_I2C 0xCC07 +#define PCI_DEVICE_ID_STMICRO_SPI_HS 0xCC08 +#define PCI_DEVICE_ID_STMICRO_MAC 0xCC09 +#define PCI_DEVICE_ID_STMICRO_SDIO_EMMC 0xCC0A +#define PCI_DEVICE_ID_STMICRO_SDIO 0xCC0B +#define PCI_DEVICE_ID_STMICRO_GPIO 0xCC0C +#define PCI_DEVICE_ID_STMICRO_VIP 0xCC0D +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA 0xCC0E +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_SRCS 0xCC0F +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS 0xCC10 +#define PCI_DEVICE_ID_STMICRO_CAN 0xCC11 +#define PCI_DEVICE_ID_STMICRO_MLB 0xCC12 +#define PCI_DEVICE_ID_STMICRO_DBP 0xCC13 +#define PCI_DEVICE_ID_STMICRO_SATA_PHY 0xCC14 +#define PCI_DEVICE_ID_STMICRO_ESRAM 0xCC15 +#define PCI_DEVICE_ID_STMICRO_VIC 0xCC16 + +#define PCI_VENDOR_ID_BUSLOGIC 0x104B +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040 +#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130 + +#define PCI_VENDOR_ID_TI 0x104c +#define PCI_DEVICE_ID_TI_TVP4020 0x3d07 +#define PCI_DEVICE_ID_TI_4450 0x8011 +#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 +#define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 +#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034 +#define PCI_DEVICE_ID_TI_X515 0x8036 +#define PCI_DEVICE_ID_TI_XX12 0x8039 +#define PCI_DEVICE_ID_TI_XX12_FM 0x803b +#define PCI_DEVICE_ID_TI_XIO2000A 0x8231 +#define PCI_DEVICE_ID_TI_1130 0xac12 +#define PCI_DEVICE_ID_TI_1031 0xac13 +#define PCI_DEVICE_ID_TI_1131 0xac15 +#define PCI_DEVICE_ID_TI_1250 0xac16 +#define PCI_DEVICE_ID_TI_1220 0xac17 +#define PCI_DEVICE_ID_TI_1221 0xac19 +#define PCI_DEVICE_ID_TI_1210 0xac1a +#define PCI_DEVICE_ID_TI_1450 0xac1b +#define PCI_DEVICE_ID_TI_1225 0xac1c +#define PCI_DEVICE_ID_TI_1251A 0xac1d +#define PCI_DEVICE_ID_TI_1211 0xac1e +#define PCI_DEVICE_ID_TI_1251B 0xac1f +#define PCI_DEVICE_ID_TI_4410 0xac41 +#define PCI_DEVICE_ID_TI_4451 0xac42 +#define PCI_DEVICE_ID_TI_4510 0xac44 +#define PCI_DEVICE_ID_TI_4520 0xac46 +#define PCI_DEVICE_ID_TI_7510 0xac47 +#define PCI_DEVICE_ID_TI_7610 0xac48 +#define PCI_DEVICE_ID_TI_7410 0xac49 +#define PCI_DEVICE_ID_TI_1410 0xac50 +#define PCI_DEVICE_ID_TI_1420 0xac51 +#define PCI_DEVICE_ID_TI_1451A 0xac52 +#define PCI_DEVICE_ID_TI_1620 0xac54 +#define PCI_DEVICE_ID_TI_1520 0xac55 +#define PCI_DEVICE_ID_TI_1510 0xac56 +#define PCI_DEVICE_ID_TI_X620 0xac8d +#define PCI_DEVICE_ID_TI_X420 0xac8e +#define PCI_DEVICE_ID_TI_XX20_FM 0xac8f +#define PCI_DEVICE_ID_TI_DRA74x 0xb500 +#define PCI_DEVICE_ID_TI_DRA72x 0xb501 + +#define PCI_VENDOR_ID_SONY 0x104d + +/* Winbond have two vendor IDs! See 0x10ad as well */ +#define PCI_VENDOR_ID_WINBOND2 0x1050 +#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a +#define PCI_DEVICE_ID_WINBOND2_6692 0x6692 + +#define PCI_VENDOR_ID_ANIGMA 0x1051 +#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 + +#define PCI_VENDOR_ID_EFAR 0x1055 +#define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130 +#define PCI_DEVICE_ID_EFAR_SLC90E66_3 0x9463 + +#define PCI_VENDOR_ID_MOTOROLA 0x1057 +#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001 +#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 +#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004 +#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801 +#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802 +#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803 +#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b +#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803 +#define PCI_DEVICE_ID_MOTOROLA_MPC5200B 0x5809 + +#define PCI_VENDOR_ID_PROMISE 0x105a +#define PCI_DEVICE_ID_PROMISE_20265 0x0d30 +#define PCI_DEVICE_ID_PROMISE_20267 0x4d30 +#define PCI_DEVICE_ID_PROMISE_20246 0x4d33 +#define PCI_DEVICE_ID_PROMISE_20262 0x4d38 +#define PCI_DEVICE_ID_PROMISE_20263 0x0D38 +#define PCI_DEVICE_ID_PROMISE_20268 0x4d68 +#define PCI_DEVICE_ID_PROMISE_20269 0x4d69 +#define PCI_DEVICE_ID_PROMISE_20270 0x6268 +#define PCI_DEVICE_ID_PROMISE_20271 0x6269 +#define PCI_DEVICE_ID_PROMISE_20275 0x1275 +#define PCI_DEVICE_ID_PROMISE_20276 0x5275 +#define PCI_DEVICE_ID_PROMISE_20277 0x7275 + +#define PCI_VENDOR_ID_FOXCONN 0x105b + +#define PCI_VENDOR_ID_UMC 0x1060 +#define PCI_DEVICE_ID_UMC_UM8673F 0x0101 +#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a +#define PCI_DEVICE_ID_UMC_UM8886A 0x886a + +#define PCI_VENDOR_ID_PICOPOWER 0x1066 +#define PCI_DEVICE_ID_PICOPOWER_PT86C523 0x0002 +#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP 0x8002 + +#define PCI_VENDOR_ID_MYLEX 0x1069 +#define PCI_DEVICE_ID_MYLEX_DAC960_P 0x0001 +#define PCI_DEVICE_ID_MYLEX_DAC960_PD 0x0002 +#define PCI_DEVICE_ID_MYLEX_DAC960_PG 0x0010 +#define PCI_DEVICE_ID_MYLEX_DAC960_LA 0x0020 +#define PCI_DEVICE_ID_MYLEX_DAC960_LP 0x0050 +#define PCI_DEVICE_ID_MYLEX_DAC960_BA 0xBA56 +#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166 + +#define PCI_VENDOR_ID_APPLE 0x106b +#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001 +#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e +#define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 +#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021 +#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP 0x0024 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P 0x0027 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15 0x002d +#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15 0x002e +#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2 0x0032 +#define PCI_DEVICE_ID_APPLE_UNI_N_ATA 0x0033 +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034 +#define PCI_DEVICE_ID_APPLE_IPID_ATA100 0x003b +#define PCI_DEVICE_ID_APPLE_K2_ATA100 0x0043 +#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b +#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c +#define PCI_DEVICE_ID_APPLE_SH_ATA 0x0050 +#define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 +#define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 +#define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 +#define PCI_DEVICE_ID_APPLE_U4_PCIE 0x005b +#define PCI_DEVICE_ID_APPLE_IPID2_AGP 0x0066 +#define PCI_DEVICE_ID_APPLE_IPID2_ATA 0x0069 +#define PCI_DEVICE_ID_APPLE_IPID2_FW 0x006a +#define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b +#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 + +#define PCI_VENDOR_ID_YAMAHA 0x1073 +#define PCI_DEVICE_ID_YAMAHA_724 0x0004 +#define PCI_DEVICE_ID_YAMAHA_724F 0x000d +#define PCI_DEVICE_ID_YAMAHA_740 0x000a +#define PCI_DEVICE_ID_YAMAHA_740C 0x000c +#define PCI_DEVICE_ID_YAMAHA_744 0x0010 +#define PCI_DEVICE_ID_YAMAHA_754 0x0012 + +#define PCI_VENDOR_ID_QLOGIC 0x1077 +#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 +#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 +#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 +#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 +#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 +#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 +#define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 +#define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 +#define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 +#define PCI_DEVICE_ID_QLOGIC_ISP2312 0x2312 +#define PCI_DEVICE_ID_QLOGIC_ISP2322 0x2322 +#define PCI_DEVICE_ID_QLOGIC_ISP6312 0x6312 +#define PCI_DEVICE_ID_QLOGIC_ISP6322 0x6322 +#define PCI_DEVICE_ID_QLOGIC_ISP2422 0x2422 +#define PCI_DEVICE_ID_QLOGIC_ISP2432 0x2432 +#define PCI_DEVICE_ID_QLOGIC_ISP2512 0x2512 +#define PCI_DEVICE_ID_QLOGIC_ISP2522 0x2522 +#define PCI_DEVICE_ID_QLOGIC_ISP5422 0x5422 +#define PCI_DEVICE_ID_QLOGIC_ISP5432 0x5432 + +#define PCI_VENDOR_ID_CYRIX 0x1078 +#define PCI_DEVICE_ID_CYRIX_5510 0x0000 +#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001 +#define PCI_DEVICE_ID_CYRIX_5520 0x0002 +#define PCI_DEVICE_ID_CYRIX_5530_LEGACY 0x0100 +#define PCI_DEVICE_ID_CYRIX_5530_IDE 0x0102 +#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103 +#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104 + +#define PCI_VENDOR_ID_CONTAQ 0x1080 +#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693 + +#define PCI_VENDOR_ID_OLICOM 0x108d +#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012 +#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013 +#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014 + +#define PCI_VENDOR_ID_SUN 0x108e +#define PCI_DEVICE_ID_SUN_EBUS 0x1000 +#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001 +#define PCI_DEVICE_ID_SUN_RIO_EBUS 0x1100 +#define PCI_DEVICE_ID_SUN_RIO_GEM 0x1101 +#define PCI_DEVICE_ID_SUN_RIO_1394 0x1102 +#define PCI_DEVICE_ID_SUN_RIO_USB 0x1103 +#define PCI_DEVICE_ID_SUN_GEM 0x2bad +#define PCI_DEVICE_ID_SUN_SIMBA 0x5000 +#define PCI_DEVICE_ID_SUN_PBM 0x8000 +#define PCI_DEVICE_ID_SUN_SCHIZO 0x8001 +#define PCI_DEVICE_ID_SUN_SABRE 0xa000 +#define PCI_DEVICE_ID_SUN_HUMMINGBIRD 0xa001 +#define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801 +#define PCI_DEVICE_ID_SUN_CASSINI 0xabba + +#define PCI_VENDOR_ID_NI 0x1093 +#define PCI_DEVICE_ID_NI_PCI2322 0xd130 +#define PCI_DEVICE_ID_NI_PCI2324 0xd140 +#define PCI_DEVICE_ID_NI_PCI2328 0xd150 +#define PCI_DEVICE_ID_NI_PXI8422_2322 0xd190 +#define PCI_DEVICE_ID_NI_PXI8422_2324 0xd1a0 +#define PCI_DEVICE_ID_NI_PXI8420_2322 0xd1d0 +#define PCI_DEVICE_ID_NI_PXI8420_2324 0xd1e0 +#define PCI_DEVICE_ID_NI_PXI8420_2328 0xd1f0 +#define PCI_DEVICE_ID_NI_PXI8420_23216 0xd1f1 +#define PCI_DEVICE_ID_NI_PCI2322I 0xd250 +#define PCI_DEVICE_ID_NI_PCI2324I 0xd270 +#define PCI_DEVICE_ID_NI_PCI23216 0xd2b0 +#define PCI_DEVICE_ID_NI_PXI8430_2322 0x7080 +#define PCI_DEVICE_ID_NI_PCI8430_2322 0x70db +#define PCI_DEVICE_ID_NI_PXI8430_2324 0x70dd +#define PCI_DEVICE_ID_NI_PCI8430_2324 0x70df +#define PCI_DEVICE_ID_NI_PXI8430_2328 0x70e2 +#define PCI_DEVICE_ID_NI_PCI8430_2328 0x70e4 +#define PCI_DEVICE_ID_NI_PXI8430_23216 0x70e6 +#define PCI_DEVICE_ID_NI_PCI8430_23216 0x70e7 +#define PCI_DEVICE_ID_NI_PXI8432_2322 0x70e8 +#define PCI_DEVICE_ID_NI_PCI8432_2322 0x70ea +#define PCI_DEVICE_ID_NI_PXI8432_2324 0x70ec +#define PCI_DEVICE_ID_NI_PCI8432_2324 0x70ee + +#define PCI_VENDOR_ID_CMD 0x1095 +#define PCI_DEVICE_ID_CMD_643 0x0643 +#define PCI_DEVICE_ID_CMD_646 0x0646 +#define PCI_DEVICE_ID_CMD_648 0x0648 +#define PCI_DEVICE_ID_CMD_649 0x0649 + +#define PCI_DEVICE_ID_SII_680 0x0680 +#define PCI_DEVICE_ID_SII_3112 0x3112 +#define PCI_DEVICE_ID_SII_1210SA 0x0240 + +#define PCI_VENDOR_ID_BROOKTREE 0x109e +#define PCI_DEVICE_ID_BROOKTREE_878 0x0878 +#define PCI_DEVICE_ID_BROOKTREE_879 0x0879 + +#define PCI_VENDOR_ID_SGI 0x10a9 +#define PCI_DEVICE_ID_SGI_IOC3 0x0003 +#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002 + +#define PCI_VENDOR_ID_WINBOND 0x10ad +#define PCI_DEVICE_ID_WINBOND_82C105 0x0105 +#define PCI_DEVICE_ID_WINBOND_83C553 0x0565 + +#define PCI_VENDOR_ID_PLX 0x10b5 +#define PCI_DEVICE_ID_PLX_R685 0x1030 +#define PCI_DEVICE_ID_PLX_ROMULUS 0x106a +#define PCI_DEVICE_ID_PLX_SPCOM800 0x1076 +#define PCI_DEVICE_ID_PLX_1077 0x1077 +#define PCI_DEVICE_ID_PLX_SPCOM200 0x1103 +#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 +#define PCI_DEVICE_ID_PLX_R753 0x1152 +#define PCI_DEVICE_ID_PLX_OLITEC 0x1187 +#define PCI_DEVICE_ID_PLX_PCI200SYN 0x3196 +#define PCI_DEVICE_ID_PLX_9030 0x9030 +#define PCI_DEVICE_ID_PLX_9050 0x9050 +#define PCI_DEVICE_ID_PLX_9056 0x9056 +#define PCI_DEVICE_ID_PLX_9080 0x9080 +#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001 + +#define PCI_VENDOR_ID_MADGE 0x10b6 +#define PCI_DEVICE_ID_MADGE_MK2 0x0002 + +#define PCI_VENDOR_ID_3COM 0x10b7 +#define PCI_DEVICE_ID_3COM_3C985 0x0001 +#define PCI_DEVICE_ID_3COM_3C940 0x1700 +#define PCI_DEVICE_ID_3COM_3C339 0x3390 +#define PCI_DEVICE_ID_3COM_3C359 0x3590 +#define PCI_DEVICE_ID_3COM_3C940B 0x80eb +#define PCI_DEVICE_ID_3COM_3CR990 0x9900 +#define PCI_DEVICE_ID_3COM_3CR990_TX_95 0x9902 +#define PCI_DEVICE_ID_3COM_3CR990_TX_97 0x9903 +#define PCI_DEVICE_ID_3COM_3CR990B 0x9904 +#define PCI_DEVICE_ID_3COM_3CR990_FX 0x9905 +#define PCI_DEVICE_ID_3COM_3CR990SVR95 0x9908 +#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909 +#define PCI_DEVICE_ID_3COM_3CR990SVR 0x990a + +#define PCI_VENDOR_ID_AL 0x10b9 +#define PCI_DEVICE_ID_AL_M1533 0x1533 +#define PCI_DEVICE_ID_AL_M1535 0x1535 +#define PCI_DEVICE_ID_AL_M1541 0x1541 +#define PCI_DEVICE_ID_AL_M1563 0x1563 +#define PCI_DEVICE_ID_AL_M1621 0x1621 +#define PCI_DEVICE_ID_AL_M1631 0x1631 +#define PCI_DEVICE_ID_AL_M1632 0x1632 +#define PCI_DEVICE_ID_AL_M1641 0x1641 +#define PCI_DEVICE_ID_AL_M1644 0x1644 +#define PCI_DEVICE_ID_AL_M1647 0x1647 +#define PCI_DEVICE_ID_AL_M1651 0x1651 +#define PCI_DEVICE_ID_AL_M1671 0x1671 +#define PCI_DEVICE_ID_AL_M1681 0x1681 +#define PCI_DEVICE_ID_AL_M1683 0x1683 +#define PCI_DEVICE_ID_AL_M1689 0x1689 +#define PCI_DEVICE_ID_AL_M5219 0x5219 +#define PCI_DEVICE_ID_AL_M5228 0x5228 +#define PCI_DEVICE_ID_AL_M5229 0x5229 +#define PCI_DEVICE_ID_AL_M5451 0x5451 +#define PCI_DEVICE_ID_AL_M7101 0x7101 + +#define PCI_VENDOR_ID_NEOMAGIC 0x10c8 +#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 +#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006 +#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016 + +#define PCI_VENDOR_ID_TCONRAD 0x10da +#define PCI_DEVICE_ID_TCONRAD_TOKENRING 0x0508 + +#define PCI_VENDOR_ID_ROHM 0x10db + +#define PCI_VENDOR_ID_NVIDIA 0x10de +#define PCI_DEVICE_ID_NVIDIA_TNT 0x0020 +#define PCI_DEVICE_ID_NVIDIA_TNT2 0x0028 +#define PCI_DEVICE_ID_NVIDIA_UTNT2 0x0029 +#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN 0x002a +#define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C +#define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800 0x0041 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE 0x0042 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x0045 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000 0x004E +#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS 0x0052 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055 +#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 +#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 +#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069 +#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 +#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089 +#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a +#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800 0x0098 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099 +#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 +#define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1 +#define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2 +#define PCI_DEVICE_ID_GEFORCE_GO_6800 0x00c8 +#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA 0x00c9 +#define PCI_DEVICE_ID_QUADRO_FX_GO1400 0x00cc +#define PCI_DEVICE_ID_QUADRO_FX_1400 0x00ce +#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5 +#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9 +#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5 +#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea +#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 +#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 +#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 +#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX 0x0110 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2 0x0111 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO 0x0112 +#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR 0x0113 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT 0x0140 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600 0x0141 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL 0x0145 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540 0x014E +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200 0x014F +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS 0x0150 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2 0x0151 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA 0x0152 +#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO 0x0153 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200 0x0164 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250 0x0166 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1 0x0167 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1 0x0168 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460 0x0170 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440 0x0171 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420 0x0172 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE 0x0173 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO 0x0174 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO 0x0175 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO 0x0177 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL 0x0178 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200 0x017A +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000 0x0185 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO 0x0186 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO 0x0187 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL 0x0188 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC 0x0189 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS 0x018A +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL 0x018B +#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0 +#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4 +#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc +#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC 0x0203 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B 0x0211 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE 0x0212 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT 0x0215 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600 0x0250 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400 0x0251 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200 0x0253 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO 0x0286 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL 0x0288 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL 0x0289 +#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL 0x028C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA 0x0301 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800 0x0302 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000 0x0308 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000 0x0309 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA 0x0311 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600 0x0312 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE 0x0314 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600 0x031A +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650 0x031B +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700 0x031C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200 0x0320 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA 0x0321 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1 0x0322 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE 0x0323 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200 0x0324 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250 0x0325 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500 0x0326 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100 0x0327 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32 0x0328 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI 0x032A +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500 0x032B +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300 0x032C +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100 0x032D +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA 0x0330 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900 0x0331 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT 0x0332 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA 0x0333 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT 0x0334 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000 0x0338 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700 0x033F +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA 0x0341 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700 0x0342 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE 0x0343 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE 0x0344 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1 0x0347 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348 +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C +#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E +#define PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V0 0x0360 +#define PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4 0x0364 +#define PCI_DEVICE_ID_NVIDIA_NVENET_15 0x0373 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS 0x0542 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_320M 0x08A0 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA 0x0D85 + +#define PCI_VENDOR_ID_IMS 0x10e0 +#define PCI_DEVICE_ID_IMS_TT128 0x9128 +#define PCI_DEVICE_ID_IMS_TT3D 0x9135 + +#define PCI_VENDOR_ID_AMCC 0x10e8 +#define PCI_VENDOR_ID_AMPERE 0x1def + +#define PCI_VENDOR_ID_INTERG 0x10ea +#define PCI_DEVICE_ID_INTERG_1682 0x1682 +#define PCI_DEVICE_ID_INTERG_2000 0x2000 +#define PCI_DEVICE_ID_INTERG_2010 0x2010 +#define PCI_DEVICE_ID_INTERG_5000 0x5000 +#define PCI_DEVICE_ID_INTERG_5050 0x5050 + +#define PCI_VENDOR_ID_REALTEK 0x10ec +#define PCI_DEVICE_ID_REALTEK_8139 0x8139 + +#define PCI_VENDOR_ID_XILINX 0x10ee +#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0 +#define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1 +#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2 +#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3 +#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 +#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 + +#define PCI_VENDOR_ID_INIT 0x1101 + +#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */ +#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002 +#define PCI_DEVICE_ID_CREATIVE_20K1 0x0005 +#define PCI_DEVICE_ID_CREATIVE_20K2 0x000b +#define PCI_SUBDEVICE_ID_CREATIVE_SB0760 0x0024 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 +#define PCI_SUBDEVICE_ID_CREATIVE_SB1270 0x0062 +#define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000 + +#define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ +#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938 + +#define PCI_VENDOR_ID_TTI 0x1103 +#define PCI_DEVICE_ID_TTI_HPT343 0x0003 +#define PCI_DEVICE_ID_TTI_HPT366 0x0004 +#define PCI_DEVICE_ID_TTI_HPT372 0x0005 +#define PCI_DEVICE_ID_TTI_HPT302 0x0006 +#define PCI_DEVICE_ID_TTI_HPT371 0x0007 +#define PCI_DEVICE_ID_TTI_HPT374 0x0008 +#define PCI_DEVICE_ID_TTI_HPT372N 0x0009 /* apparently a 372N variant? */ + +#define PCI_VENDOR_ID_SIGMA 0x1105 + +#define PCI_VENDOR_ID_VIA 0x1106 +#define PCI_DEVICE_ID_VIA_8763_0 0x0198 +#define PCI_DEVICE_ID_VIA_8380_0 0x0204 +#define PCI_DEVICE_ID_VIA_3238_0 0x0238 +#define PCI_DEVICE_ID_VIA_PT880 0x0258 +#define PCI_DEVICE_ID_VIA_PT880ULTRA 0x0308 +#define PCI_DEVICE_ID_VIA_PX8X0_0 0x0259 +#define PCI_DEVICE_ID_VIA_3269_0 0x0269 +#define PCI_DEVICE_ID_VIA_K8T800PRO_0 0x0282 +#define PCI_DEVICE_ID_VIA_3296_0 0x0296 +#define PCI_DEVICE_ID_VIA_8363_0 0x0305 +#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314 +#define PCI_DEVICE_ID_VIA_P4M890 0x0327 +#define PCI_DEVICE_ID_VIA_VT3324 0x0324 +#define PCI_DEVICE_ID_VIA_VT3336 0x0336 +#define PCI_DEVICE_ID_VIA_VT3351 0x0351 +#define PCI_DEVICE_ID_VIA_VT3364 0x0364 +#define PCI_DEVICE_ID_VIA_8371_0 0x0391 +#define PCI_DEVICE_ID_VIA_6415 0x0415 +#define PCI_DEVICE_ID_VIA_8501_0 0x0501 +#define PCI_DEVICE_ID_VIA_82C561 0x0561 +#define PCI_DEVICE_ID_VIA_82C586_1 0x0571 +#define PCI_DEVICE_ID_VIA_82C576 0x0576 +#define PCI_DEVICE_ID_VIA_82C586_0 0x0586 +#define PCI_DEVICE_ID_VIA_82C596 0x0596 +#define PCI_DEVICE_ID_VIA_82C597_0 0x0597 +#define PCI_DEVICE_ID_VIA_82C598_0 0x0598 +#define PCI_DEVICE_ID_VIA_8601_0 0x0601 +#define PCI_DEVICE_ID_VIA_8605_0 0x0605 +#define PCI_DEVICE_ID_VIA_82C686 0x0686 +#define PCI_DEVICE_ID_VIA_82C691_0 0x0691 +#define PCI_DEVICE_ID_VIA_82C576_1 0x1571 +#define PCI_DEVICE_ID_VIA_82C586_2 0x3038 +#define PCI_DEVICE_ID_VIA_82C586_3 0x3040 +#define PCI_DEVICE_ID_VIA_82C596_3 0x3050 +#define PCI_DEVICE_ID_VIA_82C596B_3 0x3051 +#define PCI_DEVICE_ID_VIA_82C686_4 0x3057 +#define PCI_DEVICE_ID_VIA_82C686_5 0x3058 +#define PCI_DEVICE_ID_VIA_8233_5 0x3059 +#define PCI_DEVICE_ID_VIA_8233_0 0x3074 +#define PCI_DEVICE_ID_VIA_8633_0 0x3091 +#define PCI_DEVICE_ID_VIA_8367_0 0x3099 +#define PCI_DEVICE_ID_VIA_8653_0 0x3101 +#define PCI_DEVICE_ID_VIA_8622 0x3102 +#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104 +#define PCI_DEVICE_ID_VIA_8233C_0 0x3109 +#define PCI_DEVICE_ID_VIA_8361 0x3112 +#define PCI_DEVICE_ID_VIA_XM266 0x3116 +#define PCI_DEVICE_ID_VIA_612X 0x3119 +#define PCI_DEVICE_ID_VIA_862X_0 0x3123 +#define PCI_DEVICE_ID_VIA_8753_0 0x3128 +#define PCI_DEVICE_ID_VIA_8233A 0x3147 +#define PCI_DEVICE_ID_VIA_8703_51_0 0x3148 +#define PCI_DEVICE_ID_VIA_8237_SATA 0x3149 +#define PCI_DEVICE_ID_VIA_XN266 0x3156 +#define PCI_DEVICE_ID_VIA_6410 0x3164 +#define PCI_DEVICE_ID_VIA_8754C_0 0x3168 +#define PCI_DEVICE_ID_VIA_8235 0x3177 +#define PCI_DEVICE_ID_VIA_8385_0 0x3188 +#define PCI_DEVICE_ID_VIA_8377_0 0x3189 +#define PCI_DEVICE_ID_VIA_8378_0 0x3205 +#define PCI_DEVICE_ID_VIA_8783_0 0x3208 +#define PCI_DEVICE_ID_VIA_8237 0x3227 +#define PCI_DEVICE_ID_VIA_8251 0x3287 +#define PCI_DEVICE_ID_VIA_8261 0x3402 +#define PCI_DEVICE_ID_VIA_8237A 0x3337 +#define PCI_DEVICE_ID_VIA_8237S 0x3372 +#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x5324 +#define PCI_DEVICE_ID_VIA_8231 0x8231 +#define PCI_DEVICE_ID_VIA_8231_4 0x8235 +#define PCI_DEVICE_ID_VIA_8365_1 0x8305 +#define PCI_DEVICE_ID_VIA_CX700 0x8324 +#define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581 +#define PCI_DEVICE_ID_VIA_VX800 0x8353 +#define PCI_DEVICE_ID_VIA_VX855 0x8409 +#define PCI_DEVICE_ID_VIA_VX900 0x8410 +#define PCI_DEVICE_ID_VIA_8371_1 0x8391 +#define PCI_DEVICE_ID_VIA_82C598_1 0x8598 +#define PCI_DEVICE_ID_VIA_838X_1 0xB188 +#define PCI_DEVICE_ID_VIA_83_87XX_1 0xB198 +#define PCI_DEVICE_ID_VIA_VX855_IDE 0xC409 +#define PCI_DEVICE_ID_VIA_ANON 0xFFFF + +#define PCI_VENDOR_ID_SIEMENS 0x110A +#define PCI_DEVICE_ID_SIEMENS_DSCC4 0x2102 + +#define PCI_VENDOR_ID_VORTEX 0x1119 +#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000 +#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001 +#define PCI_DEVICE_ID_VORTEX_GDT6x10 0x0002 +#define PCI_DEVICE_ID_VORTEX_GDT6x20 0x0003 +#define PCI_DEVICE_ID_VORTEX_GDT6530 0x0004 +#define PCI_DEVICE_ID_VORTEX_GDT6550 0x0005 +#define PCI_DEVICE_ID_VORTEX_GDT6x17 0x0006 +#define PCI_DEVICE_ID_VORTEX_GDT6x27 0x0007 +#define PCI_DEVICE_ID_VORTEX_GDT6537 0x0008 +#define PCI_DEVICE_ID_VORTEX_GDT6557 0x0009 +#define PCI_DEVICE_ID_VORTEX_GDT6x15 0x000a +#define PCI_DEVICE_ID_VORTEX_GDT6x25 0x000b +#define PCI_DEVICE_ID_VORTEX_GDT6535 0x000c +#define PCI_DEVICE_ID_VORTEX_GDT6555 0x000d +#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100 +#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101 +#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102 +#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103 +#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104 +#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105 + +#define PCI_VENDOR_ID_EF 0x111a +#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000 +#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002 +#define PCI_DEVICE_ID_EF_ATM_LANAI2 0x0003 +#define PCI_DEVICE_ID_EF_ATM_LANAIHB 0x0005 + +#define PCI_VENDOR_ID_IDT 0x111d +#define PCI_DEVICE_ID_IDT_IDT77201 0x0001 + +#define PCI_VENDOR_ID_FORE 0x1127 +#define PCI_DEVICE_ID_FORE_PCA200E 0x0300 + +#define PCI_VENDOR_ID_PHILIPS 0x1131 +#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146 +#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730 + +#define PCI_VENDOR_ID_EICON 0x1133 +#define PCI_DEVICE_ID_EICON_DIVA20 0xe002 +#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 +#define PCI_DEVICE_ID_EICON_DIVA201 0xe005 +#define PCI_DEVICE_ID_EICON_DIVA202 0xe00b +#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010 +#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 +#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 +#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 + +#define PCI_VENDOR_ID_CISCO 0x1137 + +#define PCI_VENDOR_ID_ZIATECH 0x1138 +#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 + + +#define PCI_VENDOR_ID_SYSKONNECT 0x1148 +#define PCI_DEVICE_ID_SYSKONNECT_TR 0x4200 +#define PCI_DEVICE_ID_SYSKONNECT_GE 0x4300 +#define PCI_DEVICE_ID_SYSKONNECT_YU 0x4320 +#define PCI_DEVICE_ID_SYSKONNECT_9DXX 0x4400 +#define PCI_DEVICE_ID_SYSKONNECT_9MXX 0x4500 + +#define PCI_VENDOR_ID_DIGI 0x114f +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070 +#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072 +#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073 +#define PCI_DEVICE_ID_DIGI_NEO_8 0x00B1 +#define PCI_DEVICE_ID_NEO_2DB9 0x00C8 +#define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9 +#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA +#define PCI_DEVICE_ID_NEO_2RJ45PRI 0x00CB +#define PCIE_DEVICE_ID_NEO_4_IBM 0x00F4 + +#define PCI_VENDOR_ID_XIRCOM 0x115d +#define PCI_DEVICE_ID_XIRCOM_RBM56G 0x0101 +#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103 + +#define PCI_VENDOR_ID_SERVERWORKS 0x1166 +#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008 +#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 +#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB 0x0036 +#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103 +#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 +#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 +#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 +#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 +#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227 +#define PCI_DEVICE_ID_SERVERWORKS_HT1100LD 0x0408 + +#define PCI_VENDOR_ID_ALTERA 0x1172 + +#define PCI_VENDOR_ID_SBE 0x1176 +#define PCI_DEVICE_ID_SBE_WANXL100 0x0301 +#define PCI_DEVICE_ID_SBE_WANXL200 0x0302 +#define PCI_DEVICE_ID_SBE_WANXL400 0x0104 +#define PCI_SUBDEVICE_ID_SBE_T3E3 0x0009 +#define PCI_SUBDEVICE_ID_SBE_2T3E3_P0 0x0901 +#define PCI_SUBDEVICE_ID_SBE_2T3E3_P1 0x0902 + +#define PCI_VENDOR_ID_TOSHIBA 0x1179 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1 0x0101 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2 0x0102 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_3 0x0103 +#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_5 0x0105 +#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x060a +#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f +#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617 + +#define PCI_VENDOR_ID_TOSHIBA_2 0x102f +#define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030 +#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU 0x0031 +#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939 0x0032 +#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE 0x0105 +#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 +#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 + +#define PCI_VENDOR_ID_ATTO 0x117c + +#define PCI_VENDOR_ID_RICOH 0x1180 +#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 +#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466 +#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475 +#define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 +#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 +#define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5CE822 0xe822 +#define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 +#define PCI_DEVICE_ID_RICOH_R5C832 0x0832 +#define PCI_DEVICE_ID_RICOH_R5C843 0x0843 + +#define PCI_VENDOR_ID_DLINK 0x1186 +#define PCI_DEVICE_ID_DLINK_DGE510T 0x4c00 + +#define PCI_VENDOR_ID_ARTOP 0x1191 +#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005 +#define PCI_DEVICE_ID_ARTOP_ATP860 0x0006 +#define PCI_DEVICE_ID_ARTOP_ATP860R 0x0007 +#define PCI_DEVICE_ID_ARTOP_ATP865 0x0008 +#define PCI_DEVICE_ID_ARTOP_ATP865R 0x0009 +#define PCI_DEVICE_ID_ARTOP_ATP867A 0x000A +#define PCI_DEVICE_ID_ARTOP_ATP867B 0x000B +#define PCI_DEVICE_ID_ARTOP_AEC7610 0x8002 +#define PCI_DEVICE_ID_ARTOP_AEC7612UW 0x8010 +#define PCI_DEVICE_ID_ARTOP_AEC7612U 0x8020 +#define PCI_DEVICE_ID_ARTOP_AEC7612S 0x8030 +#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040 +#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050 +#define PCI_DEVICE_ID_ARTOP_8060 0x8060 + +#define PCI_VENDOR_ID_ZEITNET 0x1193 +#define PCI_DEVICE_ID_ZEITNET_1221 0x0001 +#define PCI_DEVICE_ID_ZEITNET_1225 0x0002 + +#define PCI_VENDOR_ID_FUJITSU_ME 0x119e +#define PCI_DEVICE_ID_FUJITSU_FS155 0x0001 +#define PCI_DEVICE_ID_FUJITSU_FS50 0x0003 + +#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9 +#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334 + +#define PCI_VENDOR_ID_MARVELL 0x11ab +#define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b +#define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 +#define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 +#define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 +#define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 +#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND 0x4100 +#define PCI_DEVICE_ID_MARVELL_88ALP01_SD 0x4101 +#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC 0x4102 + +#define PCI_VENDOR_ID_V3 0x11b0 +#define PCI_DEVICE_ID_V3_V960 0x0001 +#define PCI_DEVICE_ID_V3_V351 0x0002 + +#define PCI_VENDOR_ID_ATT 0x11c1 +#define PCI_DEVICE_ID_ATT_VENUS_MODEM 0x480 + +#define PCI_VENDOR_ID_SPECIALIX 0x11cb +#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004 + +#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4 +#define PCI_DEVICE_ID_AD1889JS 0x1889 + +#define PCI_DEVICE_ID_SEGA_BBA 0x1234 + +#define PCI_VENDOR_ID_ZORAN 0x11de +#define PCI_DEVICE_ID_ZORAN_36057 0x6057 +#define PCI_DEVICE_ID_ZORAN_36120 0x6120 + +#define PCI_VENDOR_ID_COMPEX 0x11f6 +#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112 + +#define PCI_VENDOR_ID_PMC_Sierra 0x11f8 +#define PCI_VENDOR_ID_MICROSEMI 0x11f8 + +#define PCI_VENDOR_ID_RP 0x11fe +#define PCI_DEVICE_ID_RP32INTF 0x0001 +#define PCI_DEVICE_ID_RP8INTF 0x0002 +#define PCI_DEVICE_ID_RP16INTF 0x0003 +#define PCI_DEVICE_ID_RP4QUAD 0x0004 +#define PCI_DEVICE_ID_RP8OCTA 0x0005 +#define PCI_DEVICE_ID_RP8J 0x0006 +#define PCI_DEVICE_ID_RP4J 0x0007 +#define PCI_DEVICE_ID_RP8SNI 0x0008 +#define PCI_DEVICE_ID_RP16SNI 0x0009 +#define PCI_DEVICE_ID_RPP4 0x000A +#define PCI_DEVICE_ID_RPP8 0x000B +#define PCI_DEVICE_ID_RP4M 0x000D +#define PCI_DEVICE_ID_RP2_232 0x000E +#define PCI_DEVICE_ID_RP2_422 0x000F +#define PCI_DEVICE_ID_URP32INTF 0x0801 +#define PCI_DEVICE_ID_URP8INTF 0x0802 +#define PCI_DEVICE_ID_URP16INTF 0x0803 +#define PCI_DEVICE_ID_URP8OCTA 0x0805 +#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C +#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D +#define PCI_DEVICE_ID_CRP16INTF 0x0903 + +#define PCI_VENDOR_ID_CYCLADES 0x120e +#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100 +#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101 +#define PCI_DEVICE_ID_CYCLOM_4Y_Lo 0x0102 +#define PCI_DEVICE_ID_CYCLOM_4Y_Hi 0x0103 +#define PCI_DEVICE_ID_CYCLOM_8Y_Lo 0x0104 +#define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105 +#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200 +#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201 +#define PCI_DEVICE_ID_PC300_RX_2 0x0300 +#define PCI_DEVICE_ID_PC300_RX_1 0x0301 +#define PCI_DEVICE_ID_PC300_TE_2 0x0310 +#define PCI_DEVICE_ID_PC300_TE_1 0x0311 +#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320 +#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321 + +#define PCI_VENDOR_ID_ESSENTIAL 0x120f +#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001 + +#define PCI_VENDOR_ID_O2 0x1217 +#define PCI_DEVICE_ID_O2_6729 0x6729 +#define PCI_DEVICE_ID_O2_6730 0x673a +#define PCI_DEVICE_ID_O2_6832 0x6832 +#define PCI_DEVICE_ID_O2_6836 0x6836 +#define PCI_DEVICE_ID_O2_6812 0x6872 +#define PCI_DEVICE_ID_O2_6933 0x6933 +#define PCI_DEVICE_ID_O2_8120 0x8120 +#define PCI_DEVICE_ID_O2_8220 0x8220 +#define PCI_DEVICE_ID_O2_8221 0x8221 +#define PCI_DEVICE_ID_O2_8320 0x8320 +#define PCI_DEVICE_ID_O2_8321 0x8321 + +#define PCI_VENDOR_ID_3DFX 0x121a +#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001 +#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002 +#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 +#define PCI_DEVICE_ID_3DFX_VOODOO3 0x0005 +#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 + +#define PCI_VENDOR_ID_AVM 0x1244 +#define PCI_DEVICE_ID_AVM_B1 0x0700 +#define PCI_DEVICE_ID_AVM_C4 0x0800 +#define PCI_DEVICE_ID_AVM_A1 0x0a00 +#define PCI_DEVICE_ID_AVM_A1_V2 0x0e00 +#define PCI_DEVICE_ID_AVM_C2 0x1100 +#define PCI_DEVICE_ID_AVM_T1 0x1200 + +#define PCI_VENDOR_ID_STALLION 0x124d + +/* Allied Telesyn */ +#define PCI_VENDOR_ID_AT 0x1259 +#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701 +#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703 + +#define PCI_VENDOR_ID_ESS 0x125d +#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 +#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 +#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988 +#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989 +#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990 +#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992 +#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998 +#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999 +#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a +#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b + +#define PCI_VENDOR_ID_SATSAGEM 0x1267 +#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016 + +#define PCI_VENDOR_ID_ENSONIQ 0x1274 +#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880 +#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000 +#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 + +#define PCI_VENDOR_ID_TRANSMETA 0x1279 +#define PCI_DEVICE_ID_EFFICEON 0x0060 + +#define PCI_VENDOR_ID_ROCKWELL 0x127A + +#define PCI_VENDOR_ID_ITE 0x1283 +#define PCI_DEVICE_ID_ITE_8172 0x8172 +#define PCI_DEVICE_ID_ITE_8211 0x8211 +#define PCI_DEVICE_ID_ITE_8212 0x8212 +#define PCI_DEVICE_ID_ITE_8213 0x8213 +#define PCI_DEVICE_ID_ITE_8152 0x8152 +#define PCI_DEVICE_ID_ITE_8872 0x8872 +#define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 + +/* formerly Platform Tech */ +#define PCI_DEVICE_ID_ESS_ESS0100 0x0100 + +#define PCI_VENDOR_ID_ALTEON 0x12ae + +#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232 0x0001 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232 0x0002 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232 0x0003 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485 0x0004 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4 0x0005 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485 0x0006 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2 0x0007 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485 0x0008 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6 0x0009 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1 0x000A +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1 0x000B +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ 0x000C +#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM 0x000D +#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI 0x0100 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2 0x0201 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4 0x0202 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232 0x0300 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232 0x0301 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232 0x0302 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1 0x0310 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2 0x0311 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4 0x0312 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2 0x0320 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4 0x0321 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8 0x0322 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485 0x0330 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 0x0331 +#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 0x0332 + +#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2 +#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018 + +#define PCI_VENDOR_ID_PERICOM 0x12D8 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958 + +#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4 0x0031 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8 0x0021 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16 0x0011 +#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC 0x0041 +#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D +#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4 0xF001 +#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8 0xF010 + +#define PCI_VENDOR_ID_AUREAL 0x12eb +#define PCI_DEVICE_ID_AUREAL_VORTEX_1 0x0001 +#define PCI_DEVICE_ID_AUREAL_VORTEX_2 0x0002 +#define PCI_DEVICE_ID_AUREAL_ADVANTAGE 0x0003 + +#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8 +#define PCI_DEVICE_ID_LML_33R10 0x8a02 + +#define PCI_VENDOR_ID_ESDGMBH 0x12fe +#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111 + +#define PCI_VENDOR_ID_CB 0x1307 /* Measurement Computing */ + +#define PCI_VENDOR_ID_SIIG 0x131f +#define PCI_SUBVENDOR_ID_SIIG 0x131f +#define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000 +#define PCI_DEVICE_ID_SIIG_1S_10x_650 0x1001 +#define PCI_DEVICE_ID_SIIG_1S_10x_850 0x1002 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011 +#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012 +#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020 +#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021 +#define PCI_DEVICE_ID_SIIG_2S_10x_550 0x1030 +#define PCI_DEVICE_ID_SIIG_2S_10x_650 0x1031 +#define PCI_DEVICE_ID_SIIG_2S_10x_850 0x1032 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035 +#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036 +#define PCI_DEVICE_ID_SIIG_4S_10x_550 0x1050 +#define PCI_DEVICE_ID_SIIG_4S_10x_650 0x1051 +#define PCI_DEVICE_ID_SIIG_4S_10x_850 0x1052 +#define PCI_DEVICE_ID_SIIG_1S_20x_550 0x2000 +#define PCI_DEVICE_ID_SIIG_1S_20x_650 0x2001 +#define PCI_DEVICE_ID_SIIG_1S_20x_850 0x2002 +#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020 +#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021 +#define PCI_DEVICE_ID_SIIG_2S_20x_550 0x2030 +#define PCI_DEVICE_ID_SIIG_2S_20x_650 0x2031 +#define PCI_DEVICE_ID_SIIG_2S_20x_850 0x2032 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041 +#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011 +#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012 +#define PCI_DEVICE_ID_SIIG_4S_20x_550 0x2050 +#define PCI_DEVICE_ID_SIIG_4S_20x_650 0x2051 +#define PCI_DEVICE_ID_SIIG_4S_20x_850 0x2052 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061 +#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062 +#define PCI_DEVICE_ID_SIIG_8S_20x_550 0x2080 +#define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 +#define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 +#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 + +#define PCI_VENDOR_ID_RADISYS 0x1331 + +#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332 +#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415 +#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425 +#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155 + +#define PCI_VENDOR_ID_DOMEX 0x134a +#define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 + +#define PCI_VENDOR_ID_INTASHIELD 0x135a +#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 +#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0 + +#define PCI_VENDOR_ID_QUATECH 0x135C +#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 +#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 +#define PCI_DEVICE_ID_QUATECH_DSC200 0x0030 +#define PCI_DEVICE_ID_QUATECH_QSC200 0x0040 +#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 +#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060 +#define PCI_DEVICE_ID_QUATECH_QSCP100 0x0120 +#define PCI_DEVICE_ID_QUATECH_DSCP100 0x0130 +#define PCI_DEVICE_ID_QUATECH_QSCP200 0x0140 +#define PCI_DEVICE_ID_QUATECH_DSCP200 0x0150 +#define PCI_DEVICE_ID_QUATECH_QSCLP100 0x0170 +#define PCI_DEVICE_ID_QUATECH_DSCLP100 0x0180 +#define PCI_DEVICE_ID_QUATECH_DSC100E 0x0181 +#define PCI_DEVICE_ID_QUATECH_SSCLP100 0x0190 +#define PCI_DEVICE_ID_QUATECH_QSCLP200 0x01A0 +#define PCI_DEVICE_ID_QUATECH_DSCLP200 0x01B0 +#define PCI_DEVICE_ID_QUATECH_DSC200E 0x01B1 +#define PCI_DEVICE_ID_QUATECH_SSCLP200 0x01C0 +#define PCI_DEVICE_ID_QUATECH_ESCLP100 0x01E0 +#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278 + +#define PCI_VENDOR_ID_SEALEVEL 0x135e +#define PCI_DEVICE_ID_SEALEVEL_U530 0x7101 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM2 0x7201 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM422 0x7402 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202 +#define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401 +#define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801 +#define PCI_DEVICE_ID_SEALEVEL_7803 0x7803 +#define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804 + +#define PCI_VENDOR_ID_HYPERCOPE 0x1365 +#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050 +#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104 +#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106 +#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107 +#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108 + +#define PCI_VENDOR_ID_DIGIGRAM 0x1369 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM 0xc001 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM 0xc002 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_SERIAL_SUBSYSTEM 0xc021 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_CAE_SERIAL_SUBSYSTEM 0xc022 + +#define PCI_VENDOR_ID_KAWASAKI 0x136b +#define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 + +#define PCI_VENDOR_ID_CNET 0x1371 +#define PCI_DEVICE_ID_CNET_GIGACARD 0x434e + +#define PCI_VENDOR_ID_LMC 0x1376 +#define PCI_DEVICE_ID_LMC_HSSI 0x0003 +#define PCI_DEVICE_ID_LMC_DS3 0x0004 +#define PCI_DEVICE_ID_LMC_SSI 0x0005 +#define PCI_DEVICE_ID_LMC_T1 0x0006 + +#define PCI_VENDOR_ID_NETGEAR 0x1385 +#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a + +#define PCI_VENDOR_ID_APPLICOM 0x1389 +#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 +#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 +#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 + +#define PCI_VENDOR_ID_MOXA 0x1393 +#define PCI_DEVICE_ID_MOXA_RC7000 0x0001 +#define PCI_DEVICE_ID_MOXA_CP102 0x1020 +#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021 +#define PCI_DEVICE_ID_MOXA_CP102U 0x1022 +#define PCI_DEVICE_ID_MOXA_C104 0x1040 +#define PCI_DEVICE_ID_MOXA_CP104U 0x1041 +#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042 +#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043 +#define PCI_DEVICE_ID_MOXA_CT114 0x1140 +#define PCI_DEVICE_ID_MOXA_CP114 0x1141 +#define PCI_DEVICE_ID_MOXA_CP118U 0x1180 +#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181 +#define PCI_DEVICE_ID_MOXA_CP132 0x1320 +#define PCI_DEVICE_ID_MOXA_CP132U 0x1321 +#define PCI_DEVICE_ID_MOXA_CP134U 0x1340 +#define PCI_DEVICE_ID_MOXA_C168 0x1680 +#define PCI_DEVICE_ID_MOXA_CP168U 0x1681 +#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682 +#define PCI_DEVICE_ID_MOXA_CP204J 0x2040 +#define PCI_DEVICE_ID_MOXA_C218 0x2180 +#define PCI_DEVICE_ID_MOXA_C320 0x3200 + +#define PCI_VENDOR_ID_CCD 0x1397 +#define PCI_DEVICE_ID_CCD_HFC4S 0x08B4 +#define PCI_SUBDEVICE_ID_CCD_PMX2S 0x1234 +#define PCI_DEVICE_ID_CCD_HFC8S 0x16B8 +#define PCI_DEVICE_ID_CCD_2BD0 0x2bd0 +#define PCI_DEVICE_ID_CCD_HFCE1 0x30B1 +#define PCI_SUBDEVICE_ID_CCD_SPD4S 0x3136 +#define PCI_SUBDEVICE_ID_CCD_SPDE1 0x3137 +#define PCI_DEVICE_ID_CCD_B000 0xb000 +#define PCI_DEVICE_ID_CCD_B006 0xb006 +#define PCI_DEVICE_ID_CCD_B007 0xb007 +#define PCI_DEVICE_ID_CCD_B008 0xb008 +#define PCI_DEVICE_ID_CCD_B009 0xb009 +#define PCI_DEVICE_ID_CCD_B00A 0xb00a +#define PCI_DEVICE_ID_CCD_B00B 0xb00b +#define PCI_DEVICE_ID_CCD_B00C 0xb00c +#define PCI_DEVICE_ID_CCD_B100 0xb100 +#define PCI_SUBDEVICE_ID_CCD_IOB4ST 0xB520 +#define PCI_SUBDEVICE_ID_CCD_IOB8STR 0xB521 +#define PCI_SUBDEVICE_ID_CCD_IOB8ST 0xB522 +#define PCI_SUBDEVICE_ID_CCD_IOB1E1 0xB523 +#define PCI_SUBDEVICE_ID_CCD_SWYX4S 0xB540 +#define PCI_SUBDEVICE_ID_CCD_JH4S20 0xB550 +#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1 0xB552 +#define PCI_SUBDEVICE_ID_CCD_JHSE1 0xB553 +#define PCI_SUBDEVICE_ID_CCD_JH8S 0xB55B +#define PCI_SUBDEVICE_ID_CCD_BN4S 0xB560 +#define PCI_SUBDEVICE_ID_CCD_BN8S 0xB562 +#define PCI_SUBDEVICE_ID_CCD_BNE1 0xB563 +#define PCI_SUBDEVICE_ID_CCD_BNE1D 0xB564 +#define PCI_SUBDEVICE_ID_CCD_BNE1DP 0xB565 +#define PCI_SUBDEVICE_ID_CCD_BN2S 0xB566 +#define PCI_SUBDEVICE_ID_CCD_BN1SM 0xB567 +#define PCI_SUBDEVICE_ID_CCD_BN4SM 0xB568 +#define PCI_SUBDEVICE_ID_CCD_BN2SM 0xB569 +#define PCI_SUBDEVICE_ID_CCD_BNE1M 0xB56A +#define PCI_SUBDEVICE_ID_CCD_BN8SP 0xB56B +#define PCI_SUBDEVICE_ID_CCD_HFC4S 0xB620 +#define PCI_SUBDEVICE_ID_CCD_HFC8S 0xB622 +#define PCI_DEVICE_ID_CCD_B700 0xb700 +#define PCI_DEVICE_ID_CCD_B701 0xb701 +#define PCI_SUBDEVICE_ID_CCD_HFCE1 0xC523 +#define PCI_SUBDEVICE_ID_CCD_OV2S 0xE884 +#define PCI_SUBDEVICE_ID_CCD_OV4S 0xE888 +#define PCI_SUBDEVICE_ID_CCD_OV8S 0xE998 + +#define PCI_VENDOR_ID_EXAR 0x13a8 +#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 +#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 +#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158 +#define PCI_DEVICE_ID_EXAR_XR17V352 0x0352 +#define PCI_DEVICE_ID_EXAR_XR17V354 0x0354 +#define PCI_DEVICE_ID_EXAR_XR17V358 0x0358 + +#define PCI_VENDOR_ID_MICROGATE 0x13c0 +#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 +#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 + +#define PCI_VENDOR_ID_3WARE 0x13C1 +#define PCI_DEVICE_ID_3WARE_1000 0x1000 +#define PCI_DEVICE_ID_3WARE_7000 0x1001 +#define PCI_DEVICE_ID_3WARE_9000 0x1002 + +#define PCI_VENDOR_ID_IOMEGA 0x13ca +#define PCI_DEVICE_ID_IOMEGA_BUZ 0x4231 + +#define PCI_VENDOR_ID_ABOCOM 0x13D1 +#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1 + +#define PCI_VENDOR_ID_SUNDANCE 0x13f0 + +#define PCI_VENDOR_ID_CMEDIA 0x13f6 +#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100 +#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101 +#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 +#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 + +#define PCI_VENDOR_ID_ADVANTECH 0x13fe + +#define PCI_VENDOR_ID_MEILHAUS 0x1402 + +#define PCI_VENDOR_ID_LAVA 0x1407 +#define PCI_DEVICE_ID_LAVA_DSERIAL 0x0100 /* 2x 16550 */ +#define PCI_DEVICE_ID_LAVA_QUATRO_A 0x0101 /* 2x 16550, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUATRO_B 0x0102 /* 2x 16550, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUATTRO_A 0x0120 /* 2x 16550A, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUATTRO_B 0x0121 /* 2x 16550A, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_OCTO_A 0x0180 /* 4x 16550A, half of 8 port */ +#define PCI_DEVICE_ID_LAVA_OCTO_B 0x0181 /* 4x 16550A, half of 8 port */ +#define PCI_DEVICE_ID_LAVA_PORT_PLUS 0x0200 /* 2x 16650 */ +#define PCI_DEVICE_ID_LAVA_QUAD_A 0x0201 /* 2x 16650, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_QUAD_B 0x0202 /* 2x 16650, half of 4 port */ +#define PCI_DEVICE_ID_LAVA_SSERIAL 0x0500 /* 1x 16550 */ +#define PCI_DEVICE_ID_LAVA_PORT_650 0x0600 /* 1x 16650 */ +#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000 +#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */ +#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */ +#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800 + +#define PCI_VENDOR_ID_TIMEDIA 0x1409 +#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168 + +#define PCI_VENDOR_ID_ICE 0x1412 +#define PCI_DEVICE_ID_ICE_1712 0x1712 +#define PCI_DEVICE_ID_VT1724 0x1724 + +#define PCI_VENDOR_ID_OXSEMI 0x1415 +#define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403 +#define PCI_DEVICE_ID_OXSEMI_PCIe840 0xC000 +#define PCI_DEVICE_ID_OXSEMI_PCIe840_G 0xC004 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_0 0xC100 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G 0xC104 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1 0xC110 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G 0xC114 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U 0xC118 +#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU 0xC11C +#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501 +#define PCI_DEVICE_ID_OXSEMI_C950 0x950B +#define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511 +#define PCI_DEVICE_ID_OXSEMI_16PCI954PP 0x9513 +#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521 +#define PCI_DEVICE_ID_OXSEMI_16PCI952PP 0x9523 +#define PCI_SUBDEVICE_ID_OXSEMI_C950 0x0001 + +#define PCI_VENDOR_ID_CHELSIO 0x1425 + +#define PCI_VENDOR_ID_ADLINK 0x144a + +#define PCI_VENDOR_ID_SAMSUNG 0x144d + +#define PCI_VENDOR_ID_GIGABYTE 0x1458 + +#define PCI_VENDOR_ID_AMBIT 0x1468 + +#define PCI_VENDOR_ID_MYRICOM 0x14c1 + +#define PCI_VENDOR_ID_MEDIATEK 0x14c3 +#define PCI_DEVICE_ID_MEDIATEK_7629 0x7629 + +#define PCI_VENDOR_ID_TITAN 0x14D2 +#define PCI_DEVICE_ID_TITAN_010L 0x8001 +#define PCI_DEVICE_ID_TITAN_100L 0x8010 +#define PCI_DEVICE_ID_TITAN_110L 0x8011 +#define PCI_DEVICE_ID_TITAN_200L 0x8020 +#define PCI_DEVICE_ID_TITAN_210L 0x8021 +#define PCI_DEVICE_ID_TITAN_400L 0x8040 +#define PCI_DEVICE_ID_TITAN_800L 0x8080 +#define PCI_DEVICE_ID_TITAN_100 0xA001 +#define PCI_DEVICE_ID_TITAN_200 0xA005 +#define PCI_DEVICE_ID_TITAN_400 0xA003 +#define PCI_DEVICE_ID_TITAN_800B 0xA004 + +#define PCI_VENDOR_ID_PANACOM 0x14d4 +#define PCI_DEVICE_ID_PANACOM_QUADMODEM 0x0400 +#define PCI_DEVICE_ID_PANACOM_DUALMODEM 0x0402 + +#define PCI_VENDOR_ID_SIPACKETS 0x14d9 +#define PCI_DEVICE_ID_SP1011 0x0010 + +#define PCI_VENDOR_ID_AFAVLAB 0x14db +#define PCI_DEVICE_ID_AFAVLAB_P028 0x2180 +#define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 +#define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150 + +#define PCI_VENDOR_ID_AMPLICON 0x14dc + +#define PCI_VENDOR_ID_BCM_GVC 0x14a4 +#define PCI_VENDOR_ID_BROADCOM 0x14e4 +#define PCI_DEVICE_ID_TIGON3_5752 0x1600 +#define PCI_DEVICE_ID_TIGON3_5752M 0x1601 +#define PCI_DEVICE_ID_NX2_5709 0x1639 +#define PCI_DEVICE_ID_NX2_5709S 0x163a +#define PCI_DEVICE_ID_TIGON3_5700 0x1644 +#define PCI_DEVICE_ID_TIGON3_5701 0x1645 +#define PCI_DEVICE_ID_TIGON3_5702 0x1646 +#define PCI_DEVICE_ID_TIGON3_5703 0x1647 +#define PCI_DEVICE_ID_TIGON3_5704 0x1648 +#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 +#define PCI_DEVICE_ID_NX2_5706 0x164a +#define PCI_DEVICE_ID_NX2_5708 0x164c +#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d +#define PCI_DEVICE_ID_NX2_57710 0x164e +#define PCI_DEVICE_ID_NX2_57711 0x164f +#define PCI_DEVICE_ID_NX2_57711E 0x1650 +#define PCI_DEVICE_ID_TIGON3_5705 0x1653 +#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 +#define PCI_DEVICE_ID_TIGON3_5719 0x1657 +#define PCI_DEVICE_ID_TIGON3_5721 0x1659 +#define PCI_DEVICE_ID_TIGON3_5722 0x165a +#define PCI_DEVICE_ID_TIGON3_5723 0x165b +#define PCI_DEVICE_ID_TIGON3_5705M 0x165d +#define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e +#define PCI_DEVICE_ID_NX2_57712 0x1662 +#define PCI_DEVICE_ID_NX2_57712E 0x1663 +#define PCI_DEVICE_ID_NX2_57712_MF 0x1663 +#define PCI_DEVICE_ID_TIGON3_5714 0x1668 +#define PCI_DEVICE_ID_TIGON3_5714S 0x1669 +#define PCI_DEVICE_ID_TIGON3_5780 0x166a +#define PCI_DEVICE_ID_TIGON3_5780S 0x166b +#define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#define PCI_DEVICE_ID_NX2_57712_VF 0x166f +#define PCI_DEVICE_ID_TIGON3_5754M 0x1672 +#define PCI_DEVICE_ID_TIGON3_5755M 0x1673 +#define PCI_DEVICE_ID_TIGON3_5756 0x1674 +#define PCI_DEVICE_ID_TIGON3_5750 0x1676 +#define PCI_DEVICE_ID_TIGON3_5751 0x1677 +#define PCI_DEVICE_ID_TIGON3_5715 0x1678 +#define PCI_DEVICE_ID_TIGON3_5715S 0x1679 +#define PCI_DEVICE_ID_TIGON3_5754 0x167a +#define PCI_DEVICE_ID_TIGON3_5755 0x167b +#define PCI_DEVICE_ID_TIGON3_5751M 0x167d +#define PCI_DEVICE_ID_TIGON3_5751F 0x167e +#define PCI_DEVICE_ID_TIGON3_5787F 0x167f +#define PCI_DEVICE_ID_TIGON3_5761E 0x1680 +#define PCI_DEVICE_ID_TIGON3_5761 0x1681 +#define PCI_DEVICE_ID_TIGON3_5764 0x1684 +#define PCI_DEVICE_ID_NX2_57800 0x168a +#define PCI_DEVICE_ID_NX2_57840 0x168d +#define PCI_DEVICE_ID_NX2_57810 0x168e +#define PCI_DEVICE_ID_TIGON3_5787M 0x1693 +#define PCI_DEVICE_ID_TIGON3_5782 0x1696 +#define PCI_DEVICE_ID_TIGON3_5784 0x1698 +#define PCI_DEVICE_ID_TIGON3_5786 0x169a +#define PCI_DEVICE_ID_TIGON3_5787 0x169b +#define PCI_DEVICE_ID_TIGON3_5788 0x169c +#define PCI_DEVICE_ID_TIGON3_5789 0x169d +#define PCI_DEVICE_ID_NX2_57840_4_10 0x16a1 +#define PCI_DEVICE_ID_NX2_57840_2_20 0x16a2 +#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 +#define PCI_DEVICE_ID_NX2_57800_MF 0x16a5 +#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 +#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 +#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 +#define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 +#define PCI_DEVICE_ID_NX2_5706S 0x16aa +#define PCI_DEVICE_ID_NX2_5708S 0x16ac +#define PCI_DEVICE_ID_NX2_57840_VF 0x16ad +#define PCI_DEVICE_ID_NX2_57810_MF 0x16ae +#define PCI_DEVICE_ID_NX2_57810_VF 0x16af +#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 +#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 +#define PCI_DEVICE_ID_TIGON3_5781 0x16dd +#define PCI_DEVICE_ID_TIGON3_5753 0x16f7 +#define PCI_DEVICE_ID_TIGON3_5753M 0x16fd +#define PCI_DEVICE_ID_TIGON3_5753F 0x16fe +#define PCI_DEVICE_ID_TIGON3_5901 0x170d +#define PCI_DEVICE_ID_BCM4401B1 0x170c +#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e +#define PCI_DEVICE_ID_TIGON3_5906 0x1712 +#define PCI_DEVICE_ID_TIGON3_5906M 0x1713 +#define PCI_DEVICE_ID_BCM4401 0x4401 +#define PCI_DEVICE_ID_BCM4401B0 0x4402 + +#define PCI_VENDOR_ID_TOPIC 0x151f +#define PCI_DEVICE_ID_TOPIC_TP560 0x0000 + +#define PCI_VENDOR_ID_MAINPINE 0x1522 +#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100 +#define PCI_VENDOR_ID_ENE 0x1524 +#define PCI_DEVICE_ID_ENE_CB710_FLASH 0x0510 +#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550 +#define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551 +#define PCI_DEVICE_ID_ENE_CB714_SD 0x0750 +#define PCI_DEVICE_ID_ENE_CB714_SD_2 0x0751 +#define PCI_DEVICE_ID_ENE_1211 0x1211 +#define PCI_DEVICE_ID_ENE_1225 0x1225 +#define PCI_DEVICE_ID_ENE_1410 0x1410 +#define PCI_DEVICE_ID_ENE_710 0x1411 +#define PCI_DEVICE_ID_ENE_712 0x1412 +#define PCI_DEVICE_ID_ENE_1420 0x1420 +#define PCI_DEVICE_ID_ENE_720 0x1421 +#define PCI_DEVICE_ID_ENE_722 0x1422 + +#define PCI_SUBVENDOR_ID_PERLE 0x155f +#define PCI_SUBDEVICE_ID_PCI_RAS4 0xf001 +#define PCI_SUBDEVICE_ID_PCI_RAS8 0xf010 + +#define PCI_VENDOR_ID_SYBA 0x1592 +#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782 +#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783 + +#define PCI_VENDOR_ID_MORETON 0x15aa +#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 + +#define PCI_VENDOR_ID_VMWARE 0x15ad +#define PCI_DEVICE_ID_VMWARE_VMXNET3 0x07b0 + +#define PCI_VENDOR_ID_ZOLTRIX 0x15b0 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 + +#define PCI_VENDOR_ID_MELLANOX 0x15b3 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX3 0x1003 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO 0x1007 +#define PCI_DEVICE_ID_MELLANOX_CONNECTIB 0x1011 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX4 0x1013 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX 0x1015 +#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 +#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 +#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c +#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 +#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 +#define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 +#define PCI_DEVICE_ID_MELLANOX_HERMON_SDR 0x6340 +#define PCI_DEVICE_ID_MELLANOX_HERMON_DDR 0x634a +#define PCI_DEVICE_ID_MELLANOX_HERMON_QDR 0x6354 +#define PCI_DEVICE_ID_MELLANOX_HERMON_EN 0x6368 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN 0x6372 +#define PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2 0x6732 +#define PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2 0x673c +#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2 0x6746 +#define PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2 0x6750 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2 0x675a +#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2 0x6764 +#define PCI_DEVICE_ID_MELLANOX_CONNECTX2 0x676e + +#define PCI_VENDOR_ID_DFI 0x15bd + +#define PCI_VENDOR_ID_QUICKNET 0x15e2 +#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500 + +/* + * ADDI-DATA GmbH communication cards + */ +#define PCI_VENDOR_ID_ADDIDATA 0x15B8 +#define PCI_DEVICE_ID_ADDIDATA_APCI7500 0x7000 +#define PCI_DEVICE_ID_ADDIDATA_APCI7420 0x7001 +#define PCI_DEVICE_ID_ADDIDATA_APCI7300 0x7002 +#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2 0x7009 +#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2 0x700A +#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2 0x700B +#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3 0x700C +#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3 0x700D +#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3 0x700E +#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3 0x700F +#define PCI_DEVICE_ID_ADDIDATA_APCIe7300 0x7010 +#define PCI_DEVICE_ID_ADDIDATA_APCIe7420 0x7011 +#define PCI_DEVICE_ID_ADDIDATA_APCIe7500 0x7012 +#define PCI_DEVICE_ID_ADDIDATA_APCIe7800 0x7013 + +#define PCI_VENDOR_ID_PDC 0x15e9 + +#define PCI_VENDOR_ID_FARSITE 0x1619 +#define PCI_DEVICE_ID_FARSITE_T2P 0x0400 +#define PCI_DEVICE_ID_FARSITE_T4P 0x0440 +#define PCI_DEVICE_ID_FARSITE_T1U 0x0610 +#define PCI_DEVICE_ID_FARSITE_T2U 0x0620 +#define PCI_DEVICE_ID_FARSITE_T4U 0x0640 +#define PCI_DEVICE_ID_FARSITE_TE1 0x1610 +#define PCI_DEVICE_ID_FARSITE_TE1C 0x1612 + +#define PCI_VENDOR_ID_ARIMA 0x161f + +#define PCI_VENDOR_ID_BROCADE 0x1657 +#define PCI_DEVICE_ID_BROCADE_CT 0x0014 +#define PCI_DEVICE_ID_BROCADE_FC_8G1P 0x0017 +#define PCI_DEVICE_ID_BROCADE_CT_FC 0x0021 + +#define PCI_VENDOR_ID_SIBYTE 0x166d +#define PCI_DEVICE_ID_BCM1250_PCI 0x0001 +#define PCI_DEVICE_ID_BCM1250_HT 0x0002 + +#define PCI_VENDOR_ID_ATHEROS 0x168c + +#define PCI_VENDOR_ID_NETCELL 0x169c +#define PCI_DEVICE_ID_REVOLUTION 0x0044 + +#define PCI_VENDOR_ID_CENATEK 0x16CA +#define PCI_DEVICE_ID_CENATEK_IDE 0x0001 + +#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31 0xabcf +#define PCI_DEVICE_ID_SYNOPSYS_EDDA 0xedda + +#define PCI_VENDOR_ID_USR 0x16ec + +#define PCI_VENDOR_ID_VITESSE 0x1725 +#define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174 + +#define PCI_VENDOR_ID_LINKSYS 0x1737 +#define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 + +#define PCI_VENDOR_ID_ALTIMA 0x173b +#define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 +#define PCI_DEVICE_ID_ALTIMA_AC1001 0x03e9 +#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea +#define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb + +#define PCI_VENDOR_ID_CAVIUM 0x177d + +#define PCI_VENDOR_ID_TECHWELL 0x1797 +#define PCI_DEVICE_ID_TECHWELL_6800 0x6800 +#define PCI_DEVICE_ID_TECHWELL_6801 0x6801 +#define PCI_DEVICE_ID_TECHWELL_6804 0x6804 +#define PCI_DEVICE_ID_TECHWELL_6816_1 0x6810 +#define PCI_DEVICE_ID_TECHWELL_6816_2 0x6811 +#define PCI_DEVICE_ID_TECHWELL_6816_3 0x6812 +#define PCI_DEVICE_ID_TECHWELL_6816_4 0x6813 + +#define PCI_VENDOR_ID_BELKIN 0x1799 +#define PCI_DEVICE_ID_BELKIN_F5D7010V7 0x701f + +#define PCI_VENDOR_ID_RDC 0x17f3 +#define PCI_DEVICE_ID_RDC_R6020 0x6020 +#define PCI_DEVICE_ID_RDC_R6030 0x6030 +#define PCI_DEVICE_ID_RDC_R6040 0x6040 +#define PCI_DEVICE_ID_RDC_R6060 0x6060 +#define PCI_DEVICE_ID_RDC_R6061 0x6061 +#define PCI_DEVICE_ID_RDC_D1010 0x1010 + +#define PCI_VENDOR_ID_GLI 0x17a0 + +#define PCI_VENDOR_ID_LENOVO 0x17aa + +#define PCI_VENDOR_ID_QCOM 0x17cb + +#define PCI_VENDOR_ID_CDNS 0x17cd + +#define PCI_VENDOR_ID_ARECA 0x17d3 +#define PCI_DEVICE_ID_ARECA_1110 0x1110 +#define PCI_DEVICE_ID_ARECA_1120 0x1120 +#define PCI_DEVICE_ID_ARECA_1130 0x1130 +#define PCI_DEVICE_ID_ARECA_1160 0x1160 +#define PCI_DEVICE_ID_ARECA_1170 0x1170 +#define PCI_DEVICE_ID_ARECA_1200 0x1200 +#define PCI_DEVICE_ID_ARECA_1201 0x1201 +#define PCI_DEVICE_ID_ARECA_1202 0x1202 +#define PCI_DEVICE_ID_ARECA_1210 0x1210 +#define PCI_DEVICE_ID_ARECA_1220 0x1220 +#define PCI_DEVICE_ID_ARECA_1230 0x1230 +#define PCI_DEVICE_ID_ARECA_1260 0x1260 +#define PCI_DEVICE_ID_ARECA_1270 0x1270 +#define PCI_DEVICE_ID_ARECA_1280 0x1280 +#define PCI_DEVICE_ID_ARECA_1380 0x1380 +#define PCI_DEVICE_ID_ARECA_1381 0x1381 +#define PCI_DEVICE_ID_ARECA_1680 0x1680 +#define PCI_DEVICE_ID_ARECA_1681 0x1681 + +#define PCI_VENDOR_ID_S2IO 0x17d5 +#define PCI_DEVICE_ID_S2IO_WIN 0x5731 +#define PCI_DEVICE_ID_S2IO_UNI 0x5831 +#define PCI_DEVICE_ID_HERC_WIN 0x5732 +#define PCI_DEVICE_ID_HERC_UNI 0x5832 + +#define PCI_VENDOR_ID_SITECOM 0x182d +#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 + +#define PCI_VENDOR_ID_TOPSPIN 0x1867 + +#define PCI_VENDOR_ID_COMMTECH 0x18f7 + +#define PCI_VENDOR_ID_SILAN 0x1904 + +#define PCI_VENDOR_ID_RENESAS 0x1912 +#define PCI_DEVICE_ID_RENESAS_SH7781 0x0001 +#define PCI_DEVICE_ID_RENESAS_SH7780 0x0002 +#define PCI_DEVICE_ID_RENESAS_SH7763 0x0004 +#define PCI_DEVICE_ID_RENESAS_SH7785 0x0007 +#define PCI_DEVICE_ID_RENESAS_SH7786 0x0010 + +#define PCI_VENDOR_ID_SOLARFLARE 0x1924 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0 0x0703 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1 0x6703 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000B 0x0710 + +#define PCI_VENDOR_ID_TDI 0x192E +#define PCI_DEVICE_ID_TDI_EHCI 0x0101 + +#define PCI_VENDOR_ID_FREESCALE 0x1957 /* duplicate: NXP */ +#define PCI_VENDOR_ID_NXP 0x1957 /* duplicate: FREESCALE */ +#define PCI_DEVICE_ID_MPC8308 0xc006 +#define PCI_DEVICE_ID_MPC8315E 0x00b4 +#define PCI_DEVICE_ID_MPC8315 0x00b5 +#define PCI_DEVICE_ID_MPC8314E 0x00b6 +#define PCI_DEVICE_ID_MPC8314 0x00b7 +#define PCI_DEVICE_ID_MPC8378E 0x00c4 +#define PCI_DEVICE_ID_MPC8378 0x00c5 +#define PCI_DEVICE_ID_MPC8377E 0x00c6 +#define PCI_DEVICE_ID_MPC8377 0x00c7 +#define PCI_DEVICE_ID_MPC8548E 0x0012 +#define PCI_DEVICE_ID_MPC8548 0x0013 +#define PCI_DEVICE_ID_MPC8543E 0x0014 +#define PCI_DEVICE_ID_MPC8543 0x0015 +#define PCI_DEVICE_ID_MPC8547E 0x0018 +#define PCI_DEVICE_ID_MPC8545E 0x0019 +#define PCI_DEVICE_ID_MPC8545 0x001a +#define PCI_DEVICE_ID_MPC8569E 0x0061 +#define PCI_DEVICE_ID_MPC8569 0x0060 +#define PCI_DEVICE_ID_MPC8568E 0x0020 +#define PCI_DEVICE_ID_MPC8568 0x0021 +#define PCI_DEVICE_ID_MPC8567E 0x0022 +#define PCI_DEVICE_ID_MPC8567 0x0023 +#define PCI_DEVICE_ID_MPC8533E 0x0030 +#define PCI_DEVICE_ID_MPC8533 0x0031 +#define PCI_DEVICE_ID_MPC8544E 0x0032 +#define PCI_DEVICE_ID_MPC8544 0x0033 +#define PCI_DEVICE_ID_MPC8572E 0x0040 +#define PCI_DEVICE_ID_MPC8572 0x0041 +#define PCI_DEVICE_ID_MPC8536E 0x0050 +#define PCI_DEVICE_ID_MPC8536 0x0051 +#define PCI_DEVICE_ID_P2020E 0x0070 +#define PCI_DEVICE_ID_P2020 0x0071 +#define PCI_DEVICE_ID_P2010E 0x0078 +#define PCI_DEVICE_ID_P2010 0x0079 +#define PCI_DEVICE_ID_P1020E 0x0100 +#define PCI_DEVICE_ID_P1020 0x0101 +#define PCI_DEVICE_ID_P1021E 0x0102 +#define PCI_DEVICE_ID_P1021 0x0103 +#define PCI_DEVICE_ID_P1011E 0x0108 +#define PCI_DEVICE_ID_P1011 0x0109 +#define PCI_DEVICE_ID_P1022E 0x0110 +#define PCI_DEVICE_ID_P1022 0x0111 +#define PCI_DEVICE_ID_P1013E 0x0118 +#define PCI_DEVICE_ID_P1013 0x0119 +#define PCI_DEVICE_ID_P4080E 0x0400 +#define PCI_DEVICE_ID_P4080 0x0401 +#define PCI_DEVICE_ID_P4040E 0x0408 +#define PCI_DEVICE_ID_P4040 0x0409 +#define PCI_DEVICE_ID_P2040E 0x0410 +#define PCI_DEVICE_ID_P2040 0x0411 +#define PCI_DEVICE_ID_P3041E 0x041E +#define PCI_DEVICE_ID_P3041 0x041F +#define PCI_DEVICE_ID_P5020E 0x0420 +#define PCI_DEVICE_ID_P5020 0x0421 +#define PCI_DEVICE_ID_P5010E 0x0428 +#define PCI_DEVICE_ID_P5010 0x0429 +#define PCI_DEVICE_ID_MPC8641 0x7010 +#define PCI_DEVICE_ID_MPC8641D 0x7011 +#define PCI_DEVICE_ID_MPC8610 0x7018 + +#define PCI_VENDOR_ID_PASEMI 0x1959 + +#define PCI_VENDOR_ID_ATTANSIC 0x1969 +#define PCI_DEVICE_ID_ATTANSIC_L1 0x1048 +#define PCI_DEVICE_ID_ATTANSIC_L2 0x2048 + +#define PCI_VENDOR_ID_JMICRON 0x197B +#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 +#define PCI_DEVICE_ID_JMICRON_JMB361 0x2361 +#define PCI_DEVICE_ID_JMICRON_JMB362 0x2362 +#define PCI_DEVICE_ID_JMICRON_JMB363 0x2363 +#define PCI_DEVICE_ID_JMICRON_JMB364 0x2364 +#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365 +#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366 +#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368 +#define PCI_DEVICE_ID_JMICRON_JMB369 0x2369 +#define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381 +#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382 +#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383 +#define PCI_DEVICE_ID_JMICRON_JMB385_MS 0x2388 +#define PCI_DEVICE_ID_JMICRON_JMB388_SD 0x2391 +#define PCI_DEVICE_ID_JMICRON_JMB388_ESD 0x2392 +#define PCI_DEVICE_ID_JMICRON_JMB390_MS 0x2393 + +#define PCI_VENDOR_ID_KORENIX 0x1982 +#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600 +#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff +#define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700 +#define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff + +#define PCI_VENDOR_ID_HUAWEI 0x19e5 + +#define PCI_VENDOR_ID_NETRONOME 0x19ee +#define PCI_DEVICE_ID_NETRONOME_NFP4000 0x4000 +#define PCI_DEVICE_ID_NETRONOME_NFP5000 0x5000 +#define PCI_DEVICE_ID_NETRONOME_NFP6000 0x6000 +#define PCI_DEVICE_ID_NETRONOME_NFP6000_VF 0x6003 + +#define PCI_VENDOR_ID_QMI 0x1a32 + +#define PCI_VENDOR_ID_AZWAVE 0x1a3b + +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBDEVICE_ID_QEMU 0x1100 + +#define PCI_VENDOR_ID_ASMEDIA 0x1b21 + +#define PCI_VENDOR_ID_REDHAT 0x1b36 + +#define PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS 0x1c36 + +#define PCI_VENDOR_ID_CIRCUITCO 0x1cc8 +#define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001 + +#define PCI_VENDOR_ID_AMAZON 0x1d0f + +#define PCI_VENDOR_ID_ZHAOXIN 0x1d17 + +#define PCI_VENDOR_ID_HYGON 0x1d94 + +#define PCI_VENDOR_ID_HXT 0x1dbf + +#define PCI_VENDOR_ID_TEKRAM 0x1de1 +#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 + +#define PCI_VENDOR_ID_TEHUTI 0x1fc9 +#define PCI_DEVICE_ID_TEHUTI_3009 0x3009 +#define PCI_DEVICE_ID_TEHUTI_3010 0x3010 +#define PCI_DEVICE_ID_TEHUTI_3014 0x3014 + +#define PCI_VENDOR_ID_SUNIX 0x1fd4 +#define PCI_DEVICE_ID_SUNIX_1999 0x1999 + +#define PCI_VENDOR_ID_HINT 0x3388 +#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013 + +#define PCI_VENDOR_ID_3DLABS 0x3d3d +#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007 +#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V 0x0009 + +#define PCI_VENDOR_ID_NETXEN 0x4040 +#define PCI_DEVICE_ID_NX2031_10GXSR 0x0001 +#define PCI_DEVICE_ID_NX2031_10GCX4 0x0002 +#define PCI_DEVICE_ID_NX2031_4GCU 0x0003 +#define PCI_DEVICE_ID_NX2031_IMEZ 0x0004 +#define PCI_DEVICE_ID_NX2031_HMEZ 0x0005 +#define PCI_DEVICE_ID_NX2031_XG_MGMT 0x0024 +#define PCI_DEVICE_ID_NX2031_XG_MGMT2 0x0025 +#define PCI_DEVICE_ID_NX3031 0x0100 + +#define PCI_VENDOR_ID_AKS 0x416c +#define PCI_DEVICE_ID_AKS_ALADDINCARD 0x0100 + +#define PCI_VENDOR_ID_ACCESSIO 0x494f +#define PCI_DEVICE_ID_ACCESSIO_WDG_CSM 0x22c0 + +#define PCI_VENDOR_ID_S3 0x5333 +#define PCI_DEVICE_ID_S3_TRIO 0x8811 +#define PCI_DEVICE_ID_S3_868 0x8880 +#define PCI_DEVICE_ID_S3_968 0x88f0 +#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 +#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 +#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00 + +#define PCI_VENDOR_ID_DUNORD 0x5544 +#define PCI_DEVICE_ID_DUNORD_I3000 0x0001 + +#define PCI_VENDOR_ID_DCI 0x6666 +#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001 +#define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 +#define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 + +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_EESSC 0x0008 +#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 +#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 +#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 +#define PCI_DEVICE_ID_INTEL_PXH_1 0x032A +#define PCI_DEVICE_ID_INTEL_PXHV 0x032C +#define PCI_DEVICE_ID_INTEL_80332_0 0x0330 +#define PCI_DEVICE_ID_INTEL_80332_1 0x0332 +#define PCI_DEVICE_ID_INTEL_80333_0 0x0370 +#define PCI_DEVICE_ID_INTEL_80333_1 0x0372 +#define PCI_DEVICE_ID_INTEL_QAT_DH895XCC 0x0435 +#define PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF 0x0443 +#define PCI_DEVICE_ID_INTEL_82375 0x0482 +#define PCI_DEVICE_ID_INTEL_82424 0x0483 +#define PCI_DEVICE_ID_INTEL_82378 0x0484 +#define PCI_DEVICE_ID_INTEL_MRST_SD0 0x0807 +#define PCI_DEVICE_ID_INTEL_MRST_SD1 0x0808 +#define PCI_DEVICE_ID_INTEL_MFD_SD 0x0820 +#define PCI_DEVICE_ID_INTEL_MFD_SDIO1 0x0821 +#define PCI_DEVICE_ID_INTEL_MFD_SDIO2 0x0822 +#define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823 +#define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824 +#define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F +#define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095E +#define PCI_DEVICE_ID_INTEL_I960 0x0960 +#define PCI_DEVICE_ID_INTEL_I960RM 0x0962 +#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 +#define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 +#define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085 +#define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F +#define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 +#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 +#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 +#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 +#define PCI_DEVICE_ID_INTEL_7205_0 0x255d +#define PCI_DEVICE_ID_INTEL_82437 0x122d +#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e +#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230 +#define PCI_DEVICE_ID_INTEL_82371MX 0x1234 +#define PCI_DEVICE_ID_INTEL_82441 0x1237 +#define PCI_DEVICE_ID_INTEL_82380FB 0x124b +#define PCI_DEVICE_ID_INTEL_82439 0x1250 +#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ +#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a +#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 +#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */ +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 +#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 +#define PCI_DEVICE_ID_INTEL_QAT_C3XXX 0x19e2 +#define PCI_DEVICE_ID_INTEL_QAT_C3XXX_VF 0x19e3 +#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 +#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 +#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f +#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 +#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f +#define PCI_DEVICE_ID_INTEL_VMD_201D 0x201d +#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 +#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f +#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 +#define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 +#define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 +#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415 +#define PCI_DEVICE_ID_INTEL_82801AA_6 0x2416 +#define PCI_DEVICE_ID_INTEL_82801AA_8 0x2418 +#define PCI_DEVICE_ID_INTEL_82801AB_0 0x2420 +#define PCI_DEVICE_ID_INTEL_82801AB_1 0x2421 +#define PCI_DEVICE_ID_INTEL_82801AB_3 0x2423 +#define PCI_DEVICE_ID_INTEL_82801AB_5 0x2425 +#define PCI_DEVICE_ID_INTEL_82801AB_6 0x2426 +#define PCI_DEVICE_ID_INTEL_82801AB_8 0x2428 +#define PCI_DEVICE_ID_INTEL_82801BA_0 0x2440 +#define PCI_DEVICE_ID_INTEL_82801BA_2 0x2443 +#define PCI_DEVICE_ID_INTEL_82801BA_4 0x2445 +#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2448 +#define PCI_DEVICE_ID_INTEL_82801BA_8 0x244a +#define PCI_DEVICE_ID_INTEL_82801BA_9 0x244b +#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c +#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e +#define PCI_DEVICE_ID_INTEL_82801E_0 0x2450 +#define PCI_DEVICE_ID_INTEL_82801E_11 0x245b +#define PCI_DEVICE_ID_INTEL_82801CA_0 0x2480 +#define PCI_DEVICE_ID_INTEL_82801CA_3 0x2483 +#define PCI_DEVICE_ID_INTEL_82801CA_5 0x2485 +#define PCI_DEVICE_ID_INTEL_82801CA_6 0x2486 +#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a +#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b +#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c +#define PCI_DEVICE_ID_INTEL_82801DB_0 0x24c0 +#define PCI_DEVICE_ID_INTEL_82801DB_1 0x24c1 +#define PCI_DEVICE_ID_INTEL_82801DB_2 0x24c2 +#define PCI_DEVICE_ID_INTEL_82801DB_3 0x24c3 +#define PCI_DEVICE_ID_INTEL_82801DB_5 0x24c5 +#define PCI_DEVICE_ID_INTEL_82801DB_6 0x24c6 +#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24c9 +#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca +#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb +#define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc +#define PCI_DEVICE_ID_INTEL_82801EB_0 0x24d0 +#define PCI_DEVICE_ID_INTEL_82801EB_1 0x24d1 +#define PCI_DEVICE_ID_INTEL_82801EB_3 0x24d3 +#define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 +#define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 +#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db +#define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc +#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd +#define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 +#define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 +#define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 +#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 +#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab +#define PCI_DEVICE_ID_INTEL_ESB_10 0x25ac +#define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 +#define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 +#define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 +#define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 +#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c +#define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 +#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 +#define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 +#define PCI_DEVICE_ID_INTEL_82865_IG 0x2572 +#define PCI_DEVICE_ID_INTEL_82875_HB 0x2578 +#define PCI_DEVICE_ID_INTEL_82915G_HB 0x2580 +#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 +#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590 +#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 +#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0 +#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5 +#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6 +#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 +#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 +#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778 +#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0 +#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 +#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 +#define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641 +#define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642 +#define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a +#define PCI_DEVICE_ID_INTEL_ICH6_17 0x266d +#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e +#define PCI_DEVICE_ID_INTEL_ICH6_19 0x266f +#define PCI_DEVICE_ID_INTEL_ESB2_0 0x2670 +#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698 +#define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b +#define PCI_DEVICE_ID_INTEL_ESB2_18 0x269e +#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 +#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 +#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 +#define PCI_DEVICE_ID_INTEL_TGP_LPC 0x27bc +#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd +#define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da +#define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd +#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de +#define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df +#define PCI_DEVICE_ID_INTEL_ICH8_0 0x2810 +#define PCI_DEVICE_ID_INTEL_ICH8_1 0x2811 +#define PCI_DEVICE_ID_INTEL_ICH8_2 0x2812 +#define PCI_DEVICE_ID_INTEL_ICH8_3 0x2814 +#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 +#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e +#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 +#define PCI_DEVICE_ID_INTEL_VMD_28C0 0x28c0 +#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 +#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 +#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 +#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913 +#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914 +#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919 +#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 +#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 +#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 +#define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18 +#define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19 +#define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a +#define PCI_DEVICE_ID_INTEL_I7_MC_TEST 0x2c1c +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL 0x2c20 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR 0x2c21 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK 0x2c22 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC 0x2c23 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL 0x2c28 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR 0x2c29 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK 0x2c2a +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC 0x2c2b +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL 0x2c30 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 +#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 +#define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD 0x2c81 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0 0x2c90 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0 0x2c91 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR 0x2c98 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD 0x2c99 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST 0x2c9C +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL 0x2ca0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR 0x2ca1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK 0x2ca2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC 0x2ca3 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL 0x2ca8 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR 0x2ca9 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK 0x2caa +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC 0x2cab +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2 0x2d98 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2 0x2d99 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2 0x2d9a +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2 0x2d9c +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2 0x2da0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2 0x2da1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2 0x2da2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2 0x2da3 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2 0x2da8 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2 0x2da9 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2 0x2daa +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2 0x2dab +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2 0x2db0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3 +#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a +#define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b +#define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c +#define PCI_DEVICE_ID_INTEL_X58_HUB_MGMT 0x342e +#define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432 +#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433 +#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 +#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 +#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c +#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e +#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 +#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 +#define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 +#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 +#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595 +#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596 +#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597 +#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598 +#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599 +#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a +#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e +#define PCI_DEVICE_ID_INTEL_I7300_MCH_ERR 0x360c +#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 0x360f +#define PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 0x3610 +#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b +#define PCI_DEVICE_ID_INTEL_FBD_CNB 0x360c +#define PCI_DEVICE_ID_INTEL_IOAT_JSF0 0x3710 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF1 0x3711 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF2 0x3712 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF3 0x3713 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF4 0x3714 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF5 0x3715 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF6 0x3716 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF7 0x3717 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF8 0x3718 +#define PCI_DEVICE_ID_INTEL_IOAT_JSF9 0x3719 +#define PCI_DEVICE_ID_INTEL_QAT_C62X 0x37c8 +#define PCI_DEVICE_ID_INTEL_QAT_C62X_VF 0x37c9 +#define PCI_DEVICE_ID_INTEL_ICH10_0 0x3a14 +#define PCI_DEVICE_ID_INTEL_ICH10_1 0x3a16 +#define PCI_DEVICE_ID_INTEL_ICH10_2 0x3a18 +#define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a +#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 +#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 +#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00 +#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f +#define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB3 0x3c23 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB4 0x3c24 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB5 0x3c25 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB6 0x3c26 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e +#define PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f +#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46 +#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0 +#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1 +#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4 +#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5 +#define PCI_DEVICE_ID_INTEL_UNC_QPI0 0x3c41 +#define PCI_DEVICE_ID_INTEL_UNC_QPI1 0x3c42 +#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45 +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS 0x3c71 /* 15.1 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0 0x3c72 /* 16.2 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1 0x3c73 /* 16.3 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR2 0x3c76 /* 16.6 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0 0x3ca0 /* 14.0 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA 0x3ca8 /* 15.0 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0 0x3caa /* 15.2 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1 0x3cab /* 15.3 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2 0x3cac /* 15.4 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3 0x3cad /* 15.5 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO 0x3cb8 /* 17.0 */ +#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0 +#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0 0x3cf4 /* 12.6 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR 0x3cf5 /* 13.6 */ +#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1 0x3cf6 /* 12.7 */ +#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f +#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 +#define PCI_DEVICE_ID_INTEL_5100_19 0x65f3 +#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 +#define PCI_DEVICE_ID_INTEL_5100_22 0x65f6 +#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 +#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 +#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 +#define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff +#define PCI_DEVICE_ID_INTEL_EP80579_0 0x5031 +#define PCI_DEVICE_ID_INTEL_EP80579_1 0x5032 +#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 +#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010 +#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020 +#define PCI_DEVICE_ID_INTEL_82437VX 0x7030 +#define PCI_DEVICE_ID_INTEL_82439TX 0x7100 +#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 +#define PCI_DEVICE_ID_INTEL_82371AB 0x7111 +#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112 +#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 +#define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 +#define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 +#define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122 +#define PCI_DEVICE_ID_INTEL_82810_IG3 0x7123 +#define PCI_DEVICE_ID_INTEL_82810E_MC 0x7124 +#define PCI_DEVICE_ID_INTEL_82810E_IG 0x7125 +#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180 +#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181 +#define PCI_DEVICE_ID_INTEL_82443BX_0 0x7190 +#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191 +#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192 +#define PCI_DEVICE_ID_INTEL_440MX 0x7195 +#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196 +#define PCI_DEVICE_ID_INTEL_82443MX_0 0x7198 +#define PCI_DEVICE_ID_INTEL_82443MX_1 0x7199 +#define PCI_DEVICE_ID_INTEL_82443MX_3 0x719b +#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0 +#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2 +#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 +#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 +#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a +#define PCI_DEVICE_ID_INTEL_E6XX_CU 0x8183 +#define PCI_DEVICE_ID_INTEL_ITC_LPC 0x8186 +#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 +#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 +#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca +#define PCI_DEVICE_ID_INTEL_82454NX 0x84cb +#define PCI_DEVICE_ID_INTEL_84460GX 0x84ea +#define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500 +#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 +#define PCI_DEVICE_ID_INTEL_VMD_9A0B 0x9a0b +#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 + +#define PCI_VENDOR_ID_WANGXUN 0x8088 + +#define PCI_VENDOR_ID_SCALEMP 0x8686 +#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010 + +#define PCI_VENDOR_ID_COMPUTONE 0x8e0e +#define PCI_DEVICE_ID_COMPUTONE_PG 0x0302 +#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e +#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001 +#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002 +#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003 + +#define PCI_VENDOR_ID_KTI 0x8e2e + +#define PCI_VENDOR_ID_ADAPTEC 0x9004 +#define PCI_DEVICE_ID_ADAPTEC_7810 0x1078 +#define PCI_DEVICE_ID_ADAPTEC_7821 0x2178 +#define PCI_DEVICE_ID_ADAPTEC_38602 0x3860 +#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078 +#define PCI_DEVICE_ID_ADAPTEC_7855 0x5578 +#define PCI_DEVICE_ID_ADAPTEC_3860 0x6038 +#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075 +#define PCI_DEVICE_ID_ADAPTEC_7860 0x6078 +#define PCI_DEVICE_ID_ADAPTEC_7861 0x6178 +#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078 +#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178 +#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278 +#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378 +#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478 +#define PCI_DEVICE_ID_ADAPTEC_7895 0x7895 +#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078 +#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178 +#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278 +#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378 +#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478 +#define PCI_DEVICE_ID_ADAPTEC_7885 0x8578 +#define PCI_DEVICE_ID_ADAPTEC_7886 0x8678 +#define PCI_DEVICE_ID_ADAPTEC_7887 0x8778 +#define PCI_DEVICE_ID_ADAPTEC_7888 0x8878 + +#define PCI_VENDOR_ID_ADAPTEC2 0x9005 +#define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010 +#define PCI_DEVICE_ID_ADAPTEC2_2930U2 0x0011 +#define PCI_DEVICE_ID_ADAPTEC2_7890B 0x0013 +#define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f +#define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050 +#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051 +#define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f +#define PCI_DEVICE_ID_ADAPTEC2_7892A 0x0080 +#define PCI_DEVICE_ID_ADAPTEC2_7892B 0x0081 +#define PCI_DEVICE_ID_ADAPTEC2_7892D 0x0083 +#define PCI_DEVICE_ID_ADAPTEC2_7892P 0x008f +#define PCI_DEVICE_ID_ADAPTEC2_7899A 0x00c0 +#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1 +#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3 +#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf +#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN 0x0500 +#define PCI_DEVICE_ID_ADAPTEC2_SCAMP 0x0503 + +#define PCI_VENDOR_ID_HOLTEK 0x9412 +#define PCI_DEVICE_ID_HOLTEK_6565 0x6565 + +#define PCI_VENDOR_ID_NETMOS 0x9710 +#define PCI_DEVICE_ID_NETMOS_9705 0x9705 +#define PCI_DEVICE_ID_NETMOS_9715 0x9715 +#define PCI_DEVICE_ID_NETMOS_9735 0x9735 +#define PCI_DEVICE_ID_NETMOS_9745 0x9745 +#define PCI_DEVICE_ID_NETMOS_9755 0x9755 +#define PCI_DEVICE_ID_NETMOS_9805 0x9805 +#define PCI_DEVICE_ID_NETMOS_9815 0x9815 +#define PCI_DEVICE_ID_NETMOS_9835 0x9835 +#define PCI_DEVICE_ID_NETMOS_9845 0x9845 +#define PCI_DEVICE_ID_NETMOS_9855 0x9855 +#define PCI_DEVICE_ID_NETMOS_9865 0x9865 +#define PCI_DEVICE_ID_NETMOS_9900 0x9900 +#define PCI_DEVICE_ID_NETMOS_9901 0x9901 +#define PCI_DEVICE_ID_NETMOS_9904 0x9904 +#define PCI_DEVICE_ID_NETMOS_9912 0x9912 +#define PCI_DEVICE_ID_NETMOS_9922 0x9922 + +#define PCI_VENDOR_ID_3COM_2 0xa727 + +#define PCI_VENDOR_ID_SOLIDRUN 0xd063 + +#define PCI_VENDOR_ID_DIGIUM 0xd161 +#define PCI_DEVICE_ID_DIGIUM_HFC4S 0xb410 + +#define PCI_SUBVENDOR_ID_EXSYS 0xd84d +#define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014 +#define PCI_SUBDEVICE_ID_EXSYS_4055 0x4055 + +#define PCI_VENDOR_ID_TIGERJET 0xe159 +#define PCI_DEVICE_ID_TIGERJET_300 0x0001 +#define PCI_DEVICE_ID_TIGERJET_100 0x0002 + +#define PCI_VENDOR_ID_XILINX_RME 0xea60 +#define PCI_DEVICE_ID_RME_DIGI32 0x9896 +#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897 +#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898 + +#define PCI_VENDOR_ID_XEN 0x5853 +#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001 + +#define PCI_VENDOR_ID_OCZ 0x1b85 + +#define PCI_VENDOR_ID_NCUBE 0x10ff + +#define PCI_VENDOR_ID_PHYTIUM 0x1db7 + +#endif /* _LINUX_PCI_IDS_H */ diff --git a/tools/phytium-pi/__pycache__/py_terminal.cpython-311.pyc b/tools/phytium-pi/__pycache__/py_terminal.cpython-311.pyc new file mode 100644 index 0000000000..3cade90ed9 Binary files /dev/null and b/tools/phytium-pi/__pycache__/py_terminal.cpython-311.pyc differ diff --git a/tools/phytium-pi/phytium-pi-board.dtb b/tools/phytium-pi/phytium-pi-board.dtb new file mode 100755 index 0000000000..f26b397243 Binary files /dev/null and b/tools/phytium-pi/phytium-pi-board.dtb differ diff --git a/tools/phytium-pi/phytium-pi.its b/tools/phytium-pi/phytium-pi.its new file mode 100755 index 0000000000..83c6c42996 --- /dev/null +++ b/tools/phytium-pi/phytium-pi.its @@ -0,0 +1,50 @@ +/* + * U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs + */ + +/dts-v1/; + +/ { + description = "Various kernels, ramdisks and FDT blobs"; + #address-cells = <1>; + + images { + kernel { + description = "ArceOS for Phytium Pi"; + data = /incbin/("../../arceos-phytium-pi.bin.gz"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "gzip"; + load = <0x90100000>; + entry = <0x90100000>; + hash-1 { + algo = "md5"; + }; + hash-2 { + algo = "sha1"; + }; + }; + + fdt-phytium { + description = "phytium-pi fdt"; + data = /incbin/("./phytium-pi-board.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + hash-1 { + algo = "crc32"; + }; + }; + }; + + configurations { + default = "config-phytium-pi"; + + config-phytium-pi { + description = "phytium-pi configuration"; + kernel = "kernel"; + fdt = "fdt-phytium"; + }; + }; +}; diff --git a/tools/phytium-pi/uboot_test_send.py b/tools/phytium-pi/uboot_test_send.py new file mode 100644 index 0000000000..1907001aee --- /dev/null +++ b/tools/phytium-pi/uboot_test_send.py @@ -0,0 +1,99 @@ +import os +os.system('title Terminal S') + +from collections import deque +import threading +import sys + +import colorama +import click +from getch import getch +import serial +from serial.tools import list_ports + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +@click.command(context_settings=CONTEXT_SETTINGS) +@click.option('-p', '--port', default=None, help='serial port name') +@click.option('-b', '--baudrate', default=115200, help='set baud reate') +@click.option('--parity', default='N', type=click.Choice(['N', 'E', 'O', 'S', 'M']), help='set parity') +@click.option('-s', '--stopbits', default=1, help='set stop bits') +@click.option('-l', is_flag=True, help='list serial ports') +def main(port, baudrate, parity, stopbits, l): + if port is None: + ports = list_ports.comports() + if not ports: + print('--- No serial port available ---') + return + if len(ports) == 1: + port = ports[0][0] + else: + print('--- Available Ports ----') + for i, v in enumerate(ports): + print('--- {}: {}'.format(i, v)) + + if l: + return + raw = input('--- Select port index: ') + try: + n = int(raw) + port = ports[n][0] + except: + return + try: + device = serial.Serial(port=port, + baudrate=baudrate, + bytesize=8, + parity=parity, + stopbits=stopbits, + timeout=0.1) + except: + print('--- Failed to open {} ---'.format(port)) + return + + print('--- Press Ctrl+] to quit ---') + + queue = deque() + + def read_input(): + while device.is_open: + ch = getch() + # print(ch) + if ch == b'\x1d': # 'ctrl + ]' to quit + break + if ch == b'\x00' or ch == b'\xe0': # arrow keys' escape sequences + ch2 = getch() + conv = { b'H': b'A', b'P': b'B', b'M': b'C', b'K': b'D' } + if ch2 in conv: + # Esc[ + queue.append(b'\x1b[' + conv[ch2]) + else: + queue.append(ch + ch2) + else: + queue.append(ch) + + colorama.init() + + thread = threading.Thread(target=read_input) + thread.start() + while thread.is_alive(): + try: + length = len(queue) + if length > 0: + device.write(b''.join(queue.popleft() for _ in range(length))) + + line = device.readline() + if line: + print(line.decode(), end='', flush=True) + except IOError: + print('Device is disconnected') + break + except UnicodeDecodeError: + print([x for x in line]) + + device.close() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/phytium-pi/uboot_transfer.py b/tools/phytium-pi/uboot_transfer.py new file mode 100644 index 0000000000..0322dcf672 --- /dev/null +++ b/tools/phytium-pi/uboot_transfer.py @@ -0,0 +1,118 @@ +import serial +import sys +import os +import time +import threading + +class UbootTransfer: + def __init__(self, device, baud, filePath): + self.device = device + self.baud = baud + self.filePath = filePath + # 打开串口 + print("Open serial device") + self.ser = serial.Serial(device, baud, timeout=1) + + def checkDevice(self): + # 检查串口设备是否存在 + if not os.path.exists(self.device): + print("Device {} does not exist".format(self.device)) + sys.exit(1) + + def readOutput(self): + while True: + line = self.ser.readline().decode().strip() + if line: + print(line) + if 'Phytium-Pi#' in line: + break + + def start(self): + while True: + if self.ser.in_waiting: + # 读取串口数据 + serial_data = self.ser.read(self.ser.in_waiting).decode('utf-8') + print(serial_data, end='') + + # 从终端获取用户输入,并发送到串口 + if serial_data.endswith('# '): + user_input = input() + '\r\n' + self.ser.write(user_input.encode('utf-8')) + + def transfer(self): + # 检查串口设备是否存在 + self.checkDevice() + + try: + # 等待串口输出 'Hit any key to stop autoboot:',然后模拟输入 + # while True: + # line = self.ser.readline().decode().strip() + # if line: + # print(line) + # if 'Hit any key' in line: + # print("find the line: Hit any key to stop autoboot:") + # #self.sendCommand(); + # self.ser.write(b'qwertyuiop\n') + # self.ser.write(b'asdfghjkl\n') + # self.ser.write(b'zxcvbnm\n') + # break + + + # 他妈的我是真的服了啊,浪费将近一天的时间研究到底是怎么进入系统的 + # 一开始以为是发送的回车是有问题的,后面测试发送其他字符也没有问题 + # 手动进入中断后发送回车也是没有问题的,但是就是在等待'Hit any key to stop autoboot:'的时候不行了 + # 直接暴力做法在进入之前循环发送回车 + # 真的是太坐牢了啊 + # 在没有检测到'Phytium-Pi#'之前,循环发送回车 + while True: + self.ser.write(b'\n') + line = self.ser.readline().decode().strip() + if line: + print(line) + if 'Phytium-Pi#' in line: + break + + # 检测到输出'Phytium-Pi#'字样后,模拟输入指令 + while True: + line = self.ser.readline().decode().strip() + if line: + print(line) + if 'Phytium-Pi#' in line: + print("find the line: Phytium-Pi#") + # 发送命令:usb start; fatload usb 0 0x90100000 文件名; go 0x90100000 + self.ser.write(b'usb start\n') + self.readOutput() + self.ser.write(b'fatls usb 0\n') + self.readOutput() + self.ser.write(b'fatload usb 0 0x90100000 ' + filePath.encode() + b'\n') + self.readOutput() + self.ser.write(b'go 0x90100000\n') + self.readOutput() + print("finish send command") + break + + # 模拟终端,接收用户输入并发送到串口,同时打印串口输出 + # 用户输入一个指令之后,发送到串口,然后等待串口输出,然后打印输出 + # 等待出现 Phytium-Pi# 用户可以发送下一个指令 + self.start() + + + except serial.SerialException as e: + print("Serial error:", e) + + finally: + self.ser.close() + +# 入口函数 +if __name__ == '__main__': + print("-- Uboot Transfer --") + if len(sys.argv) != 4: + print("Usage: python uboot_transfer.py ") + sys.exit(1) + + device = sys.argv[1] + baud = int(sys.argv[2]) + filePath = sys.argv[3] + + ubootTransfer = UbootTransfer(device, baud, filePath) + ubootTransfer.transfer() diff --git a/tools/phytium-pi/uboot_transfer.rb b/tools/phytium-pi/uboot_transfer.rb new file mode 100644 index 0000000000..dc1b00c2db --- /dev/null +++ b/tools/phytium-pi/uboot_transfer.rb @@ -0,0 +1,69 @@ +require 'serialport' + +class UbootTransfer + def initialize(device, baud, file_path) + @device = device + @baud = baud + @file_path = file_path + end + + def check_device + unless File.exist?(@device) + puts "Device #{@device} does not exist" + exit(1) + end + end + + def transfer + check_device + + puts "Open serial device" + ser = SerialPort.new(@device, @baud, 8, 1, SerialPort::NONE) + + begin + loop do + line = ser.readline.strip + puts line unless line.empty? + break if line.include?('Hit any key') + + ser.write("\r\n") + end + + loop do + line = ser.readline.strip + puts line unless line.empty? + break if line.include?('Phytium-Pi#') + + ser.write("usb start; fatload usb 0 0x90100000 #{@file_path}\r\n") + ser.write("go 0x90100000\r\n") + end + + loop do + user_input = gets.chomp + ser.write("#{user_input}\r\n") + line = ser.readline.strip + puts line unless line.empty? + break if user_input == 'exit' + end + rescue IOError => e + puts "Serial error: #{e.message}" + ensure + ser.close + end + end +end + +if __FILE__ == $PROGRAM_NAME + puts "-- Uboot Transfer --" + unless ARGV.length == 3 + puts "Usage: ruby uboot_transfer.rb " + exit(1) + end + + device = ARGV[0] + baud = ARGV[1].to_i + file_path = ARGV[2] + + uboot_transfer = UbootTransfer.new(device, baud, file_path) + uboot_transfer.transfer +end diff --git a/tools/phytium-pi/yet_another_uboot_transfer.py b/tools/phytium-pi/yet_another_uboot_transfer.py new file mode 100755 index 0000000000..24cf91cfbc --- /dev/null +++ b/tools/phytium-pi/yet_another_uboot_transfer.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +#↑兄啊你不知道uboot可以保存启动配置的嘛?设置为默认等待从串口传入内核就好了啊? +import sys +import time +import serial +from xmodem import XMODEM + +def send_file(port, baudrate, file_path): + # 打开串口 + ser = serial.Serial(port, baudrate, timeout=1) + + # 等待 U-Boot 提示符 + while True: + line = ser.readline().decode('utf-8', errors='ignore').strip() + print(line) + if line.endswith('Phytium-Pi#'): + break + + # 发送 loady 命令 + ser.write(b'loadx 0x90100000\n') + time.sleep(0.5) + + # 等待 U-Boot 准备好接收文件 + while True: + line = ser.readline().decode('utf-8', errors='ignore').strip() + print(line) + if 'Ready for binary' in line: + break + + # 发送 'C' 字符开始传输 + ser.write(b'C') + + # 使用 xmodem 协议传输文件 + with open(file_path, 'rb') as f: + def getc(size, timeout=1): + return ser.read(size) or None + + def putc(data, timeout=1): + return ser.write(data) + + modem = XMODEM(getc, putc) + modem.send(f) + + # 关闭串口 + ser.close() + +if __name__ == '__main__': + if len(sys.argv) != 4: + print("Usage: python script.py ") + sys.exit(1) + + port = sys.argv[1] + baudrate = int(sys.argv[2]) + file_path = sys.argv[3] + + send_file(port, baudrate, file_path) diff --git a/tools/raspi4/chainloader/.gitignore b/tools/raspi4/chainloader/.gitignore new file mode 100644 index 0000000000..1bebdabd4b --- /dev/null +++ b/tools/raspi4/chainloader/.gitignore @@ -0,0 +1,3 @@ +/target/ +target/ +/target diff --git a/tools/raspi4/chainloader/.vscode/settings.json b/tools/raspi4/chainloader/.vscode/settings.json new file mode 100644 index 0000000000..bfa278e9aa --- /dev/null +++ b/tools/raspi4/chainloader/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "editor.formatOnSave": true, + "editor.rulers": [100], + "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat", + "rust-analyzer.cargo.features": ["bsp_rpi3"], + "rust-analyzer.checkOnSave.allTargets": false, + "rust-analyzer.checkOnSave.extraArgs": ["--bins"], + "rust-analyzer.lens.debug": false, + "rust-analyzer.lens.run": false +} diff --git a/tools/raspi4/chainloader/Cargo.lock b/tools/raspi4/chainloader/Cargo.lock new file mode 100644 index 0000000000..047875fe58 --- /dev/null +++ b/tools/raspi4/chainloader/Cargo.lock @@ -0,0 +1,26 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aceb88e55ba626a5479279268d009a92d9d00eacce0de1b8c236c7ad31b7225" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "mingo" +version = "0.6.0" +dependencies = [ + "aarch64-cpu", + "tock-registers", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" diff --git a/tools/raspi4/chainloader/Cargo.toml b/tools/raspi4/chainloader/Cargo.toml new file mode 100644 index 0000000000..1fe55455ef --- /dev/null +++ b/tools/raspi4/chainloader/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "mingo" +version = "0.6.0" +authors = ["Andre Richter "] +edition = "2021" + +[profile.release] +lto = true + +[features] +default = [] +bsp_rpi3 = ["tock-registers"] +bsp_rpi4 = ["tock-registers"] +enable_jtag_debug = [] + +[[bin]] +name = "kernel" +path = "src/main.rs" + +##-------------------------------------------------------------------------------------------------- +## Dependencies +##-------------------------------------------------------------------------------------------------- + +[dependencies] + +# Optional dependencies +tock-registers = { version = "0.8.x", default-features = false, features = ["register_types"], optional = true } + +# Platform specific dependencies +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = { version = "9.x.x" } + +[workspace] diff --git a/tools/raspi4/chainloader/Makefile b/tools/raspi4/chainloader/Makefile new file mode 100644 index 0000000000..2c3620ca98 --- /dev/null +++ b/tools/raspi4/chainloader/Makefile @@ -0,0 +1,236 @@ +## SPDX-License-Identifier: MIT OR Apache-2.0 +## +## Copyright (c) 2018-2023 Andre Richter + +include ../common/docker.mk +include ../common/format.mk +include ../common/operating_system.mk + +##-------------------------------------------------------------------------------------------------- +## Optional, user-provided configuration values +##-------------------------------------------------------------------------------------------------- + +# Default to the RPi3. +BSP ?= rpi4 + +# Default to a serial device name that is common in Linux. +DEV_SERIAL ?= /dev/ttyUSB0 + +# Default not to enable jtag debug +JTAG ?= n + +##-------------------------------------------------------------------------------------------------- +## BSP-specific configuration values +##-------------------------------------------------------------------------------------------------- +QEMU_MISSING_STRING = "This board is not yet supported for QEMU." + +TARGET = aarch64-unknown-none-softfloat +KERNEL_BIN = kernel8.img +QEMU_BINARY = qemu-system-aarch64 +QEMU_MACHINE_TYPE = +QEMU_RELEASE_ARGS = -serial stdio -display none +OBJDUMP_BINARY = aarch64-none-elf-objdump +NM_BINARY = aarch64-none-elf-nm +READELF_BINARY = aarch64-none-elf-readelf +LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +RUSTC_MISC_ARGS = -C target-cpu=cortex-a72 +CHAINBOOT_DEMO_PAYLOAD = demo_payload_rpi4.img + +# Export for build.rs. +export LD_SCRIPT_PATH + + + +##-------------------------------------------------------------------------------------------------- +## Targets and Prerequisites +##-------------------------------------------------------------------------------------------------- +KERNEL_MANIFEST = Cargo.toml +KERNEL_LINKER_SCRIPT = kernel.ld +LAST_BUILD_CONFIG = target/$(BSP).build_config + +KERNEL_ELF = target/$(TARGET)/release/kernel +# This parses cargo's dep-info file. +# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files +KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG) + + + +##-------------------------------------------------------------------------------------------------- +## Command building blocks +##-------------------------------------------------------------------------------------------------- +RUSTFLAGS = $(RUSTC_MISC_ARGS) \ + -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ + -C link-arg=--script=$(KERNEL_LINKER_SCRIPT) + +RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \ + -D warnings \ + -D missing_docs + +FEATURES = --features bsp_$(BSP) +ifeq ($(JTAG),y) + FEATURES += --features enable_jtag_debug +endif +COMPILER_ARGS = --target=$(TARGET) \ + $(FEATURES) \ + --release + +RUSTC_CMD = cargo rustc $(COMPILER_ARGS) +DOC_CMD = cargo doc $(COMPILER_ARGS) +CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) +OBJCOPY_CMD = rust-objcopy \ + --strip-all \ + -O binary + +EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) +EXEC_TEST_MINIPUSH = ruby tests/chainboot_test.rb +EXEC_MINIPUSH = ruby ../common/serial/minipush.rb + +##------------------------------------------------------------------------------ +## Dockerization +##------------------------------------------------------------------------------ +DOCKER_CMD = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial +DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i +DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common +DOCKER_ARG_DEV = --privileged -v /dev:/dev + +# DOCKER_IMAGE defined in include file (see top of this file). +DOCKER_QEMU = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE) +DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE) +DOCKER_TEST = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE) + +# Dockerize commands, which require USB device passthrough, only on Linux. +ifeq ($(shell uname -s),Linux) + DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV) + + DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE) +endif + + + +##-------------------------------------------------------------------------------------------------- +## Targets +##-------------------------------------------------------------------------------------------------- +.PHONY: all doc qemu chainboot clippy clean readelf objdump nm check + +all: clean $(KERNEL_BIN) + +##------------------------------------------------------------------------------ +## Save the configuration as a file, so make understands if it changed. +##------------------------------------------------------------------------------ +$(LAST_BUILD_CONFIG): + @rm -f target/*.build_config + @mkdir -p target + @touch $(LAST_BUILD_CONFIG) + +##------------------------------------------------------------------------------ +## Compile the kernel ELF +##------------------------------------------------------------------------------ +$(KERNEL_ELF): $(KERNEL_ELF_DEPS) + $(call color_header, "Compiling kernel ELF - $(BSP)") + @RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD) + +##------------------------------------------------------------------------------ +## Generate the stripped kernel binary +##------------------------------------------------------------------------------ +$(KERNEL_BIN): $(KERNEL_ELF) + $(call color_header, "Generating stripped binary") + @$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN) + $(call color_progress_prefix, "Name") + @echo $(KERNEL_BIN) + $(call color_progress_prefix, "Size") + $(call disk_usage_KiB, $(KERNEL_BIN)) + +##------------------------------------------------------------------------------ +## Generate the documentation +##------------------------------------------------------------------------------ +doc: + $(call color_header, "Generating docs") + @$(DOC_CMD) --document-private-items --open + +##------------------------------------------------------------------------------ +## Run the kernel in QEMU +##------------------------------------------------------------------------------ +ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board. + +qemu qemuasm: + $(call color_header, "$(QEMU_MISSING_STRING)") + +else # QEMU is supported. + +qemu: $(KERNEL_BIN) + $(call color_header, "Launching QEMU") + @$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) + +qemuasm: $(KERNEL_BIN) + $(call color_header, "Launching QEMU with ASM output") + @$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -d in_asm + +endif + +##------------------------------------------------------------------------------ +## Push the kernel to the real HW target +##------------------------------------------------------------------------------ +chainboot: $(KERNEL_BIN) + @$(DOCKER_CHAINBOOT) $(EXEC_MINIPUSH) $(DEV_SERIAL) $(CHAINBOOT_DEMO_PAYLOAD) + +##------------------------------------------------------------------------------ +## Run clippy +##------------------------------------------------------------------------------ +clippy: + @RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD) + +##------------------------------------------------------------------------------ +## Clean +##------------------------------------------------------------------------------ +clean: + rm -rf target $(KERNEL_BIN) + +##------------------------------------------------------------------------------ +## Run readelf +##------------------------------------------------------------------------------ +readelf: $(KERNEL_ELF) + $(call color_header, "Launching readelf") + @$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF) + +##------------------------------------------------------------------------------ +## Run objdump +##------------------------------------------------------------------------------ +objdump: $(KERNEL_ELF) + $(call color_header, "Launching objdump") + @$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \ + --section .text \ + --section .rodata \ + $(KERNEL_ELF) | rustfilt + +##------------------------------------------------------------------------------ +## Run nm +##------------------------------------------------------------------------------ +nm: $(KERNEL_ELF) + $(call color_header, "Launching nm") + @$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt + + + +##-------------------------------------------------------------------------------------------------- +## Testing targets +##-------------------------------------------------------------------------------------------------- +.PHONY: test test_boot + +ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board. + +test_boot test: + $(call color_header, "$(QEMU_MISSING_STRING)") + +else # QEMU is supported. + +##------------------------------------------------------------------------------ +## Run boot test +##------------------------------------------------------------------------------ +test_boot: $(KERNEL_BIN) + $(call color_header, "Boot test - $(BSP)") + @$(DOCKER_TEST) $(EXEC_TEST_MINIPUSH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) \ + -kernel $(KERNEL_BIN) $(CHAINBOOT_DEMO_PAYLOAD) + +test: test_boot + +endif diff --git a/tools/raspi4/chainloader/README.CN.md b/tools/raspi4/chainloader/README.CN.md new file mode 100644 index 0000000000..de7f51114a --- /dev/null +++ b/tools/raspi4/chainloader/README.CN.md @@ -0,0 +1,116 @@ +# 教程06 - UART链加载器 + +## tl;dr + +- 从SD卡上运行是一次不错的体验,但是每次都为每个新的二进制文件这样做将非常繁琐。 + 因此,让我们编写一个[chainloader]。 +- 这将是您需要放在SD卡上的最后一个二进制文件。 + 每个后续的教程都将在`Makefile`中提供一个`chainboot`,让您方便地通过`UART`加载内核。 + +[chainloader]: https://en.wikipedia.org/wiki/Chain_loading + + +## 注意 + +请注意,这个教程中有一些内容仅通过查看源代码很难理解。 + +大致的意思是,在`boot.s`中,我们编写了一段[position independent code]代码, +它会自动确定固件加载二进制文件的位置(`0x8_0000`),以及链接到的位置(`0x200_0000`,参见 `kernel.ld`)。 +然后,二进制文件将自身从加载地址复制到链接地址(也就是"重定位"自身),然后跳转到`_start_rust()`的重定位版本。 + +由于链加载程序现在已经"脱离了路径",它现在可以从`UART`接收另一个内核二进制文件,并将其复制到RPi固件的标准加载地址`0x8_0000`。 +最后,它跳转到`0x8_0000`,新加载的二进制文件会透明地执行,就好像它一直从SD卡加载一样。 + +在我有时间详细写下这些内容之前,请耐心等待。目前,请将这个教程视为一种便利功能的启用程序,它允许快速启动以下教程。 +_对于那些渴望深入了解的人,可以直接跳到第[15章](../15_virtual_mem_part3_precomputed_tables),阅读README的前半部分, +其中讨论了`Load Address != Link Address`的问题_。 + +[position independent code]: https://en.wikipedia.org/wiki/Position-independent_code + +## 安装并测试它 + +我们的链加载程序称为`MiniLoad`,受到了[raspbootin]的启发。 + +您可以按照以下教程尝试它: +1. 根据您的目标硬件运行命令:`make`或`BSP=rpi4 make`。 +1. 将`kernel8.img`复制到SD卡中,并将SD卡重新插入您的RPi。 +1. 运行命令`make chainboot`或`BSP=rpi4 make chainboot`。 +1. 将USB串口连接到您的主机PC上。 + - 请参考[top-level README](../README.md#-usb-serial-output)中的接线图。 + - 确保您**没有**连接USB串口的电源引脚,只连接RX/TX和GND。 +1. 将RPi连接到(USB)电源线。 +1. 观察加载程序通过`UART`获取内核: + +> ❗ **注意**: `make chainboot`假设默认的串行设备名称为`/dev/ttyUSB0`。根据您的主机操作系统,设备名称可能会有所不同。 +> 例如,在`macOS`上,它可能是类似于`/dev/tty.usbserial-0001`的名称。 +> 在这种情况下,请明确给出设备名称: + + +```console +$ DEV_SERIAL=/dev/tty.usbserial-0001 make chainboot +``` + +[raspbootin]: https://github.com/mrvn/raspbootin + +```console +$ make chainboot +[...] +Minipush 1.0 + +[MP] ⏳ Waiting for /dev/ttyUSB0 +[MP] ✅ Serial connected +[MP] 🔌 Please power the target now + + __ __ _ _ _ _ +| \/ (_)_ _ (_) | ___ __ _ __| | +| |\/| | | ' \| | |__/ _ \/ _` / _` | +|_| |_|_|_||_|_|____\___/\__,_\__,_| + + Raspberry Pi 3 + +[ML] Requesting binary +[MP] ⏩ Pushing 7 KiB ==========================================🦀 100% 0 KiB/s Time: 00:00:00 +[ML] Loaded! Executing the payload now + +[0] mingo version 0.5.0 +[1] Booting on: Raspberry Pi 3 +[2] Drivers loaded: + 1. BCM PL011 UART + 2. BCM GPIO +[3] Chars written: 117 +[4] Echoing input now +``` + +在这个教程中,为了演示目的,加载了上一个教程中的内核版本。在后续的教程中,将使用工作目录的内核。 + +## 测试它 + +这个教程中的`Makefile`有一个额外的目标`qemuasm`,它可以让你很好地观察到内核在重新定位后如何从加载地址区域(`0x80_XXX`) +跳转到重新定位的代码(`0x0200_0XXX`): + +```console +$ make qemuasm +[...] +N: +0x00080030: 58000140 ldr x0, #0x80058 +0x00080034: 9100001f mov sp, x0 +0x00080038: 58000141 ldr x1, #0x80060 +0x0008003c: d61f0020 br x1 + +---------------- +IN: +0x02000070: 9400044c bl #0x20011a0 + +---------------- +IN: +0x020011a0: 90000008 adrp x8, #0x2001000 +0x020011a4: 90000009 adrp x9, #0x2001000 +0x020011a8: f9446508 ldr x8, [x8, #0x8c8] +0x020011ac: f9446929 ldr x9, [x9, #0x8d0] +0x020011b0: eb08013f cmp x9, x8 +0x020011b4: 54000109 b.ls #0x20011d4 +[...] +``` + +## 相比之前的变化(diff) +请检查[英文版本](README.md#diff-to-previous),这是最新的。 \ No newline at end of file diff --git a/tools/raspi4/chainloader/README.md b/tools/raspi4/chainloader/README.md new file mode 100644 index 0000000000..5e4efe25dd --- /dev/null +++ b/tools/raspi4/chainloader/README.md @@ -0,0 +1,670 @@ +# Tutorial 06 - UART Chainloader + +## tl;dr + +- Running from an SD card was a nice experience, but it would be extremely tedious to do it for + every new binary. So let's write a [chainloader]. +- This will be the last binary you need to put on the SD card. Each following tutorial will provide + a `chainboot` target in the `Makefile` that lets you conveniently load the kernel over `UART`. + +[chainloader]: https://en.wikipedia.org/wiki/Chain_loading + + +## Note + +Please note that there is stuff going on in this tutorial that is very hard to grasp by only looking +at the source code changes. + +The gist of it is that in `boot.s`, we are writing a piece of [position independent code] which +automatically determines where the firmware has loaded the binary (`0x8_0000`), and where it was +linked to (`0x200_0000`, see `kernel.ld`). The binary then copies itself from loaded to linked +address (aka "relocating" itself), and then jumps to the relocated version of `_start_rust()`. + +Since the chainloader has put itself "out of the way" now, it can now receive another kernel binary +from the `UART` and copy it to the standard load address of the RPi firmware at `0x8_0000`. Finally, +it jumps to `0x8_0000` and the newly loaded binary transparently executes as if it had been loaded +from SD card all along. + +Please bear with me until I find the time to write it all down here elaborately. For the time being, +please see this tutorial as an enabler for a convenience feature that allows booting the following +tutorials in a quick manner. _For those keen to get a deeper understanding, it could make sense to +skip forward to [Chapter 15](../15_virtual_mem_part3_precomputed_tables) and read the first half of +the README, where `Load Address != Link Address` is discussed_. + +[position independent code]: https://en.wikipedia.org/wiki/Position-independent_code + +## Install and test it + +Our chainloader is called `MiniLoad` and is inspired by [raspbootin]. + +You can try it with this tutorial already: +1. Depending on your target hardware, run:`make` or `BSP=rpi4 make`. +1. Copy `kernel8.img` to the SD card and put the SD card back into your RPi. +1. Run `make chainboot` or `BSP=rpi4 make chainboot`. +1. Connect the USB serial to your host PC. + - Wiring diagram at [top-level README](../README.md#-usb-serial-output). + - Make sure that you **DID NOT** connect the power pin of the USB serial. Only RX/TX and GND. +1. Connect the RPi to the (USB) power cable. +1. Observe the loader fetching a kernel over `UART`: + +> ❗ **NOTE**: `make chainboot` assumes a default serial device name of `/dev/ttyUSB0`. Depending on +> your host operating system, the device name might differ. For example, on `macOS`, it might be +> something like `/dev/tty.usbserial-0001`. In this case, please give the name explicitly: + + +```console +$ DEV_SERIAL=/dev/tty.usbserial-0001 make chainboot +``` + +[raspbootin]: https://github.com/mrvn/raspbootin + +```console +$ make chainboot +[...] +Minipush 1.0 + +[MP] ⏳ Waiting for /dev/ttyUSB0 +[MP] ✅ Serial connected +[MP] 🔌 Please power the target now + + __ __ _ _ _ _ +| \/ (_)_ _ (_) | ___ __ _ __| | +| |\/| | | ' \| | |__/ _ \/ _` / _` | +|_| |_|_|_||_|_|____\___/\__,_\__,_| + + Raspberry Pi 3 + +[ML] Requesting binary +[MP] ⏩ Pushing 7 KiB ==========================================🦀 100% 0 KiB/s Time: 00:00:00 +[ML] Loaded! Executing the payload now + +[0] mingo version 0.5.0 +[1] Booting on: Raspberry Pi 3 +[2] Drivers loaded: + 1. BCM PL011 UART + 2. BCM GPIO +[3] Chars written: 117 +[4] Echoing input now +``` + +In this tutorial, a version of the kernel from the previous tutorial is loaded for demo purposes. In +subsequent tutorials, it will be the working directory's kernel. + +## Test it + +The `Makefile` in this tutorial has an additional target, `qemuasm`, that lets you nicely observe +how the kernel, after relocating itself, jumps the load address region (`0x80_XXX`) to the relocated +code at (`0x0200_0XXX`): + +```console +$ make qemuasm +[...] +N: +0x00080030: 58000140 ldr x0, #0x80058 +0x00080034: 9100001f mov sp, x0 +0x00080038: 58000141 ldr x1, #0x80060 +0x0008003c: d61f0020 br x1 + +---------------- +IN: +0x02000070: 9400044c bl #0x20011a0 + +---------------- +IN: +0x020011a0: 90000008 adrp x8, #0x2001000 +0x020011a4: 90000009 adrp x9, #0x2001000 +0x020011a8: f9446508 ldr x8, [x8, #0x8c8] +0x020011ac: f9446929 ldr x9, [x9, #0x8d0] +0x020011b0: eb08013f cmp x9, x8 +0x020011b4: 54000109 b.ls #0x20011d4 +[...] +``` + +## Diff to previous +```diff + +diff -uNr 05_drivers_gpio_uart/Cargo.toml 06_uart_chainloader/Cargo.toml +--- 05_drivers_gpio_uart/Cargo.toml ++++ 06_uart_chainloader/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "mingo" +-version = "0.5.0" ++version = "0.6.0" + authors = ["Andre Richter "] + edition = "2021" + +Binary files 05_drivers_gpio_uart/demo_payload_rpi3.img and 06_uart_chainloader/demo_payload_rpi3.img differ +Binary files 05_drivers_gpio_uart/demo_payload_rpi4.img and 06_uart_chainloader/demo_payload_rpi4.img differ + +diff -uNr 05_drivers_gpio_uart/Makefile 06_uart_chainloader/Makefile +--- 05_drivers_gpio_uart/Makefile ++++ 06_uart_chainloader/Makefile +@@ -24,27 +24,29 @@ + QEMU_MISSING_STRING = "This board is not yet supported for QEMU." + + ifeq ($(BSP),rpi3) +- TARGET = aarch64-unknown-none-softfloat +- KERNEL_BIN = kernel8.img +- QEMU_BINARY = qemu-system-aarch64 +- QEMU_MACHINE_TYPE = raspi3 +- QEMU_RELEASE_ARGS = -serial stdio -display none +- OBJDUMP_BINARY = aarch64-none-elf-objdump +- NM_BINARY = aarch64-none-elf-nm +- READELF_BINARY = aarch64-none-elf-readelf +- LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +- RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 ++ TARGET = aarch64-unknown-none-softfloat ++ KERNEL_BIN = kernel8.img ++ QEMU_BINARY = qemu-system-aarch64 ++ QEMU_MACHINE_TYPE = raspi3 ++ QEMU_RELEASE_ARGS = -serial stdio -display none ++ OBJDUMP_BINARY = aarch64-none-elf-objdump ++ NM_BINARY = aarch64-none-elf-nm ++ READELF_BINARY = aarch64-none-elf-readelf ++ LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi ++ RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 ++ CHAINBOOT_DEMO_PAYLOAD = demo_payload_rpi3.img + else ifeq ($(BSP),rpi4) +- TARGET = aarch64-unknown-none-softfloat +- KERNEL_BIN = kernel8.img +- QEMU_BINARY = qemu-system-aarch64 +- QEMU_MACHINE_TYPE = +- QEMU_RELEASE_ARGS = -serial stdio -display none +- OBJDUMP_BINARY = aarch64-none-elf-objdump +- NM_BINARY = aarch64-none-elf-nm +- READELF_BINARY = aarch64-none-elf-readelf +- LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +- RUSTC_MISC_ARGS = -C target-cpu=cortex-a72 ++ TARGET = aarch64-unknown-none-softfloat ++ KERNEL_BIN = kernel8.img ++ QEMU_BINARY = qemu-system-aarch64 ++ QEMU_MACHINE_TYPE = ++ QEMU_RELEASE_ARGS = -serial stdio -display none ++ OBJDUMP_BINARY = aarch64-none-elf-objdump ++ NM_BINARY = aarch64-none-elf-nm ++ READELF_BINARY = aarch64-none-elf-readelf ++ LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi ++ RUSTC_MISC_ARGS = -C target-cpu=cortex-a72 ++ CHAINBOOT_DEMO_PAYLOAD = demo_payload_rpi4.img + endif + + # Export for build.rs. +@@ -90,8 +92,8 @@ + -O binary + + EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) +-EXEC_TEST_DISPATCH = ruby ../common/tests/dispatch.rb +-EXEC_MINITERM = ruby ../common/serial/miniterm.rb ++EXEC_TEST_MINIPUSH = ruby tests/chainboot_test.rb ++EXEC_MINIPUSH = ruby ../common/serial/minipush.rb + + ##------------------------------------------------------------------------------ + ## Dockerization +@@ -110,7 +112,7 @@ + ifeq ($(shell uname -s),Linux) + DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV) + +- DOCKER_MINITERM = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE) ++ DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE) + endif + + +@@ -118,7 +120,7 @@ + ##-------------------------------------------------------------------------------------------------- + ## Targets + ##-------------------------------------------------------------------------------------------------- +-.PHONY: all doc qemu miniterm clippy clean readelf objdump nm check ++.PHONY: all doc qemu chainboot clippy clean readelf objdump nm check + + all: $(KERNEL_BIN) + +@@ -160,7 +162,7 @@ + ##------------------------------------------------------------------------------ + ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board. + +-qemu: ++qemu qemuasm: + $(call color_header, "$(QEMU_MISSING_STRING)") + + else # QEMU is supported. +@@ -169,13 +171,17 @@ + $(call color_header, "Launching QEMU") + @$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) + ++qemuasm: $(KERNEL_BIN) ++ $(call color_header, "Launching QEMU with ASM output") ++ @$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -d in_asm ++ + endif + ##------------------------------------------------------------------------------ +-## Connect to the target's serial ++## Push the kernel to the real HW target + ##------------------------------------------------------------------------------ +-miniterm: +- @$(DOCKER_MINITERM) $(EXEC_MINITERM) $(DEV_SERIAL) ++chainboot: $(KERNEL_BIN) ++ @$(DOCKER_CHAINBOOT) $(EXEC_MINIPUSH) $(DEV_SERIAL) $(CHAINBOOT_DEMO_PAYLOAD) + + ##------------------------------------------------------------------------------ + ## Run clippy +@@ -232,7 +238,8 @@ + ##------------------------------------------------------------------------------ + test_boot: $(KERNEL_BIN) + $(call color_header, "Boot test - $(BSP)") +- @$(DOCKER_TEST) $(EXEC_TEST_DISPATCH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) ++ @$(DOCKER_TEST) $(EXEC_TEST_MINIPUSH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) \ ++ -kernel $(KERNEL_BIN) $(CHAINBOOT_DEMO_PAYLOAD) + + test: test_boot + + +diff -uNr 05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.s 06_uart_chainloader/src/_arch/aarch64/cpu/boot.s +--- 05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.s ++++ 06_uart_chainloader/src/_arch/aarch64/cpu/boot.s +@@ -18,6 +18,17 @@ + add \register, \register, #:lo12:\symbol + .endm + ++// Load the address of a symbol into a register, absolute. ++// ++// # Resources ++// ++// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html ++.macro ADR_ABS register, symbol ++ movz \register, #:abs_g2:\symbol ++ movk \register, #:abs_g1_nc:\symbol ++ movk \register, #:abs_g0_nc:\symbol ++.endm ++ + //-------------------------------------------------------------------------------------------------- + // Public Code + //-------------------------------------------------------------------------------------------------- +@@ -37,23 +48,35 @@ + // If execution reaches here, it is the boot core. + + // Initialize DRAM. +- ADR_REL x0, __bss_start +- ADR_REL x1, __bss_end_exclusive ++ ADR_ABS x0, __bss_start ++ ADR_ABS x1, __bss_end_exclusive + + .L_bss_init_loop: + cmp x0, x1 +- b.eq .L_prepare_rust ++ b.eq .L_relocate_binary + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + ++ // Next, relocate the binary. ++.L_relocate_binary: ++ ADR_REL x0, __binary_nonzero_start // The address the binary got loaded to. ++ ADR_ABS x1, __binary_nonzero_start // The address the binary was linked to. ++ ADR_ABS x2, __binary_nonzero_end_exclusive ++ ++.L_copy_loop: ++ ldr x3, [x0], #8 ++ str x3, [x1], #8 ++ cmp x1, x2 ++ b.lo .L_copy_loop ++ + // Prepare the jump to Rust code. +-.L_prepare_rust: + // Set the stack pointer. +- ADR_REL x0, __boot_core_stack_end_exclusive ++ ADR_ABS x0, __boot_core_stack_end_exclusive + mov sp, x0 + +- // Jump to Rust code. +- b _start_rust ++ // Jump to the relocated Rust code. ++ ADR_ABS x1, _start_rust ++ br x1 + + // Infinitely wait for events (aka "park the core"). + .L_parking_loop: + +diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +--- 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs ++++ 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +@@ -275,7 +275,7 @@ + } + + /// Retrieve a character. +- fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Option { ++ fn read_char(&mut self, blocking_mode: BlockingMode) -> Option { + // If RX FIFO is empty, + if self.registers.FR.matches_all(FR::RXFE::SET) { + // immediately return in non-blocking mode. +@@ -290,12 +290,7 @@ + } + + // Read one character. +- let mut ret = self.registers.DR.get() as u8 as char; +- +- // Convert carrige return to newline. +- if ret == '\r' { +- ret = '\n' +- } ++ let ret = self.registers.DR.get() as u8 as char; + + // Update statistics. + self.chars_read += 1; +@@ -381,14 +376,14 @@ + impl console::interface::Read for PL011Uart { + fn read_char(&self) -> char { + self.inner +- .lock(|inner| inner.read_char_converting(BlockingMode::Blocking).unwrap()) ++ .lock(|inner| inner.read_char(BlockingMode::Blocking).unwrap()) + } + + fn clear_rx(&self) { + // Read from the RX FIFO until it is indicating empty. + while self + .inner +- .lock(|inner| inner.read_char_converting(BlockingMode::NonBlocking)) ++ .lock(|inner| inner.read_char(BlockingMode::NonBlocking)) + .is_some() + {} + } + +diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs 06_uart_chainloader/src/bsp/raspberrypi/console.rs +--- 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs ++++ 06_uart_chainloader/src/bsp/raspberrypi/console.rs +@@ -1,16 +0,0 @@ +-// SPDX-License-Identifier: MIT OR Apache-2.0 +-// +-// Copyright (c) 2018-2023 Andre Richter +- +-//! BSP console facilities. +- +-use crate::console; +- +-//-------------------------------------------------------------------------------------------------- +-// Public Code +-//-------------------------------------------------------------------------------------------------- +- +-/// Return a reference to the console. +-pub fn console() -> &'static dyn console::interface::All { +- &super::driver::PL011_UART +-} + +diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/kernel.ld 06_uart_chainloader/src/bsp/raspberrypi/kernel.ld +--- 05_drivers_gpio_uart/src/bsp/raspberrypi/kernel.ld ++++ 06_uart_chainloader/src/bsp/raspberrypi/kernel.ld +@@ -3,8 +3,6 @@ + * Copyright (c) 2018-2023 Andre Richter + */ + +-__rpi_phys_dram_start_addr = 0; +- + /* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */ + __rpi_phys_binary_load_addr = 0x80000; + +@@ -28,7 +26,8 @@ + + SECTIONS + { +- . = __rpi_phys_dram_start_addr; ++ /* Set the link address to 32 MiB */ ++ . = 0x2000000; + + /*********************************************************************************************** + * Boot Core Stack +@@ -45,6 +44,7 @@ + /*********************************************************************************************** + * Code + RO Data + Global Offset Table + ***********************************************************************************************/ ++ __binary_nonzero_start = .; + .text : + { + KEEP(*(.text._start)) +@@ -60,6 +60,10 @@ + ***********************************************************************************************/ + .data : { *(.data*) } :segment_data + ++ /* Fill up to 8 byte, b/c relocating the binary is done in u64 chunks */ ++ . = ALIGN(8); ++ __binary_nonzero_end_exclusive = .; ++ + /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ + .bss (NOLOAD) : ALIGN(16) + { + +diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 06_uart_chainloader/src/bsp/raspberrypi/memory.rs +--- 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs ++++ 06_uart_chainloader/src/bsp/raspberrypi/memory.rs +@@ -11,6 +11,7 @@ + /// The board's physical memory map. + #[rustfmt::skip] + pub(super) mod map { ++ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000; + + pub const GPIO_OFFSET: usize = 0x0020_0000; + pub const UART_OFFSET: usize = 0x0020_1000; +@@ -35,3 +36,13 @@ + pub const PL011_UART_START: usize = START + UART_OFFSET; + } + } ++ ++//-------------------------------------------------------------------------------------------------- ++// Public Code ++//-------------------------------------------------------------------------------------------------- ++ ++/// The address on which the Raspberry firmware loads every binary by default. ++#[inline(always)] ++pub fn board_default_load_addr() -> *const u64 { ++ map::BOARD_DEFAULT_LOAD_ADDRESS as _ ++} + +diff -uNr 05_drivers_gpio_uart/src/driver.rs 06_uart_chainloader/src/driver.rs +--- 05_drivers_gpio_uart/src/driver.rs ++++ 06_uart_chainloader/src/driver.rs +@@ -4,10 +4,7 @@ + + //! Driver support. + +-use crate::{ +- println, +- synchronization::{interface::Mutex, NullLock}, +-}; ++use crate::synchronization::{interface::Mutex, NullLock}; + + //-------------------------------------------------------------------------------------------------- + // Private Definitions +@@ -154,14 +151,4 @@ + } + }); + } +- +- /// Enumerate all registered device drivers. +- pub fn enumerate(&self) { +- let mut i: usize = 1; +- self.for_each_descriptor(|descriptor| { +- println!(" {}. {}", i, descriptor.device_driver.compatible()); +- +- i += 1; +- }); +- } + } + +diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs +--- 05_drivers_gpio_uart/src/main.rs ++++ 06_uart_chainloader/src/main.rs +@@ -142,27 +142,55 @@ + kernel_main() + } + ++const MINILOAD_LOGO: &str = r#" ++ __ __ _ _ _ _ ++| \/ (_)_ _ (_) | ___ __ _ __| | ++| |\/| | | ' \| | |__/ _ \/ _` / _` | ++|_| |_|_|_||_|_|____\___/\__,_\__,_| ++"#; ++ + /// The main function running after the early init. + fn kernel_main() -> ! { + use console::console; + +- println!( +- "[0] {} version {}", +- env!("CARGO_PKG_NAME"), +- env!("CARGO_PKG_VERSION") +- ); +- println!("[1] Booting on: {}", bsp::board_name()); ++ println!("{}", MINILOAD_LOGO); ++ println!("{:^37}", bsp::board_name()); ++ println!(); ++ println!("[ML] Requesting binary"); ++ console().flush(); + +- println!("[2] Drivers loaded:"); +- driver::driver_manager().enumerate(); ++ // Discard any spurious received characters before starting with the loader protocol. ++ console().clear_rx(); + +- println!("[3] Chars written: {}", console().chars_written()); +- println!("[4] Echoing input now"); ++ // Notify `Minipush` to send the binary. ++ for _ in 0..3 { ++ console().write_char(3 as char); ++ } + +- // Discard any spurious received characters before going into echo mode. +- console().clear_rx(); +- loop { +- let c = console().read_char(); +- console().write_char(c); ++ // Read the binary's size. ++ let mut size: u32 = u32::from(console().read_char() as u8); ++ size |= u32::from(console().read_char() as u8) << 8; ++ size |= u32::from(console().read_char() as u8) << 16; ++ size |= u32::from(console().read_char() as u8) << 24; ++ ++ // Trust it's not too big. ++ console().write_char('O'); ++ console().write_char('K'); ++ ++ let kernel_addr: *mut u8 = bsp::memory::board_default_load_addr() as *mut u8; ++ unsafe { ++ // Read the kernel byte by byte. ++ for i in 0..size { ++ core::ptr::write_volatile(kernel_addr.offset(i as isize), console().read_char() as u8) ++ } + } ++ ++ println!("[ML] Loaded! Executing the payload now\n"); ++ console().flush(); ++ ++ // Use black magic to create a function pointer. ++ let kernel: fn() -> ! = unsafe { core::mem::transmute(kernel_addr) }; ++ ++ // Jump to loaded kernel! ++ kernel() + } + +diff -uNr 05_drivers_gpio_uart/tests/boot_test_string.rb 06_uart_chainloader/tests/boot_test_string.rb +--- 05_drivers_gpio_uart/tests/boot_test_string.rb ++++ 06_uart_chainloader/tests/boot_test_string.rb +@@ -1,3 +0,0 @@ +-# frozen_string_literal: true +- +-EXPECTED_PRINT = 'Echoing input now' + +diff -uNr 05_drivers_gpio_uart/tests/chainboot_test.rb 06_uart_chainloader/tests/chainboot_test.rb +--- 05_drivers_gpio_uart/tests/chainboot_test.rb ++++ 06_uart_chainloader/tests/chainboot_test.rb +@@ -0,0 +1,78 @@ ++# frozen_string_literal: true ++ ++# SPDX-License-Identifier: MIT OR Apache-2.0 ++# ++# Copyright (c) 2020-2023 Andre Richter ++ ++require_relative '../../common/serial/minipush' ++require_relative '../../common/tests/boot_test' ++require 'pty' ++ ++# Match for the last print that 'demo_payload_rpiX.img' produces. ++EXPECTED_PRINT = 'Echoing input now' ++ ++# Wait for request to power the target. ++class PowerTargetRequestTest < SubtestBase ++ MINIPUSH_POWER_TARGET_REQUEST = 'Please power the target now' ++ ++ def initialize(qemu_cmd, pty_main) ++ super() ++ @qemu_cmd = qemu_cmd ++ @pty_main = pty_main ++ end ++ ++ def name ++ 'Waiting for request to power target' ++ end ++ ++ def run(qemu_out, _qemu_in) ++ expect_or_raise(qemu_out, MINIPUSH_POWER_TARGET_REQUEST) ++ ++ # Now is the time to start QEMU with the chainloader binary. QEMU's virtual tty connects to ++ # the MiniPush instance spawned on pty_main, so that the two processes talk to each other. ++ Process.spawn(@qemu_cmd, in: @pty_main, out: @pty_main, err: '/dev/null') ++ end ++end ++ ++# Extend BootTest so that it listens on the output of a MiniPush instance, which is itself connected ++# to a QEMU instance instead of a real HW. ++class ChainbootTest < BootTest ++ MINIPUSH = '../common/serial/minipush.rb' ++ ++ def initialize(qemu_cmd, payload_path) ++ super(qemu_cmd, EXPECTED_PRINT) ++ ++ @test_name = 'Boot test using Minipush' ++ ++ @payload_path = payload_path ++ end ++ ++ private ++ ++ # override ++ def setup ++ pty_main, pty_secondary = PTY.open ++ mp_out, _mp_in = PTY.spawn("ruby #{MINIPUSH} #{pty_secondary.path} #{@payload_path}") ++ ++ # The subtests (from this class and the parents) listen on @qemu_out_wrapped. Hence, point ++ # it to MiniPush's output. ++ @qemu_out_wrapped = PTYLoggerWrapper.new(mp_out, "\r\n") ++ ++ # Important: Run this subtest before the one in the parent class. ++ @console_subtests.prepend(PowerTargetRequestTest.new(@qemu_cmd, pty_main)) ++ end ++ ++ # override ++ def finish ++ super() ++ @test_output.map! { |x| x.gsub(/.*\r/, ' ') } ++ end ++end ++ ++##-------------------------------------------------------------------------------------------------- ++## Execution starts here ++##-------------------------------------------------------------------------------------------------- ++payload_path = ARGV.pop ++qemu_cmd = ARGV.join(' ') ++ ++ChainbootTest.new(qemu_cmd, payload_path).run + +diff -uNr 05_drivers_gpio_uart/update.sh 06_uart_chainloader/update.sh +--- 05_drivers_gpio_uart/update.sh ++++ 06_uart_chainloader/update.sh +@@ -0,0 +1,8 @@ ++#!/usr/bin/env bash ++ ++cd ../05_drivers_gpio_uart ++BSP=rpi4 make ++cp kernel8.img ../06_uart_chainloader/demo_payload_rpi4.img ++make ++cp kernel8.img ../06_uart_chainloader/demo_payload_rpi3.img ++rm kernel8.img + +``` diff --git a/tools/raspi4/chainloader/build.rs b/tools/raspi4/chainloader/build.rs new file mode 100644 index 0000000000..cab00bb377 --- /dev/null +++ b/tools/raspi4/chainloader/build.rs @@ -0,0 +1,20 @@ +use std::{env, fs, process}; + +fn main() { + let ld_script_path = match env::var("LD_SCRIPT_PATH") { + Ok(var) => var, + _ => process::exit(0), + }; + + let files = fs::read_dir(ld_script_path).unwrap(); + files + .filter_map(Result::ok) + .filter(|d| { + if let Some(e) = d.path().extension() { + e == "ld" + } else { + false + } + }) + .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display())); +} diff --git a/tools/raspi4/chainloader/src/_arch/aarch64/cpu.rs b/tools/raspi4/chainloader/src/_arch/aarch64/cpu.rs new file mode 100644 index 0000000000..f1f1e9aff7 --- /dev/null +++ b/tools/raspi4/chainloader/src/_arch/aarch64/cpu.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Architectural processor code. +//! +//! # Orientation +//! +//! Since arch modules are imported into generic modules using the path attribute, the path of this +//! file is: +//! +//! crate::cpu::arch_cpu + +use aarch64_cpu::asm; + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +pub use asm::nop; + +/// Spin for `n` cycles. +#[cfg(feature = "bsp_rpi3")] +#[inline(always)] +pub fn spin_for_cycles(n: usize) { + for _ in 0..n { + asm::nop(); + } +} + +/// Pause execution on the core. +#[inline(always)] +pub fn wait_forever() -> ! { + loop { + asm::wfe() + } +} diff --git a/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.rs b/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.rs new file mode 100644 index 0000000000..2a6c46492f --- /dev/null +++ b/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2021-2023 Andre Richter + +//! Architectural boot code. +//! +//! # Orientation +//! +//! Since arch modules are imported into generic modules using the path attribute, the path of this +//! file is: +//! +//! crate::cpu::boot::arch_boot + +use core::arch::global_asm; + +// Assembly counterpart to this file. +global_asm!( + include_str!("boot.s"), + CONST_CORE_ID_MASK = const 0b11 +); + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +/// The Rust entry of the `kernel` binary. +/// +/// The function is called from the assembly `_start` function. +#[no_mangle] +pub unsafe fn _start_rust() -> ! { + crate::kernel_init() +} diff --git a/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.s b/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.s new file mode 100644 index 0000000000..3ed0d4941d --- /dev/null +++ b/tools/raspi4/chainloader/src/_arch/aarch64/cpu/boot.s @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2021-2022 Andre Richter + +//-------------------------------------------------------------------------------------------------- +// Definitions +//-------------------------------------------------------------------------------------------------- + +// Load the address of a symbol into a register, PC-relative. +// +// The symbol must lie within +/- 4 GiB of the Program Counter. +// +// # Resources +// +// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html +.macro ADR_REL register, symbol + adrp \register, \symbol + add \register, \register, #:lo12:\symbol +.endm + +// Load the address of a symbol into a register, absolute. +// +// # Resources +// +// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html +.macro ADR_ABS register, symbol + movz \register, #:abs_g2:\symbol + movk \register, #:abs_g1_nc:\symbol + movk \register, #:abs_g0_nc:\symbol +.endm + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- +.section .text._start + +//------------------------------------------------------------------------------ +// fn _start() +//------------------------------------------------------------------------------ +_start: + // Only proceed on the boot core. Park it otherwise. + mrs x0, MPIDR_EL1 + and x0, x0, {CONST_CORE_ID_MASK} + ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs + cmp x0, x1 + b.ne .L_parking_loop + + // If execution reaches here, it is the boot core. + + // Initialize DRAM. + ADR_ABS x0, __bss_start + ADR_ABS x1, __bss_end_exclusive + +.L_bss_init_loop: + cmp x0, x1 + b.eq .L_relocate_binary + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + + // Next, relocate the binary. +.L_relocate_binary: + ADR_REL x0, __binary_nonzero_start // The address the binary got loaded to. + ADR_ABS x1, __binary_nonzero_start // The address the binary was linked to. + ADR_ABS x2, __binary_nonzero_end_exclusive + +.L_copy_loop: + ldr x3, [x0], #8 + str x3, [x1], #8 + cmp x1, x2 + b.lo .L_copy_loop + + // Prepare the jump to Rust code. + // Set the stack pointer. + ADR_ABS x0, __boot_core_stack_end_exclusive + mov sp, x0 + + // Jump to the relocated Rust code. + ADR_ABS x1, _start_rust + br x1 + + // Infinitely wait for events (aka "park the core"). +.L_parking_loop: + wfe + b .L_parking_loop + +.size _start, . - _start +.type _start, function +.global _start diff --git a/tools/raspi4/chainloader/src/bsp.rs b/tools/raspi4/chainloader/src/bsp.rs new file mode 100644 index 0000000000..246973bc04 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp.rs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Conditional reexporting of Board Support Packages. + +mod device_driver; + +#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] +mod raspberrypi; + +#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] +pub use raspberrypi::*; diff --git a/tools/raspi4/chainloader/src/bsp/device_driver.rs b/tools/raspi4/chainloader/src/bsp/device_driver.rs new file mode 100644 index 0000000000..64049a4cfa --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/device_driver.rs @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Device driver. + +#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] +mod bcm; +mod common; + +#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] +pub use bcm::*; diff --git a/tools/raspi4/chainloader/src/bsp/device_driver/bcm.rs b/tools/raspi4/chainloader/src/bsp/device_driver/bcm.rs new file mode 100644 index 0000000000..1c343d1d74 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/device_driver/bcm.rs @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! BCM driver top level. + +mod bcm2xxx_gpio; +mod bcm2xxx_pl011_uart; + +pub use bcm2xxx_gpio::*; +pub use bcm2xxx_pl011_uart::*; diff --git a/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs new file mode 100644 index 0000000000..920b4c00cd --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! GPIO Driver. + +use crate::{ + bsp::device_driver::common::MMIODerefWrapper, driver, synchronization, + synchronization::NullLock, +}; +use tock_registers::{ + interfaces::{ReadWriteable, Writeable}, + register_bitfields, register_structs, + registers::ReadWrite, +}; + +//-------------------------------------------------------------------------------------------------- +// Private Definitions +//-------------------------------------------------------------------------------------------------- + +// GPIO registers. +// +// Descriptions taken from +// - https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf +// - https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf +register_bitfields! { + u32, + + /// GPIO Function Select 1 + GPFSEL1 [ + /// Pin 15 + FSEL15 OFFSET(15) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, + AltFunc0 = 0b100 // PL011 UART RX + + ], + + /// Pin 14 + FSEL14 OFFSET(12) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, + AltFunc0 = 0b100 // PL011 UART TX + ] + ], + + /// GPIO Pull-up/down Register + /// + /// BCM2837 only. + GPPUD [ + /// Controls the actuation of the internal pull-up/down control line to ALL the GPIO pins. + PUD OFFSET(0) NUMBITS(2) [ + Off = 0b00, + PullDown = 0b01, + PullUp = 0b10 + ] + ], + + /// GPIO Pull-up/down Clock Register 0 + /// + /// BCM2837 only. + GPPUDCLK0 [ + /// Pin 15 + PUDCLK15 OFFSET(15) NUMBITS(1) [ + NoEffect = 0, + AssertClock = 1 + ], + + /// Pin 14 + PUDCLK14 OFFSET(14) NUMBITS(1) [ + NoEffect = 0, + AssertClock = 1 + ] + ], + + /// GPIO Pull-up / Pull-down Register 0 + /// + /// BCM2711 only. + GPIO_PUP_PDN_CNTRL_REG0 [ + /// Pin 15 + GPIO_PUP_PDN_CNTRL15 OFFSET(30) NUMBITS(2) [ + NoResistor = 0b00, + PullUp = 0b01 + ], + + /// Pin 14 + GPIO_PUP_PDN_CNTRL14 OFFSET(28) NUMBITS(2) [ + NoResistor = 0b00, + PullUp = 0b01 + ] + ] +} + +register_structs! { + #[allow(non_snake_case)] + RegisterBlock { + (0x00 => _reserved1), + (0x04 => GPFSEL1: ReadWrite), + (0x08 => _reserved2), + (0x94 => GPPUD: ReadWrite), + (0x98 => GPPUDCLK0: ReadWrite), + (0x9C => _reserved3), + (0xE4 => GPIO_PUP_PDN_CNTRL_REG0: ReadWrite), + (0xE8 => @END), + } +} + +/// Abstraction for the associated MMIO registers. +type Registers = MMIODerefWrapper; + +struct GPIOInner { + registers: Registers, +} + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Representation of the GPIO HW. +pub struct GPIO { + inner: NullLock, +} + +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl GPIOInner { + /// Create an instance. + /// + /// # Safety + /// + /// - The user must ensure to provide a correct MMIO start address. + pub const unsafe fn new(mmio_start_addr: usize) -> Self { + Self { + registers: Registers::new(mmio_start_addr), + } + } + + /// Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + fn disable_pud_14_15_bcm2837(&mut self) { + use crate::cpu; + + // Make an educated guess for a good delay value (Sequence described in the BCM2837 + // peripherals PDF). + // + // - According to Wikipedia, the fastest RPi4 clocks around 1.5 GHz. + // - The Linux 2837 GPIO driver waits 1 µs between the steps. + // + // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs + // would the CPU be clocked at 2 GHz. + const DELAY: usize = 2000; + + self.registers.GPPUD.write(GPPUD::PUD::Off); + cpu::spin_for_cycles(DELAY); + + self.registers + .GPPUDCLK0 + .write(GPPUDCLK0::PUDCLK15::AssertClock + GPPUDCLK0::PUDCLK14::AssertClock); + cpu::spin_for_cycles(DELAY); + + self.registers.GPPUD.write(GPPUD::PUD::Off); + self.registers.GPPUDCLK0.set(0); + } + + /// Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi4")] + fn disable_pud_14_15_bcm2711(&mut self) { + self.registers.GPIO_PUP_PDN_CNTRL_REG0.write( + GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL15::PullUp + + GPIO_PUP_PDN_CNTRL_REG0::GPIO_PUP_PDN_CNTRL14::PullUp, + ); + } + + /// Map PL011 UART as standard output. + /// + /// TX to pin 14 + /// RX to pin 15 + pub fn map_pl011_uart(&mut self) { + // Select the UART on pins 14 and 15. + self.registers + .GPFSEL1 + .modify(GPFSEL1::FSEL15::AltFunc0 + GPFSEL1::FSEL14::AltFunc0); + + // Disable pull-up/down on pins 14 and 15. + #[cfg(feature = "bsp_rpi3")] + self.disable_pud_14_15_bcm2837(); + + #[cfg(feature = "bsp_rpi4")] + self.disable_pud_14_15_bcm2711(); + } +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +impl GPIO { + pub const COMPATIBLE: &'static str = "BCM GPIO"; + + /// Create an instance. + /// + /// # Safety + /// + /// - The user must ensure to provide a correct MMIO start address. + pub const unsafe fn new(mmio_start_addr: usize) -> Self { + Self { + inner: NullLock::new(GPIOInner::new(mmio_start_addr)), + } + } + + /// Concurrency safe version of `GPIOInner.map_pl011_uart()` + pub fn map_pl011_uart(&self) { + self.inner.lock(|inner| inner.map_pl011_uart()) + } +} + +//------------------------------------------------------------------------------ +// OS Interface Code +//------------------------------------------------------------------------------ +use synchronization::interface::Mutex; + +impl driver::interface::DeviceDriver for GPIO { + fn compatible(&self) -> &'static str { + Self::COMPATIBLE + } +} diff --git a/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs new file mode 100644 index 0000000000..50a069ea1b --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! PL011 UART driver. +//! +//! # Resources +//! +//! - +//! - + +use crate::{ + bsp::device_driver::common::MMIODerefWrapper, console, cpu, driver, synchronization, + synchronization::NullLock, +}; +use core::fmt; +use tock_registers::{ + interfaces::{Readable, Writeable}, + register_bitfields, register_structs, + registers::{ReadOnly, ReadWrite, WriteOnly}, +}; + +//-------------------------------------------------------------------------------------------------- +// Private Definitions +//-------------------------------------------------------------------------------------------------- + +// PL011 UART registers. +// +// Descriptions taken from "PrimeCell UART (PL011) Technical Reference Manual" r1p5. +register_bitfields! { + u32, + + /// Flag Register. + FR [ + /// Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the + /// Line Control Register, LCR_H. + /// + /// - If the FIFO is disabled, this bit is set when the transmit holding register is empty. + /// - If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. + /// - This bit does not indicate if there is data in the transmit shift register. + TXFE OFFSET(7) NUMBITS(1) [], + + /// Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the + /// LCR_H Register. + /// + /// - If the FIFO is disabled, this bit is set when the transmit holding register is full. + /// - If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + TXFF OFFSET(5) NUMBITS(1) [], + + /// Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the + /// LCR_H Register. + /// + /// - If the FIFO is disabled, this bit is set when the receive holding register is empty. + /// - If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + RXFE OFFSET(4) NUMBITS(1) [], + + /// UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains + /// set until the complete byte, including all the stop bits, has been sent from the shift + /// register. + /// + /// This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether + /// the UART is enabled or not. + BUSY OFFSET(3) NUMBITS(1) [] + ], + + /// Integer Baud Rate Divisor. + IBRD [ + /// The integer baud rate divisor. + BAUD_DIVINT OFFSET(0) NUMBITS(16) [] + ], + + /// Fractional Baud Rate Divisor. + FBRD [ + /// The fractional baud rate divisor. + BAUD_DIVFRAC OFFSET(0) NUMBITS(6) [] + ], + + /// Line Control Register. + LCR_H [ + /// Word length. These bits indicate the number of data bits transmitted or received in a + /// frame. + #[allow(clippy::enum_variant_names)] + WLEN OFFSET(5) NUMBITS(2) [ + FiveBit = 0b00, + SixBit = 0b01, + SevenBit = 0b10, + EightBit = 0b11 + ], + + /// Enable FIFOs: + /// + /// 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding + /// registers. + /// + /// 1 = Transmit and receive FIFO buffers are enabled (FIFO mode). + FEN OFFSET(4) NUMBITS(1) [ + FifosDisabled = 0, + FifosEnabled = 1 + ] + ], + + /// Control Register. + CR [ + /// Receive enable. If this bit is set to 1, the receive section of the UART is enabled. + /// Data reception occurs for either UART signals or SIR signals depending on the setting of + /// the SIREN bit. When the UART is disabled in the middle of reception, it completes the + /// current character before stopping. + RXE OFFSET(9) NUMBITS(1) [ + Disabled = 0, + Enabled = 1 + ], + + /// Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. + /// Data transmission occurs for either UART signals, or SIR signals depending on the + /// setting of the SIREN bit. When the UART is disabled in the middle of transmission, it + /// completes the current character before stopping. + TXE OFFSET(8) NUMBITS(1) [ + Disabled = 0, + Enabled = 1 + ], + + /// UART enable: + /// + /// 0 = UART is disabled. If the UART is disabled in the middle of transmission or + /// reception, it completes the current character before stopping. + /// + /// 1 = The UART is enabled. Data transmission and reception occurs for either UART signals + /// or SIR signals depending on the setting of the SIREN bit + UARTEN OFFSET(0) NUMBITS(1) [ + /// If the UART is disabled in the middle of transmission or reception, it completes the + /// current character before stopping. + Disabled = 0, + Enabled = 1 + ] + ], + + /// Interrupt Clear Register. + ICR [ + /// Meta field for all pending interrupts. + ALL OFFSET(0) NUMBITS(11) [] + ] +} + +register_structs! { + #[allow(non_snake_case)] + pub RegisterBlock { + (0x00 => DR: ReadWrite), + (0x04 => _reserved1), + (0x18 => FR: ReadOnly), + (0x1c => _reserved2), + (0x24 => IBRD: WriteOnly), + (0x28 => FBRD: WriteOnly), + (0x2c => LCR_H: WriteOnly), + (0x30 => CR: WriteOnly), + (0x34 => _reserved3), + (0x44 => ICR: WriteOnly), + (0x48 => @END), + } +} + +/// Abstraction for the associated MMIO registers. +type Registers = MMIODerefWrapper; + +#[derive(PartialEq)] +enum BlockingMode { + Blocking, + NonBlocking, +} + +struct PL011UartInner { + registers: Registers, + chars_written: usize, + chars_read: usize, +} + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Representation of the UART. +pub struct PL011Uart { + inner: NullLock, +} + +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl PL011UartInner { + /// Create an instance. + /// + /// # Safety + /// + /// - The user must ensure to provide a correct MMIO start address. + pub const unsafe fn new(mmio_start_addr: usize) -> Self { + Self { + registers: Registers::new(mmio_start_addr), + chars_written: 0, + chars_read: 0, + } + } + + /// Set up baud rate and characteristics. + /// + /// This results in 8N1 and 921_600 baud. + /// + /// The calculation for the BRD is (we set the clock to 48 MHz in config.txt): + /// `(48_000_000 / 16) / 921_600 = 3.2552083`. + /// + /// This means the integer part is `3` and goes into the `IBRD`. + /// The fractional part is `0.2552083`. + /// + /// `FBRD` calculation according to the PL011 Technical Reference Manual: + /// `INTEGER((0.2552083 * 64) + 0.5) = 16`. + /// + /// Therefore, the generated baud rate divider is: `3 + 16/64 = 3.25`. Which results in a + /// genrated baud rate of `48_000_000 / (16 * 3.25) = 923_077`. + /// + /// Error = `((923_077 - 921_600) / 921_600) * 100 = 0.16%`. + pub fn init(&mut self) { + // Execution can arrive here while there are still characters queued in the TX FIFO and + // actively being sent out by the UART hardware. If the UART is turned off in this case, + // those queued characters would be lost. + // + // For example, this can happen during runtime on a call to panic!(), because panic!() + // initializes its own UART instance and calls init(). + // + // Hence, flush first to ensure all pending characters are transmitted. + self.flush(); + + // Turn the UART off temporarily. + self.registers.CR.set(0); + + // Clear all pending interrupts. + self.registers.ICR.write(ICR::ALL::CLEAR); + + // From the PL011 Technical Reference Manual: + // + // The LCR_H, IBRD, and FBRD registers form the single 30-bit wide LCR Register that is + // updated on a single write strobe generated by a LCR_H write. So, to internally update the + // contents of IBRD or FBRD, a LCR_H write must always be performed at the end. + // + // Set the baud rate, 8N1 and FIFO enabled. + self.registers.IBRD.write(IBRD::BAUD_DIVINT.val(3)); + self.registers.FBRD.write(FBRD::BAUD_DIVFRAC.val(16)); + self.registers + .LCR_H + .write(LCR_H::WLEN::EightBit + LCR_H::FEN::FifosEnabled); + + // Turn the UART on. + self.registers + .CR + .write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled); + } + + /// Send a character. + fn write_char(&mut self, c: char) { + // Spin while TX FIFO full is set, waiting for an empty slot. + while self.registers.FR.matches_all(FR::TXFF::SET) { + cpu::nop(); + } + + // Write the character to the buffer. + self.registers.DR.set(c as u32); + + self.chars_written += 1; + } + + /// Block execution until the last buffered character has been physically put on the TX wire. + fn flush(&self) { + // Spin until the busy bit is cleared. + while self.registers.FR.matches_all(FR::BUSY::SET) { + cpu::nop(); + } + } + + /// Retrieve a character. + fn read_char(&mut self, blocking_mode: BlockingMode) -> Option { + // If RX FIFO is empty, + if self.registers.FR.matches_all(FR::RXFE::SET) { + // immediately return in non-blocking mode. + if blocking_mode == BlockingMode::NonBlocking { + return None; + } + + // Otherwise, wait until a char was received. + while self.registers.FR.matches_all(FR::RXFE::SET) { + cpu::nop(); + } + } + + // Read one character. + let ret = self.registers.DR.get() as u8 as char; + + // Update statistics. + self.chars_read += 1; + + Some(ret) + } +} + +/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are +/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, +/// we get `write_fmt()` automatically. +/// +/// The function takes an `&mut self`, so it must be implemented for the inner struct. +/// +/// See [`src/print.rs`]. +/// +/// [`src/print.rs`]: ../../print/index.html +impl fmt::Write for PL011UartInner { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.chars() { + self.write_char(c); + } + + Ok(()) + } +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +impl PL011Uart { + pub const COMPATIBLE: &'static str = "BCM PL011 UART"; + + /// Create an instance. + /// + /// # Safety + /// + /// - The user must ensure to provide a correct MMIO start address. + pub const unsafe fn new(mmio_start_addr: usize) -> Self { + Self { + inner: NullLock::new(PL011UartInner::new(mmio_start_addr)), + } + } +} + +//------------------------------------------------------------------------------ +// OS Interface Code +//------------------------------------------------------------------------------ +use synchronization::interface::Mutex; + +impl driver::interface::DeviceDriver for PL011Uart { + fn compatible(&self) -> &'static str { + Self::COMPATIBLE + } + + unsafe fn init(&self) -> Result<(), &'static str> { + self.inner.lock(|inner| inner.init()); + + Ok(()) + } +} + +impl console::interface::Write for PL011Uart { + /// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to + /// serialize access. + fn write_char(&self, c: char) { + self.inner.lock(|inner| inner.write_char(c)); + } + + fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { + // Fully qualified syntax for the call to `core::fmt::Write::write_fmt()` to increase + // readability. + self.inner.lock(|inner| fmt::Write::write_fmt(inner, args)) + } + + fn flush(&self) { + // Spin until TX FIFO empty is set. + self.inner.lock(|inner| inner.flush()); + } +} + +impl console::interface::Read for PL011Uart { + fn read_char(&self) -> char { + self.inner + .lock(|inner| inner.read_char(BlockingMode::Blocking).unwrap()) + } + + fn clear_rx(&self) { + // Read from the RX FIFO until it is indicating empty. + while self + .inner + .lock(|inner| inner.read_char(BlockingMode::NonBlocking)) + .is_some() + {} + } +} + +impl console::interface::Statistics for PL011Uart { + fn chars_written(&self) -> usize { + self.inner.lock(|inner| inner.chars_written) + } + + fn chars_read(&self) -> usize { + self.inner.lock(|inner| inner.chars_read) + } +} + +impl console::interface::All for PL011Uart {} diff --git a/tools/raspi4/chainloader/src/bsp/device_driver/common.rs b/tools/raspi4/chainloader/src/bsp/device_driver/common.rs new file mode 100644 index 0000000000..dfe7d8ef31 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/device_driver/common.rs @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2023 Andre Richter + +//! Common device driver code. + +use core::{marker::PhantomData, ops}; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +pub struct MMIODerefWrapper { + start_addr: usize, + phantom: PhantomData T>, +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +impl MMIODerefWrapper { + /// Create an instance. + pub const unsafe fn new(start_addr: usize) -> Self { + Self { + start_addr, + phantom: PhantomData, + } + } +} + +impl ops::Deref for MMIODerefWrapper { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { &*(self.start_addr as *const _) } + } +} diff --git a/tools/raspi4/chainloader/src/bsp/raspberrypi.rs b/tools/raspi4/chainloader/src/bsp/raspberrypi.rs new file mode 100644 index 0000000000..3ea864dc78 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/raspberrypi.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Top-level BSP file for the Raspberry Pi 3 and 4. + +pub mod cpu; +pub mod driver; +pub mod memory; + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +/// Board identification. +pub fn board_name() -> &'static str { + #[cfg(feature = "bsp_rpi3")] + { + "Raspberry Pi 3" + } + + #[cfg(feature = "bsp_rpi4")] + { + "Raspberry Pi 4" + } +} diff --git a/tools/raspi4/chainloader/src/bsp/raspberrypi/cpu.rs b/tools/raspi4/chainloader/src/bsp/raspberrypi/cpu.rs new file mode 100644 index 0000000000..65cf5abbe0 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/raspberrypi/cpu.rs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! BSP Processor code. + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Used by `arch` code to find the early boot core. +#[no_mangle] +#[link_section = ".text._start_arguments"] +pub static BOOT_CORE_ID: u64 = 0; diff --git a/tools/raspi4/chainloader/src/bsp/raspberrypi/driver.rs b/tools/raspi4/chainloader/src/bsp/raspberrypi/driver.rs new file mode 100644 index 0000000000..2a80ee2c53 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/raspberrypi/driver.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! BSP driver support. + +use super::memory::map::mmio; +use crate::{bsp::device_driver, console, driver as generic_driver}; +use core::sync::atomic::{AtomicBool, Ordering}; + +//-------------------------------------------------------------------------------------------------- +// Global instances +//-------------------------------------------------------------------------------------------------- + +static PL011_UART: device_driver::PL011Uart = + unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) }; +static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) }; + +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +/// This must be called only after successful init of the UART driver. +fn post_init_uart() -> Result<(), &'static str> { + console::register_console(&PL011_UART); + + Ok(()) +} + +/// This must be called only after successful init of the GPIO driver. +fn post_init_gpio() -> Result<(), &'static str> { + GPIO.map_pl011_uart(); + Ok(()) +} + +fn driver_uart() -> Result<(), &'static str> { + let uart_descriptor = + generic_driver::DeviceDriverDescriptor::new(&PL011_UART, Some(post_init_uart)); + generic_driver::driver_manager().register_driver(uart_descriptor); + + Ok(()) +} + +fn driver_gpio() -> Result<(), &'static str> { + let gpio_descriptor = generic_driver::DeviceDriverDescriptor::new(&GPIO, Some(post_init_gpio)); + generic_driver::driver_manager().register_driver(gpio_descriptor); + + Ok(()) +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +/// Initialize the driver subsystem. +/// +/// # Safety +/// +/// See child function calls. +pub unsafe fn init() -> Result<(), &'static str> { + static INIT_DONE: AtomicBool = AtomicBool::new(false); + if INIT_DONE.load(Ordering::Relaxed) { + return Err("Init already done"); + } + + driver_uart()?; + driver_gpio()?; + + INIT_DONE.store(true, Ordering::Relaxed); + Ok(()) +} diff --git a/tools/raspi4/chainloader/src/bsp/raspberrypi/kernel.ld b/tools/raspi4/chainloader/src/bsp/raspberrypi/kernel.ld new file mode 100644 index 0000000000..c84b62381d --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/raspberrypi/kernel.ld @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: MIT OR Apache-2.0 + * + * Copyright (c) 2018-2022 Andre Richter + */ + +/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */ +__rpi_phys_binary_load_addr = 0x80000; + + +ENTRY(__rpi_phys_binary_load_addr) + +/* Flags: + * 4 == R + * 5 == RX + * 6 == RW + * + * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses. + * It doesn't mean all of them need actually be loaded. + */ +PHDRS +{ + segment_boot_core_stack PT_LOAD FLAGS(6); + segment_code PT_LOAD FLAGS(5); + segment_data PT_LOAD FLAGS(6); +} + +SECTIONS +{ + /* Set the link address to 32 MiB */ + . = 0x2000000; + + /*********************************************************************************************** + * Boot Core Stack + ***********************************************************************************************/ + .boot_core_stack (NOLOAD) : + { + /* ^ */ + /* | stack */ + . += __rpi_phys_binary_load_addr; /* | growth */ + /* | direction */ + __boot_core_stack_end_exclusive = .; /* | */ + } :segment_boot_core_stack + + /*********************************************************************************************** + * Code + RO Data + Global Offset Table + ***********************************************************************************************/ + __binary_nonzero_start = .; + .text : + { + KEEP(*(.text._start)) + *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */ + *(.text._start_rust) /* The Rust entry point */ + *(.text*) /* Everything else */ + } :segment_code + + .rodata : ALIGN(8) { *(.rodata*) } :segment_code + + /*********************************************************************************************** + * Data + BSS + ***********************************************************************************************/ + .data : { *(.data*) } :segment_data + + /* Fill up to 8 byte, b/c relocating the binary is done in u64 chunks */ + . = ALIGN(8); + __binary_nonzero_end_exclusive = .; + + /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ + .bss (NOLOAD) : ALIGN(16) + { + __bss_start = .; + *(.bss*); + . = ALIGN(16); + __bss_end_exclusive = .; + } :segment_data + + /*********************************************************************************************** + * Misc + ***********************************************************************************************/ + .got : { *(.got*) } + ASSERT(SIZEOF(.got) == 0, "Relocation support not expected") + + /DISCARD/ : { *(.comment*) } +} diff --git a/tools/raspi4/chainloader/src/bsp/raspberrypi/memory.rs b/tools/raspi4/chainloader/src/bsp/raspberrypi/memory.rs new file mode 100644 index 0000000000..ee72b27a04 --- /dev/null +++ b/tools/raspi4/chainloader/src/bsp/raspberrypi/memory.rs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! BSP Memory Management. + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// The board's physical memory map. +#[rustfmt::skip] +pub(super) mod map { + pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000; + + pub const GPIO_OFFSET: usize = 0x0020_0000; + pub const UART_OFFSET: usize = 0x0020_1000; + + /// Physical devices. + #[cfg(feature = "bsp_rpi3")] + pub mod mmio { + use super::*; + + pub const START: usize = 0x3F00_0000; + pub const GPIO_START: usize = START + GPIO_OFFSET; + pub const PL011_UART_START: usize = START + UART_OFFSET; + } + + /// Physical devices. + #[cfg(feature = "bsp_rpi4")] + pub mod mmio { + use super::*; + + pub const START: usize = 0xFE00_0000; + pub const GPIO_START: usize = START + GPIO_OFFSET; + pub const PL011_UART_START: usize = START + UART_OFFSET; + } +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +/// The address on which the Raspberry firmware loads every binary by default. +#[inline(always)] +pub fn board_default_load_addr() -> *const u64 { + map::BOARD_DEFAULT_LOAD_ADDRESS as _ +} diff --git a/tools/raspi4/chainloader/src/console.rs b/tools/raspi4/chainloader/src/console.rs new file mode 100644 index 0000000000..a83f86fe01 --- /dev/null +++ b/tools/raspi4/chainloader/src/console.rs @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! System console. + +mod null_console; + +use crate::synchronization::{self, NullLock}; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Console interfaces. +pub mod interface { + use core::fmt; + + /// Console write functions. + pub trait Write { + /// Write a single character. + fn write_char(&self, c: char); + + /// Write a Rust format string. + fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; + + /// Block until the last buffered character has been physically put on the TX wire. + fn flush(&self); + } + + /// Console read functions. + pub trait Read { + /// Read a single character. + fn read_char(&self) -> char { + ' ' + } + + /// Clear RX buffers, if any. + fn clear_rx(&self); + } + + /// Console statistics. + pub trait Statistics { + /// Return the number of characters written. + fn chars_written(&self) -> usize { + 0 + } + + /// Return the number of characters read. + fn chars_read(&self) -> usize { + 0 + } + } + + /// Trait alias for a full-fledged console. + pub trait All: Write + Read + Statistics {} +} + +//-------------------------------------------------------------------------------------------------- +// Global instances +//-------------------------------------------------------------------------------------------------- + +static CUR_CONSOLE: NullLock<&'static (dyn interface::All + Sync)> = + NullLock::new(&null_console::NULL_CONSOLE); + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- +use synchronization::interface::Mutex; + +/// Register a new console. +pub fn register_console(new_console: &'static (dyn interface::All + Sync)) { + CUR_CONSOLE.lock(|con| *con = new_console); +} + +/// Return a reference to the currently registered console. +/// +/// This is the global console used by all printing macros. +pub fn console() -> &'static dyn interface::All { + CUR_CONSOLE.lock(|con| *con) +} diff --git a/tools/raspi4/chainloader/src/console/null_console.rs b/tools/raspi4/chainloader/src/console/null_console.rs new file mode 100644 index 0000000000..e92a022b6c --- /dev/null +++ b/tools/raspi4/chainloader/src/console/null_console.rs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2022-2023 Andre Richter + +//! Null console. + +use super::interface; +use core::fmt; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +pub struct NullConsole; + +//-------------------------------------------------------------------------------------------------- +// Global instances +//-------------------------------------------------------------------------------------------------- + +pub static NULL_CONSOLE: NullConsole = NullConsole {}; + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +impl interface::Write for NullConsole { + fn write_char(&self, _c: char) {} + + fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result { + fmt::Result::Ok(()) + } + + fn flush(&self) {} +} + +impl interface::Read for NullConsole { + fn clear_rx(&self) {} +} + +impl interface::Statistics for NullConsole {} +impl interface::All for NullConsole {} diff --git a/tools/raspi4/chainloader/src/cpu.rs b/tools/raspi4/chainloader/src/cpu.rs new file mode 100644 index 0000000000..eacb8924a4 --- /dev/null +++ b/tools/raspi4/chainloader/src/cpu.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2023 Andre Richter + +//! Processor code. + +#[cfg(target_arch = "aarch64")] +#[path = "_arch/aarch64/cpu.rs"] +mod arch_cpu; + +mod boot; + +//-------------------------------------------------------------------------------------------------- +// Architectural Public Reexports +//-------------------------------------------------------------------------------------------------- +pub use arch_cpu::{nop, wait_forever}; + +#[cfg(feature = "bsp_rpi3")] +pub use arch_cpu::spin_for_cycles; diff --git a/tools/raspi4/chainloader/src/cpu/boot.rs b/tools/raspi4/chainloader/src/cpu/boot.rs new file mode 100644 index 0000000000..b1e98328ac --- /dev/null +++ b/tools/raspi4/chainloader/src/cpu/boot.rs @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2021-2023 Andre Richter + +//! Boot code. + +#[cfg(target_arch = "aarch64")] +#[path = "../_arch/aarch64/cpu/boot.rs"] +mod arch_boot; diff --git a/tools/raspi4/chainloader/src/driver.rs b/tools/raspi4/chainloader/src/driver.rs new file mode 100644 index 0000000000..53592c66b1 --- /dev/null +++ b/tools/raspi4/chainloader/src/driver.rs @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Driver support. + +use crate::synchronization::{interface::Mutex, NullLock}; + +//-------------------------------------------------------------------------------------------------- +// Private Definitions +//-------------------------------------------------------------------------------------------------- + +const NUM_DRIVERS: usize = 5; + +struct DriverManagerInner { + next_index: usize, + descriptors: [Option; NUM_DRIVERS], +} + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Driver interfaces. +pub mod interface { + /// Device Driver functions. + pub trait DeviceDriver { + /// Return a compatibility string for identifying the driver. + fn compatible(&self) -> &'static str; + + /// Called by the kernel to bring up the device. + /// + /// # Safety + /// + /// - During init, drivers might do stuff with system-wide impact. + unsafe fn init(&self) -> Result<(), &'static str> { + Ok(()) + } + } +} + +/// Tpye to be used as an optional callback after a driver's init() has run. +pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'static str>; + +/// A descriptor for device drivers. +#[derive(Copy, Clone)] +pub struct DeviceDriverDescriptor { + device_driver: &'static (dyn interface::DeviceDriver + Sync), + post_init_callback: Option, +} + +/// Provides device driver management functions. +pub struct DriverManager { + inner: NullLock, +} + +//-------------------------------------------------------------------------------------------------- +// Global instances +//-------------------------------------------------------------------------------------------------- + +static DRIVER_MANAGER: DriverManager = DriverManager::new(); + +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +impl DriverManagerInner { + /// Create an instance. + pub const fn new() -> Self { + Self { + next_index: 0, + descriptors: [None; NUM_DRIVERS], + } + } +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +impl DeviceDriverDescriptor { + /// Create an instance. + pub fn new( + device_driver: &'static (dyn interface::DeviceDriver + Sync), + post_init_callback: Option, + ) -> Self { + Self { + device_driver, + post_init_callback, + } + } +} + +/// Return a reference to the global DriverManager. +pub fn driver_manager() -> &'static DriverManager { + &DRIVER_MANAGER +} + +impl DriverManager { + /// Create an instance. + pub const fn new() -> Self { + Self { + inner: NullLock::new(DriverManagerInner::new()), + } + } + + /// Register a device driver with the kernel. + pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) { + self.inner.lock(|inner| { + inner.descriptors[inner.next_index] = Some(descriptor); + inner.next_index += 1; + }) + } + + /// Helper for iterating over registered drivers. + fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDescriptor)) { + self.inner.lock(|inner| { + inner + .descriptors + .iter() + .filter_map(|x| x.as_ref()) + .for_each(f) + }) + } + + /// Fully initialize all drivers. + /// + /// # Safety + /// + /// - During init, drivers might do stuff with system-wide impact. + pub unsafe fn init_drivers(&self) { + self.for_each_descriptor(|descriptor| { + // 1. Initialize driver. + if let Err(x) = descriptor.device_driver.init() { + panic!( + "Error initializing driver: {}: {}", + descriptor.device_driver.compatible(), + x + ); + } + + // 2. Call corresponding post init callback. + if let Some(callback) = &descriptor.post_init_callback { + if let Err(x) = callback() { + panic!( + "Error during driver post-init callback: {}: {}", + descriptor.device_driver.compatible(), + x + ); + } + } + }); + } +} diff --git a/tools/raspi4/chainloader/src/main.rs b/tools/raspi4/chainloader/src/main.rs new file mode 100644 index 0000000000..e5e547252f --- /dev/null +++ b/tools/raspi4/chainloader/src/main.rs @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +// Rust embedded logo for `make doc`. +#![doc( + html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png" +)] + +//! The `kernel` binary. +//! +//! # Code organization and architecture +//! +//! The code is divided into different *modules*, each representing a typical **subsystem** of the +//! `kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example, +//! `src/memory.rs` contains code that is concerned with all things memory management. +//! +//! ## Visibility of processor architecture code +//! +//! Some of the `kernel`'s subsystems depend on low-level code that is specific to the target +//! processor architecture. For each supported processor architecture, there exists a subfolder in +//! `src/_arch`, for example, `src/_arch/aarch64`. +//! +//! The architecture folders mirror the subsystem modules laid out in `src`. For example, +//! architectural code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go +//! into `src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in +//! `src/memory/mmu.rs` using the `path attribute`. Usually, the chosen module name is the generic +//! module's name prefixed with `arch_`. +//! +//! For example, this is the top of `src/memory/mmu.rs`: +//! +//! ``` +//! #[cfg(target_arch = "aarch64")] +//! #[path = "../_arch/aarch64/memory/mmu.rs"] +//! mod arch_mmu; +//! ``` +//! +//! Often times, items from the `arch_ module` will be publicly reexported by the parent module. +//! This way, each architecture specific module can provide its implementation of an item, while the +//! caller must not be concerned which architecture has been conditionally compiled. +//! +//! ## BSP code +//! +//! `BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains +//! target board specific definitions and functions. These are things such as the board's memory map +//! or instances of drivers for devices that are featured on the respective board. +//! +//! Just like processor architecture code, the `BSP` code's module structure tries to mirror the +//! `kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is +//! provided must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`. +//! +//! ## Kernel interfaces +//! +//! Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target +//! and board for which the kernel is compiled. For example, the `interrupt controller` hardware of +//! the `Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel` +//! code to play nicely with any of the two without much hassle. +//! +//! In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`, +//! `interface` traits are provided *whenever possible* and *where it makes sense*. They are defined +//! in the respective subsystem module and help to enforce the idiom of *program to an interface, +//! not an implementation*. For example, there will be a common IRQ handling interface which the two +//! different interrupt controller `drivers` of both Raspberrys will implement, and only export the +//! interface to the rest of the `kernel`. +//! +//! ``` +//! +-------------------+ +//! | Interface (Trait) | +//! | | +//! +--+-------------+--+ +//! ^ ^ +//! | | +//! | | +//! +----------+--+ +--+----------+ +//! | kernel code | | bsp code | +//! | | | arch code | +//! +-------------+ +-------------+ +//! ``` +//! +//! # Summary +//! +//! For a logical `kernel` subsystem, corresponding code can be distributed over several physical +//! locations. Here is an example for the **memory** subsystem: +//! +//! - `src/memory.rs` and `src/memory/**/*` +//! - Common code that is agnostic of target processor architecture and `BSP` characteristics. +//! - Example: A function to zero a chunk of memory. +//! - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code. +//! - Example: An `MMU` interface that defines `MMU` function prototypes. +//! - `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*` +//! - `BSP` specific code. +//! - Example: The board's memory map (physical addresses of DRAM and MMIO devices). +//! - `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*` +//! - Processor architecture specific code. +//! - Example: Implementation of the `MMU` interface for the `__arch_name__` processor +//! architecture. +//! +//! From a namespace perspective, **memory** subsystem code lives in: +//! +//! - `crate::memory::*` +//! - `crate::bsp::memory::*` +//! +//! # Boot flow +//! +//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`. +//! - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`. +//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`. + +#![allow(dead_code)] +#![allow(clippy::upper_case_acronyms)] +#![feature(asm_const)] +#![feature(format_args_nl)] +#![feature(panic_info_message)] +#![feature(trait_alias)] +#![no_main] +#![no_std] + +mod bsp; +mod console; +mod cpu; +mod driver; +mod panic_wait; +mod print; +mod synchronization; + +/// Early init code. +/// +/// # Safety +/// +/// - Only a single core must be active and running this function. +/// - The init calls in this function must appear in the correct order. +unsafe fn kernel_init() -> ! { + // Initialize the BSP driver subsystem. + if let Err(x) = bsp::driver::init() { + panic!("Error initializing BSP driver subsystem: {}", x); + } + + // Initialize all device drivers. + driver::driver_manager().init_drivers(); + // println! is usable from here on. + + // Transition from unsafe to safe. + kernel_main() +} + +const MINILOAD_LOGO: &str = r#" + __ __ _ _ _ _ +| \/ (_)_ _ (_) | ___ __ _ __| | +| |\/| | | ' \| | |__/ _ \/ _` / _` | +|_| |_|_|_||_|_|____\___/\__,_\__,_| +"#; + +/// The main function running after the early init. +fn kernel_main() -> ! { + use console::console; + + println!("{}", MINILOAD_LOGO); + println!("{:^37}", bsp::board_name()); + println!(); + println!("[ML] Requesting binary"); + console().flush(); + + // Discard any spurious received characters before starting with the loader protocol. + console().clear_rx(); + + // Notify `Minipush` to send the binary. + for _ in 0..3 { + console().write_char(3 as char); + } + + // Read the binary's size. + let mut size: u32 = u32::from(console().read_char() as u8); + size |= u32::from(console().read_char() as u8) << 8; + size |= u32::from(console().read_char() as u8) << 16; + size |= u32::from(console().read_char() as u8) << 24; + + // Trust it's not too big. + console().write_char('O'); + console().write_char('K'); + + let kernel_addr: *mut u8 = bsp::memory::board_default_load_addr() as *mut u8; + unsafe { + // Read the kernel byte by byte. + for i in 0..size { + core::ptr::write_volatile(kernel_addr.offset(i as isize), console().read_char() as u8) + } + } + + println!("[ML] Loaded! Executing the payload now\n"); + console().flush(); + + #[cfg(feature = "enable_jtag_debug")] + print_jtag_info_and_wait_forever(); + + println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + println!("@ You're using chainboot image . @"); + println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + // Use black magic to create a function pointer. + let kernel: fn() -> ! = unsafe { core::mem::transmute(kernel_addr) }; + + // Jump to loaded kernel! + kernel() +} + +#[cfg(feature = "enable_jtag_debug")] +fn print_jtag_info_and_wait_forever() { + println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + println!("@ You're using a JTAG debug image. @"); + println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + println!("@ 1. open openocd, gdb @"); + println!("@ 2. target extended-remote :3333; @"); + println!("@ 3. set $pc=0x80000 @"); + println!("@ 4. break rust_entry/others @"); + println!("@ 5. break $previous_addr @"); + println!("@ 6. delete 1 @"); + println!("@ 7. load @"); + println!("@ 8. continue @"); + println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + + // wait for gdb connect + cpu::wait_forever() +} diff --git a/tools/raspi4/chainloader/src/panic_wait.rs b/tools/raspi4/chainloader/src/panic_wait.rs new file mode 100644 index 0000000000..5bb0896e42 --- /dev/null +++ b/tools/raspi4/chainloader/src/panic_wait.rs @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! A panic handler that infinitely waits. + +use crate::{cpu, println}; +use core::panic::PanicInfo; + +//-------------------------------------------------------------------------------------------------- +// Private Code +//-------------------------------------------------------------------------------------------------- + +/// Stop immediately if called a second time. +/// +/// # Note +/// +/// Using atomics here relieves us from needing to use `unsafe` for the static variable. +/// +/// On `AArch64`, which is the only implemented architecture at the time of writing this, +/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store +/// instructions. They are therefore safe to use even with MMU + caching deactivated. +/// +/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load +/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store +fn panic_prevent_reenter() { + use core::sync::atomic::{AtomicBool, Ordering}; + + #[cfg(not(target_arch = "aarch64"))] + compile_error!("Add the target_arch to above's check if the following code is safe to use"); + + static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false); + + if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) { + PANIC_IN_PROGRESS.store(true, Ordering::Relaxed); + + return; + } + + cpu::wait_forever() +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + // Protect against panic infinite loops if any of the following code panics itself. + panic_prevent_reenter(); + + let (location, line, column) = match info.location() { + Some(loc) => (loc.file(), loc.line(), loc.column()), + _ => ("???", 0, 0), + }; + + println!( + "Kernel panic!\n\n\ + Panic location:\n File '{}', line {}, column {}\n\n\ + {}", + location, + line, + column, + info.message().unwrap_or(&format_args!("")), + ); + + cpu::wait_forever() +} diff --git a/tools/raspi4/chainloader/src/print.rs b/tools/raspi4/chainloader/src/print.rs new file mode 100644 index 0000000000..6de99572d0 --- /dev/null +++ b/tools/raspi4/chainloader/src/print.rs @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter + +//! Printing. + +use crate::console; +use core::fmt; + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + console::console().write_fmt(args).unwrap(); +} + +/// Prints without a newline. +/// +/// Carbon copy from +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*))); +} + +/// Prints with a newline. +/// +/// Carbon copy from +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ({ + $crate::print::_print(format_args_nl!($($arg)*)); + }) +} diff --git a/tools/raspi4/chainloader/src/synchronization.rs b/tools/raspi4/chainloader/src/synchronization.rs new file mode 100644 index 0000000000..94c83de1c7 --- /dev/null +++ b/tools/raspi4/chainloader/src/synchronization.rs @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2023 Andre Richter + +//! Synchronization primitives. +//! +//! # Resources +//! +//! - +//! - +//! - + +use core::cell::UnsafeCell; + +//-------------------------------------------------------------------------------------------------- +// Public Definitions +//-------------------------------------------------------------------------------------------------- + +/// Synchronization interfaces. +pub mod interface { + + /// Any object implementing this trait guarantees exclusive access to the data wrapped within + /// the Mutex for the duration of the provided closure. + pub trait Mutex { + /// The type of the data that is wrapped by this mutex. + type Data; + + /// Locks the mutex and grants the closure temporary mutable access to the wrapped data. + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R; + } +} + +/// A pseudo-lock for teaching purposes. +/// +/// In contrast to a real Mutex implementation, does not protect against concurrent access from +/// other cores to the contained data. This part is preserved for later lessons. +/// +/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is +/// executing single-threaded, aka only running on a single core with interrupts disabled. +pub struct NullLock +where + T: ?Sized, +{ + data: UnsafeCell, +} + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- + +unsafe impl Send for NullLock where T: ?Sized + Send {} +unsafe impl Sync for NullLock where T: ?Sized + Send {} + +impl NullLock { + /// Create an instance. + pub const fn new(data: T) -> Self { + Self { + data: UnsafeCell::new(data), + } + } +} + +//------------------------------------------------------------------------------ +// OS Interface Code +//------------------------------------------------------------------------------ + +impl interface::Mutex for NullLock { + type Data = T; + + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R { + // In a real lock, there would be code encapsulating this line that ensures that this + // mutable reference will ever only be given out once at a time. + let data = unsafe { &mut *self.data.get() }; + + f(data) + } +} diff --git a/tools/raspi4/chainloader/tests/chainboot_test.rb b/tools/raspi4/chainloader/tests/chainboot_test.rb new file mode 100644 index 0000000000..00de42a367 --- /dev/null +++ b/tools/raspi4/chainloader/tests/chainboot_test.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +# SPDX-License-Identifier: MIT OR Apache-2.0 +# +# Copyright (c) 2020-2023 Andre Richter + +require_relative '../../common/serial/minipush' +require_relative '../../common/tests/boot_test' +require 'pty' + +# Match for the last print that 'demo_payload_rpiX.img' produces. +EXPECTED_PRINT = 'Echoing input now' + +# Wait for request to power the target. +class PowerTargetRequestTest < SubtestBase + MINIPUSH_POWER_TARGET_REQUEST = 'Please power the target now' + + def initialize(qemu_cmd, pty_main) + super() + @qemu_cmd = qemu_cmd + @pty_main = pty_main + end + + def name + 'Waiting for request to power target' + end + + def run(qemu_out, _qemu_in) + expect_or_raise(qemu_out, MINIPUSH_POWER_TARGET_REQUEST) + + # Now is the time to start QEMU with the chainloader binary. QEMU's virtual tty connects to + # the MiniPush instance spawned on pty_main, so that the two processes talk to each other. + Process.spawn(@qemu_cmd, in: @pty_main, out: @pty_main, err: '/dev/null') + end +end + +# Extend BootTest so that it listens on the output of a MiniPush instance, which is itself connected +# to a QEMU instance instead of a real HW. +class ChainbootTest < BootTest + MINIPUSH = '../common/serial/minipush.rb' + + def initialize(qemu_cmd, payload_path) + super(qemu_cmd, EXPECTED_PRINT) + + @test_name = 'Boot test using Minipush' + + @payload_path = payload_path + end + + private + + # override + def setup + pty_main, pty_secondary = PTY.open + mp_out, _mp_in = PTY.spawn("ruby #{MINIPUSH} #{pty_secondary.path} #{@payload_path}") + + # The subtests (from this class and the parents) listen on @qemu_out_wrapped. Hence, point + # it to MiniPush's output. + @qemu_out_wrapped = PTYLoggerWrapper.new(mp_out, "\r\n") + + # Important: Run this subtest before the one in the parent class. + @console_subtests.prepend(PowerTargetRequestTest.new(@qemu_cmd, pty_main)) + end + + # override + def finish + super() + @test_output.map! { |x| x.gsub(/.*\r/, ' ') } + end +end + +## ------------------------------------------------------------------------------------------------- +## Execution starts here +## ------------------------------------------------------------------------------------------------- +payload_path = ARGV.pop +qemu_cmd = ARGV.join(' ') + +ChainbootTest.new(qemu_cmd, payload_path).run diff --git a/tools/raspi4/chainloader/update.sh b/tools/raspi4/chainloader/update.sh new file mode 100755 index 0000000000..5fac48ba07 --- /dev/null +++ b/tools/raspi4/chainloader/update.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +cd ../05_drivers_gpio_uart +BSP=rpi4 make +cp kernel8.img ../06_uart_chainloader/demo_payload_rpi4.img +make +cp kernel8.img ../06_uart_chainloader/demo_payload_rpi3.img +rm kernel8.img diff --git a/tools/raspi4/common/image/chainboot/kernel8.img b/tools/raspi4/common/image/chainboot/kernel8.img new file mode 100755 index 0000000000..6bbc69d352 Binary files /dev/null and b/tools/raspi4/common/image/chainboot/kernel8.img differ diff --git a/tools/raspi4/common/image/jtag/kernel8.img b/tools/raspi4/common/image/jtag/kernel8.img new file mode 100755 index 0000000000..5321b8e08f Binary files /dev/null and b/tools/raspi4/common/image/jtag/kernel8.img differ diff --git a/ulib/axstd/src/lib.rs b/ulib/axstd/src/lib.rs index ced516cd75..d256cd527f 100644 --- a/ulib/axstd/src/lib.rs +++ b/ulib/axstd/src/lib.rs @@ -49,7 +49,6 @@ #![cfg_attr(all(not(test), not(doc)), no_std)] #![feature(doc_cfg)] #![feature(doc_auto_cfg)] -#![feature(ip_in_core)] #[cfg(feature = "alloc")] extern crate alloc;