x86: initializes the LPC
[akaros.git] / kern / arch / x86 / pci.h
index b39c588..beb8b05 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <ros/common.h>
 #include <sys/queue.h>
+#include <atomic.h>
 
 #define pci_debug(...)  printk(__VA_ARGS__)  
 
@@ -316,10 +317,10 @@ struct pci_bar {
        uint32_t                                        mmio_sz;
 };
 
-/* Struct for some meager contents of a PCI device */
 struct pci_device {
        STAILQ_ENTRY(pci_device)        all_dev;        /* list of all devices */
        SLIST_ENTRY(pci_device)         irq_dev;        /* list of all devs off an irq */
+       spinlock_t                                      lock;
        bool                                            in_use;         /* prevent double discovery */
        uint8_t                                         bus;
        uint8_t                                         dev;
@@ -332,6 +333,7 @@ struct pci_device {
        uint8_t                                         class;
        uint8_t                                         subclass;
        uint8_t                                         progif;
+       bool                                            msi_ready;
        uint32_t                                        msi_msg_addr_hi;
        uint32_t                                        msi_msg_addr_lo;
        uint32_t                                        msi_msg_data;
@@ -360,9 +362,23 @@ struct msix_irq_vector {
 
 /* List of all discovered devices */
 STAILQ_HEAD(pcidev_stailq, pci_device);
-SLIST_HEAD(pcidev_slist, pci_device);
 extern struct pcidev_stailq pci_devices;
 
+/* Sync rules for PCI: once a device is added to the list, it is never removed,
+ * and its read-only fields can be accessed at any time.  There is no need for
+ * refcnts or things like that.
+ *
+ * The device list is built early on when we're single threaded, so I'm not
+ * bothering with locks for that yet.  Append-only, singly-linked-list reads
+ * don't need a lock either.
+ *
+ * Other per-device accesses (like read-modify-writes to config space or MSI
+ * fields) require the device's lock.  If we ever want to unplug, we'll probably
+ * work out an RCU-like scheme for the pci_devices list.
+ *
+ * Note this is in addition to the config space global locking done by every
+ * pci_read or write call. */
+
 void pci_init(void);
 void pcidev_print_info(struct pci_device *pcidev, int verbosity);
 uint32_t pci_config_addr(uint8_t bus, uint8_t dev, uint8_t func, uint32_t reg);
@@ -385,34 +401,21 @@ void pcidev_write16(struct pci_device *pcidev, uint32_t offset, uint16_t value);
 uint8_t pcidev_read8(struct pci_device *pcidev, uint32_t offset);
 void pcidev_write8(struct pci_device *pcidev, uint32_t offset, uint8_t value);
 
-/* BAR helpers, some more helpful than others. */
-uint32_t pci_membar_get_sz(struct pci_device *pcidev, int bar);
-uint32_t pci_getbar(struct pci_device *pcidev, unsigned int bar);
-bool pci_is_iobar(uint32_t bar);
-bool pci_is_membar32(uint32_t bar);
-bool pci_is_membar64(uint32_t bar);
-uint32_t pci_getmembar32(uint32_t bar);
-uint32_t pci_getiobar32(uint32_t bar);
-uintptr_t pci_get_membar(struct pci_device *pcidev, int bir);
-
 /* Other common PCI functions */
 void pci_set_bus_master(struct pci_device *pcidev);
 void pci_clr_bus_master(struct pci_device *pcidev);
 struct pci_device *pci_match_tbdf(int tbdf);
+uintptr_t pci_get_membar(struct pci_device *pcidev, int bir);
 
-struct irq_handler; /* include loops */
 /* MSI functions, msi.c */
 int pci_msi_enable(struct pci_device *p, uint64_t vec);
-int pci_msix_enable(struct irq_handler *irq_h, struct pci_device *p,
-                    uint64_t vec);
-
-/* MSI irq handler functions, msi.c */
-void msi_mask_irq(struct irq_handler *irq_h, int apic_vector);
-void msi_unmask_irq(struct irq_handler *irq_h, int apic_vector);
-int msi_route_irq(struct irq_handler *irq_h, int apic_vector, int dest);
-void msix_mask_irq(struct irq_handler *irq_h, int apic_vector);
-void msix_unmask_irq(struct irq_handler *irq_h, int apic_vector);
-int msix_route_irq(struct irq_handler *irq_h, int apic_vector, int dest);
+struct msix_irq_vector *pci_msix_enable(struct pci_device *p, uint64_t vec);
+void pci_msi_mask(struct pci_device *p);
+void pci_msi_unmask(struct pci_device *p);
+void pci_msi_route(struct pci_device *p, int dest);
+void pci_msix_mask_vector(struct msix_irq_vector *linkage);
+void pci_msix_unmask_vector(struct msix_irq_vector *linkage);
+void pci_msix_route_vector(struct msix_irq_vector *linkage, int dest);
 
 /* TODO: this is quite the Hacke */
 #define explode_tbdf(tbdf) {pcidev.bus = tbdf >> 16;\