[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH 1/3] PCI – direkter Zugriff zum Konfigurationsraum
From: Max Reitz <max@xxxxxxxxxx>
+ Per RPC zum pci-Treiber ist jetzt direkter Zugriff auf den
PCI-Konfigurationsraum eines PCI-Geräts möglich.
Signed-off-by: Max Reitz <max@xxxxxxxxxx>
---
src/modules/include/pci.h | 27 ++++++++++++
src/modules/pci/pci.c | 3 +
src/modules/pci/pcihw.c | 42 +++++++++++++++++--
src/modules/pci/pcirpc.c | 100 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 168 insertions(+), 4 deletions(-)
create mode 100644 src/modules/pci/pcirpc.c
diff --git a/src/modules/include/pci.h b/src/modules/include/pci.h
index 30c661f..fdab461 100644
--- a/src/modules/include/pci.h
+++ b/src/modules/include/pci.h
@@ -62,4 +62,31 @@ struct pci_resource {
uint32_t length;
} __attribute__ ((packed));
+
+// Direkter Zugriff auf den PCI-Konfigurationsraum eines Geräts
+// Es wird immer ein dword zurückgegeben (das bei Schreibzugriffen keine
+// Bedeutung hat)
+#define RPC_PCI_CONFIG_SPACE_ACCESS "PCICFGS"
+
+// Typen des Zugriffs
+enum pci_csa_type {
+ PCI_CSA_READ32,
+ PCI_CSA_READ16,
+ PCI_CSA_READ8,
+ PCI_CSA_WRITE32,
+ PCI_CSA_WRITE16,
+ PCI_CSA_WRITE8
+};
+
+// RPC-Request
+struct pci_config_space_access {
+ enum pci_csa_type type;
+ // Adresse auf dem PCI-Bus
+ uint16_t bus, device, function;
+ // Offset im Konfigurationsraum
+ uint32_t reg;
+ // Nur notwendig, wenn geschrieben werden soll
+ uint32_t value;
+};
+
#endif
diff --git a/src/modules/pci/pci.c b/src/modules/pci/pci.c
index 617f74b..a7f6599 100644
--- a/src/modules/pci/pci.c
+++ b/src/modules/pci/pci.c
@@ -57,6 +57,7 @@ void create_device_files(void);
bool pre_open_handler(char** path, uint8_t args, pid_t pid,
io_resource_t* pipe_source);
int close_handler(lostio_filehandle_t* handle);
+void init_rpc_interface(void);
int main(int argc, char* argv[])
{
@@ -92,6 +93,8 @@ int main(int argc, char* argv[])
create_device_files();
+ init_rpc_interface();
+
init_service_register("pci");
while(1) {
diff --git a/src/modules/pci/pcihw.c b/src/modules/pci/pcihw.c
index b9007e3..d4e4e91 100644
--- a/src/modules/pci/pcihw.c
+++ b/src/modules/pci/pcihw.c
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2007-2009 The tyndur Project. All rights reserved.
+ * Copyright (c) 2007-2010 The tyndur Project. All rights reserved.
*
* This code is derived from software contributed to the tyndur Project
- * by Kevin Wolf.
+ * by Kevin Wolf and Max Reitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -63,7 +63,7 @@ void pci_request_io_ports()
* zur�eben, wenn reg dword-aligned ist. Ansonsten werden die
* h�twertigen Bits mit Nullen aufgef� */
-static uint32_t pci_config_read(uint32_t bus, uint32_t device, uint32_t func,
+uint32_t pci_config_read(uint32_t bus, uint32_t device, uint32_t func,
uint32_t reg)
{
uint32_t offset = reg % 0x04;
@@ -117,7 +117,7 @@ static inline uint8_t pci_config_read_byte
* @param reg Offset des zu schreibenden Registers
*
*/
-static void pci_config_write_dword
+void pci_config_write_dword
(uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t value)
{
outl(PCI_CONFIG_ADDR,
@@ -131,6 +131,40 @@ static void pci_config_write_dword
}
/**
+ * Schreibt ein word in ein Konfigurationsregister eines PCI-Ger�
+ * @see pci_config_write_dword
+ */
+void pci_config_write_word
+ (uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint16_t value)
+{
+ outl(PCI_CONFIG_ADDR,
+ 0x1 << 31
+ | ((bus & 0xFF) << 16)
+ | ((device & 0x1F) << 11)
+ | ((func & 0x07) << 8)
+ | ((reg & 0xFC)));
+
+ outw(PCI_CONFIG_DATA + (reg & 2), value);
+}
+
+/**
+ * Schreibt ein byte in ein Konfigurationsregister eines PCI-Ger�
+ * @see pci_config_write_dword
+ */
+void pci_config_write_byte
+ (uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint8_t value)
+{
+ outl(PCI_CONFIG_ADDR,
+ 0x1 << 31
+ | ((bus & 0xFF) << 16)
+ | ((device & 0x1F) << 11)
+ | ((func & 0x07) << 8)
+ | ((reg & 0xFC)));
+
+ outb(PCI_CONFIG_DATA + (reg & 3), value);
+}
+
+/**
* Prueft ob ein PCI-Geraet Funktionen unterstuetzt.
*
* @param bus Bus-Nummer des Ger�
diff --git a/src/modules/pci/pcirpc.c b/src/modules/pci/pcirpc.c
new file mode 100644
index 0000000..f753536
--- /dev/null
+++ b/src/modules/pci/pcirpc.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Max Reitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rpc.h>
+#include <syscall.h>
+
+#include "pci.h"
+#include "pcihw.h"
+
+
+void pci_config_write_dword(uint32_t bus, uint32_t device, uint32_t func,
+ uint32_t reg, uint32_t value);
+void pci_config_write_word(uint32_t bus, uint32_t device, uint32_t func,
+ uint32_t reg, uint16_t value);
+void pci_config_write_byte(uint32_t bus, uint32_t device, uint32_t func,
+ uint32_t reg, uint8_t value);
+uint32_t pci_config_read(uint32_t bus, uint32_t device, uint32_t func,
+ uint32_t reg);
+
+
+static void config_space_handler(pid_t src, uint32_t corr_id, size_t length,
+ void* data)
+{
+ struct pci_config_space_access* csa = data;
+
+ if (length < sizeof(*csa)) {
+ rpc_send_dword_response(src, corr_id, 0);
+ return;
+ }
+
+ uint32_t value = csa->value;
+
+ switch (csa->type) {
+ case PCI_CSA_READ32:
+ value = pci_config_read(csa->bus, csa->device, csa->function,
+ csa->reg);
+ rpc_send_dword_response(src, corr_id, value);
+ break;
+ case PCI_CSA_READ16:
+ value = pci_config_read(csa->bus, csa->device, csa->function,
+ csa->reg);
+ rpc_send_dword_response(src, corr_id, value & 0xFFFF);
+ break;
+ case PCI_CSA_READ8:
+ value = pci_config_read(csa->bus, csa->device, csa->function,
+ csa->reg);
+ rpc_send_dword_response(src, corr_id, value & 0xFF);
+ break;
+ case PCI_CSA_WRITE32:
+ pci_config_write_dword(csa->bus, csa->device, csa->function,
+ csa->reg, value);
+ rpc_send_dword_response(src, corr_id, 0);
+ break;
+ case PCI_CSA_WRITE16:
+ pci_config_write_word(csa->bus, csa->device, csa->function,
+ csa->reg, value);
+ rpc_send_dword_response(src, corr_id, 0);
+ break;
+ case PCI_CSA_WRITE8:
+ pci_config_write_byte(csa->bus, csa->device, csa->function,
+ csa->reg, value);
+ rpc_send_dword_response(src, corr_id, 0);
+ break;
+ default:
+ rpc_send_dword_response(src, corr_id, 0);
+ }
+}
+
+void init_rpc_interface(void)
+{
+ register_message_handler(RPC_PCI_CONFIG_SPACE_ACCESS,
+ &config_space_handler);
+}
--
1.6.4.2