[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] pickles: Add new PCI Pickle
From: |
Darshit Shah |
Subject: |
[PATCH] pickles: Add new PCI Pickle |
Date: |
Wed, 18 Sep 2024 00:28:58 +0200 |
This is a WIP pickle for defining the PCI Config Space.
At the moment, we use the definitions in the PCIe Base Specification
Revision 5 (PCIe 5) specification document.
The current commit only adds a mapping for the base config space.
Detailed descriptions of the various capabilities will come later.
---
pickles.org | 2 +
pickles/pci/pci.pk | 197 ++++++++++++++++++++++++++++++++++++++
pickles/pci/pci_common.pk | 32 +++++++
3 files changed, 231 insertions(+)
create mode 100644 pickles/pci/pci.pk
create mode 100644 pickles/pci/pci_common.pk
diff --git a/pickles.org b/pickles.org
index 027ca82..7626f50 100644
--- a/pickles.org
+++ b/pickles.org
@@ -145,6 +145,8 @@ know in mailto:poke-devel@gnu.org.
|-------------+------------------------------+-----------------------------------------------------------------------------|
| openpgp.pk | OpenPGP RFC 4880 (GnuPG etc) |
https://git.ageinghacker.net/git/cgit.cgi/pokology/tree/pickles/openpgp.pk |
|-------------+------------------------------+-----------------------------------------------------------------------------|
+ | pci.pk | PCI Config Space |
https://git.ageinghacker.net/git/cgit.cgi/pokology/tree/pickes/pci/pci.pk |
+
|-------------+------------------------------+-----------------------------------------------------------------------------|
| tzif.pk | Timezone Information Format |
https://git.ageinghacker.net/git/cgit.cgi/pokology/tree/pickles/tzif.pk |
|-------------+------------------------------+-----------------------------------------------------------------------------|
| uimage.pk | U-Boot Image Format |
https://git.ageinghacker.net/git/cgit.cgi/pokology/tree/pickles/uimage.pk |
diff --git a/pickles/pci/pci.pk b/pickles/pci/pci.pk
new file mode 100644
index 0000000..da9aa9e
--- /dev/null
+++ b/pickles/pci/pci.pk
@@ -0,0 +1,197 @@
+/* pci.pk - PCI Config Space (PCI Base Specification v5) */
+
+/* Work in progress */
+
+/* Copyright (C) 2024 Darshit Shah */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* PCI Express Base Specification v5
+ *
+ * https://pcisig.com/pci-express-base-specification-revision-50-version-10
+ * https://en.wikipedia.org/wiki/PCI_configuration_space
+ *
+ * This pickle implements a mapping over the PCI Base Config Space as defined
+ * in revision 5.0 of the specification.
+ */
+
+/* set_endian (ENDIAN_LITTLE); */
+
+load "pci_common.pk";
+
+type PCI_Command =
+ struct uint<16>
+ {
+ rsvdz;
+ rsvdz;
+ rsvdz;
+ rsvdz;
+ rsvdz;
+ uint<1> int_disable;
+ uint<1> fast_b2b_tx_enable == 0T;
+ uint<1> serr_enable;
+ uint<1> idsel_stepping == 0T;
+ uint<1> parity_error_response;
+ uint<1> vga_palette_snoop == 0T;
+ uint<1> mem_write_invalidate == 0T;
+ uint<1> sp_cycle_enable == 0T;
+ uint<1> bus_master_enable;
+ uint<1> mem_enable;
+ uint<1> io_enable;
+ };
+
+type PCI_Status =
+ struct uint<16>
+ {
+ uint<1> parity_error;
+ uint<1> sig_sys_error;
+ uint<1> rcvd_master_abort;
+ uint<1> rcvd_target_abort;
+ uint<1> sig_target_abort;
+ uint<2> devsel_timing == 0;
+ uint<1> master_data_parity_error;
+ uint<1> fast_b2b_tx_cap;
+ rsvdz;
+ uint<1> Mhz66_cap == 0T;
+ uint<1> cap_list;
+ uint<1> int_status;
+ rsvdz;
+ rsvdz;
+ uint<1> imm_readiness;
+ };
+
+type PCI_Hdr_Type =
+ struct uint<8>
+ {
+ uint<7> hdr_layout;
+ uint<1> multi_fn;
+ };
+
+type PCI_BAR =
+ struct
+ {
+ uint<32>;
+ };
+
+assert (#PCI_BAR == 32#b);
+
+type PCI_Type0 =
+ struct
+ {
+ PCI_BAR[6] bars;
+ uint<32> cardbus_cis_ptr == 0x0U;
+ uint<16> subsystem_vendor_id;
+ uint<16> subsystem_id;
+ uint<32> exp_rom_base_addr;
+ offset<uint<8>,B> cap_ptr;
+ uint<56> rsvdz == 0;
+ uint<8> int_line;
+ uint<8> int_pin;
+ uint<8> min_gnt;
+ uint<8> max_lat;
+ };
+
+assert (#PCI_Type0 == 48#B);
+
+type PCI_Type1 =
+ struct
+ {
+ PCI_BAR bar_0;
+ PCI_BAR bar_1;
+ uint<8> primary_bus_nr;
+ uint<8> sec_bus_nr;
+ uint<8> sub_bus_nr;
+ uint<8> sec_lat_timer;
+ uint<8> io_base;
+ uint<8> io_limit;
+ uint<16> sec_status;
+ uint<16> mem_base;
+ uint<16> mem_limit;
+ uint<16> prefetch_mem_base;
+ uint<16> prefetch_mem_limit;
+ uint<32> prefetch_mem_base_upper;
+ uint<32> prefetch_mem_limit_upper;
+ uint<16> io_base_upper;
+ uint<16> io_base_limit;
+ offset<uint<8>,B> cap_ptr;
+ uint<24> rsvdz == 0;
+ uint<32> exp_rom_base;
+ uint<8> int_line;
+ uint<8> int_pin;
+ uint<16> bridge_ctrl;
+ };
+
+assert (#PCI_Type1 == 48#B);
+
+
+type PCI_Config_Space =
+ struct
+ {
+ uint<16> vendor;
+ uint<16> device;
+ PCI_Command command;
+ PCI_Status status;
+ uint<8> revision_id;
+ uint<24> class_code;
+ uint<8> cache_line_size;
+ uint<8> pri_lat_timer == 0;
+ PCI_Hdr_Type header;
+ uint<8> BIST;
+ if (header.hdr_layout == 0T)
+ PCI_Type0 endpt_specific_data;
+ if (header.hdr_layout == 1T)
+ PCI_Type1 bridge_specific_data;
+ // These are technically not a part of Type 0 / Type 1 structures
+ // But I define them in there for ease. Instead, we can use Field Labels
+ // to create virtual fields here that point to the correct data
+ computed offset<uint<8>,B> cap_ptr;
+ computed uint<8> int_line;
+ computed uint<8> int_pin;
+
+ method get_cap_ptr = offset<uint<8>,B>:
+ { return header.hdr_layout == 0 ? endpt_specific_data.cap_ptr :
bridge_specific_data.cap_ptr; }
+
+ method get_int_line = uint<8>:
+ { return header.hdr_layout == 0 ? endpt_specific_data.int_line :
bridge_specific_data.int_line; }
+
+ method get_int_pin = uint<8>:
+ { return header.hdr_layout == 0 ? endpt_specific_data.int_pin :
bridge_specific_data.int_pin; }
+
+ method set_cap_ptr = (offset<uint<8>,B> inp) void:
+ {
+ if (header.hdr_layout == 0)
+ endpt_specific_data.cap_ptr = inp;
+ else
+ bridge_specific_data.cap_ptr = inp;
+ }
+
+ method set_int_line = (uint<8> inp) void:
+ {
+ if (header.hdr_layout == 0)
+ endpt_specific_data.int_line = inp;
+ else
+ bridge_specific_data.int_line = inp;
+ }
+
+ method set_int_pin = (uint<8>) void:
+ {
+ if (header.hdr_layout == 0)
+ endpt_specific_data.int_pin = inp;
+ else
+ bridge_specific_data.int_pin = inp;
+ }
+ };
+
+assert ((PCI_Config_Space {})'size == 0x40#B);
diff --git a/pickles/pci/pci_common.pk b/pickles/pci/pci_common.pk
new file mode 100644
index 0000000..32f2943
--- /dev/null
+++ b/pickles/pci/pci_common.pk
@@ -0,0 +1,32 @@
+/* pci_common.pk - Common Definitions for reuse in PCI pickles */
+
+/* Work in progress */
+
+/* Copyright (C) 2024 Darshit Shah */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+// While the PCI base specification differentiates between RsvdZ and RsvdP, we
+// don't need that in Poke. The only difference between the two is what
happens
+// when you write to the bit, which is not something our representation needs
+// to care about.
+type rsvdz = struct bit {
+ bit rsvdz == 0x0;
+ method _print = void:
+ {
+ print "rsvdz: 0";
+ }
+};
--
2.46.1