Port-amd64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: x86 pcitag_t change proposal/patch



On Wed, Dec 05, 2012 at 06:08:56PM -0800, Matt Thomas wrote:
> 
> On Dec 5, 2012, at 5:42 PM, Jonathan A. Kollasch wrote:
> 
> > 
> > And now for something without C bitfields.
> > <pcitag-diff-2.txt>
> 
> 
> Better.
> 
> FN -> FUNC
> DEVFN -> DEVFUNC
> 
> _tag should have a cast of (pcitag_t) in it otherwise its type will be 
> uintmax_t not uint32_t.
> 

Attached patch incorporates above suggestions.
Index: sys/arch/x86/include/pci_machdep_common.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/pci_machdep_common.h,v
retrieving revision 1.9
diff -u -a -p -r1.9 pci_machdep_common.h
--- sys/arch/x86/include/pci_machdep_common.h   15 Jun 2012 13:58:34 -0000      
1.9
+++ sys/arch/x86/include/pci_machdep_common.h   6 Dec 2012 02:23:49 -0000
@@ -42,31 +42,18 @@
 #endif
 
 /*
- * i386-specific PCI structure and type definitions.
+ * x86-specific PCI structure and type definitions.
  * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
  *
  * Configuration tag; created from a {bus,device,function} triplet by
  * pci_make_tag(), and passed to pci_conf_read() and pci_conf_write().
- * We could instead always pass the {bus,device,function} triplet to
- * the read and write routines, but this would cause extra overhead.
- *
- * Mode 2 is historical and deprecated by the Revision 2.0 specification.
- *
- *
- * Mode 1 tag:
- *      31              24           16 15     11 10  8
- *     +---------------------------------------------------------------+
- *     |1|      0      |      BUS      |   DEV   |FUNC |       0       |
- *     +---------------------------------------------------------------+
- */
-union x86_pci_tag_u {
-       uint32_t mode1;
-       struct {
-               uint16_t port;
-               uint8_t enable;
-               uint8_t forward;
-       } mode2;
-};
+ */
+
+#define X86_PCITAG_FUNC                __BITS(2,0)
+#define X86_PCITAG_DEV         __BITS(7,3)
+#define X86_PCITAG_DEVFUNC     __BITS(7,0)
+#define X86_PCITAG_BUS         __BITS(15,8)
+#define X86_PCITAG_BDF         __BITS(15,0)
 
 extern struct x86_bus_dma_tag pci_bus_dma_tag;
 #ifdef _LP64
@@ -80,7 +67,7 @@ struct pci_chipset_tag;
  * Types provided to machine-independent PCI code
  */
 typedef struct pci_chipset_tag *pci_chipset_tag_t;
-typedef union x86_pci_tag_u pcitag_t;
+typedef uint32_t pcitag_t;
 
 struct pci_chipset_tag {
        pci_chipset_tag_t pc_super;
@@ -90,7 +77,7 @@ struct pci_chipset_tag {
 };
 
 /*
- * i386-specific PCI variables and functions.
+ * x86-specific PCI variables and functions.
  * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
  */
 int            pci_bus_flags(void);
Index: sys/arch/x86/pci/pci_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/pci/pci_machdep.c,v
retrieving revision 1.56
diff -u -a -p -r1.56 pci_machdep.c
--- sys/arch/x86/pci/pci_machdep.c      1 Mar 2012 20:16:27 -0000       1.56
+++ sys/arch/x86/pci/pci_machdep.c      6 Dec 2012 02:25:32 -0000
@@ -149,18 +149,34 @@ static int pci_mode = PCI_CONF_MODE;
 static int pci_mode = -1;
 #endif
 
+typedef uint32_t pci_conf_selector_t;
+
+union pci_conf_selector {
+       pci_conf_selector_t selector;
+       struct {
+               uint32_t address;
+       } mode1;
+       struct {
+               uint16_t port;
+               uint8_t enable;
+               uint8_t forward;
+       } mode2;
+};
+
+CTASSERT(sizeof(union pci_conf_selector) == sizeof(pci_conf_selector_t));
+
 struct pci_conf_lock {
        uint32_t cl_cpuno;      /* 0: unlocked
                                 * 1 + n: locked by CPU n (0 <= n)
                                 */
-       uint32_t cl_sel;        /* the address that's being read. */
+       pci_conf_selector_t cl_sel;     /* the address that's being read. */
 };
 
 static void pci_conf_unlock(struct pci_conf_lock *);
-static uint32_t pci_conf_selector(pcitag_t, int);
+static pci_conf_selector_t pci_conf_selector(pcitag_t, int);
 static unsigned int pci_conf_port(pcitag_t, int);
-static void pci_conf_select(uint32_t);
-static void pci_conf_lock(struct pci_conf_lock *, uint32_t);
+static void pci_conf_select(pci_conf_selector_t);
+static void pci_conf_lock(struct pci_conf_lock *, pci_conf_selector_t);
 static void pci_bridge_hook(pci_chipset_tag_t, pcitag_t, void *);
 struct pci_bridge_hook_arg {
        void (*func)(pci_chipset_tag_t, pcitag_t, void *);
@@ -175,7 +191,9 @@ struct pci_bridge_hook_arg {
 #define        PCI_MODE2_FORWARD_REG   0x0cfa
 
 #define _tag(b, d, f) \
-       {.mode1 = PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8)}
+       ((pcitag_t)(__SHIFTIN((b), X86_PCITAG_BUS) | \
+        __SHIFTIN((d), X86_PCITAG_DEV) | \
+        __SHIFTIN((f), X86_PCITAG_FUNC)))
 #define _qe(bus, dev, fcn, vend, prod) \
        {_tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)}
 const struct {
@@ -252,7 +270,7 @@ static struct vga_post *vga_posth = NULL
 #endif
 
 static void
-pci_conf_lock(struct pci_conf_lock *ocl, uint32_t sel)
+pci_conf_lock(struct pci_conf_lock *ocl, pci_conf_selector_t sel)
 {
        uint32_t cpuno;
 
@@ -313,21 +331,37 @@ pci_conf_unlock(struct pci_conf_lock *oc
        kpreempt_enable();
 }
 
-static uint32_t
-pci_conf_selector(pcitag_t tag, int reg)
+static union pci_conf_selector
+pci_conf_selector_cam1(pcitag_t tag, int reg)
 {
-       static const pcitag_t mode2_mask = {
-               .mode2 = {
-                         .enable = 0xff
-                       , .forward = 0xff
-               }
-       };
+       union pci_conf_selector sel;
+
+       sel.mode1.address =
+           PCI_MODE1_ENABLE | (__SHIFTOUT(tag, X86_PCITAG_BDF) << 8) | reg;
 
+       return sel;
+}
+
+static union pci_conf_selector
+pci_conf_selector_cam2(pcitag_t tag, int reg)
+{
+       union pci_conf_selector sel;
+
+       sel.mode2.port = 0xc000 | (__SHIFTOUT(tag, X86_PCITAG_DEV) << 8) | reg;
+       sel.mode2.enable = 0xf0 | (__SHIFTOUT(tag, X86_PCITAG_FUNC) << 1);
+       sel.mode2.forward = __SHIFTOUT(tag, X86_PCITAG_BUS);
+
+       return sel;
+}
+
+static pci_conf_selector_t
+pci_conf_selector(pcitag_t tag, int reg)
+{
        switch (pci_mode) {
        case 1:
-               return tag.mode1 | reg;
+               return pci_conf_selector_cam1(tag, reg).selector;
        case 2:
-               return tag.mode1 & mode2_mask.mode1;
+               return pci_conf_selector_cam2(tag, reg).selector;
        default:
                panic("%s: mode not configured", __func__);
        }
@@ -340,26 +374,25 @@ pci_conf_port(pcitag_t tag, int reg)
        case 1:
                return PCI_MODE1_DATA_REG;
        case 2:
-               return tag.mode2.port | reg;
+               return pci_conf_selector_cam2(tag, reg).mode2.port;
        default:
                panic("%s: mode not configured", __func__);
        }
 }
 
 static void
-pci_conf_select(uint32_t sel)
+pci_conf_select(pci_conf_selector_t selector)
 {
-       pcitag_t tag;
+       union pci_conf_selector sel = { .selector = selector };
 
        switch (pci_mode) {
        case 1:
-               outl(PCI_MODE1_ADDRESS_REG, sel);
+               outl(PCI_MODE1_ADDRESS_REG, sel.mode1.address);
                return;
        case 2:
-               tag.mode1 = sel;
-               outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
-               if (tag.mode2.enable != 0)
-                       outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
+               outb(PCI_MODE2_ENABLE_REG, sel.mode2.enable);
+               if (sel.mode2.enable != 0)
+                       outb(PCI_MODE2_FORWARD_REG, sel.mode2.forward);
                return;
        default:
                panic("%s: mode not configured", __func__);
@@ -408,25 +441,15 @@ pci_make_tag(pci_chipset_tag_t pc, int b
                    pc, bus, device, function);
        }
 
-       switch (pci_mode) {
-       case 1:
-               if (bus >= 256 || device >= 32 || function >= 8)
-                       panic("%s: bad request", __func__);
-
-               tag.mode1 = PCI_MODE1_ENABLE |
-                           (bus << 16) | (device << 11) | (function << 8);
-               return tag;
-       case 2:
-               if (bus >= 256 || device >= 16 || function >= 8)
-                       panic("%s: bad request", __func__);
+       KASSERT(bus < 256);
+       KASSERT(device < 32);
+       KASSERT(function < 8);
+
+       tag = __SHIFTIN((function), X86_PCITAG_FUNC);
+       tag |=__SHIFTIN((device), X86_PCITAG_DEV);
+       tag |= __SHIFTIN((bus), X86_PCITAG_BUS);
 
-               tag.mode2.port = 0xc000 | (device << 8);
-               tag.mode2.enable = 0xf0 | (function << 1);
-               tag.mode2.forward = bus;
-               return tag;
-       default:
-               panic("%s: mode not configured", __func__);
-       }
+       return tag;
 }
 
 void
@@ -443,26 +466,14 @@ pci_decompose_tag(pci_chipset_tag_t pc, 
                return;
        }
 
-       switch (pci_mode) {
-       case 1:
-               if (bp != NULL)
-                       *bp = (tag.mode1 >> 16) & 0xff;
-               if (dp != NULL)
-                       *dp = (tag.mode1 >> 11) & 0x1f;
-               if (fp != NULL)
-                       *fp = (tag.mode1 >> 8) & 0x7;
-               return;
-       case 2:
-               if (bp != NULL)
-                       *bp = tag.mode2.forward & 0xff;
-               if (dp != NULL)
-                       *dp = (tag.mode2.port >> 8) & 0xf;
-               if (fp != NULL)
-                       *fp = (tag.mode2.enable >> 1) & 0x7;
-               return;
-       default:
-               panic("%s: mode not configured", __func__);
-       }
+       if (fp != NULL)
+               *fp = __SHIFTOUT(tag, X86_PCITAG_FUNC);
+       if (dp != NULL)
+               *dp = __SHIFTOUT(tag, X86_PCITAG_DEV);
+       if (bp != NULL)
+               *bp = __SHIFTOUT(tag, X86_PCITAG_BUS);
+
+       return;
 }
 
 pcireg_t
@@ -480,6 +491,11 @@ pci_conf_read(pci_chipset_tag_t pc, pcit
                return (*ipc->pc_ov->ov_conf_read)(ipc->pc_ctx, pc, tag, reg);
        }
 
+       if (__predict_false(reg >= PCI_CONF_SIZE ||
+           (pci_mode == 2 && __SHIFTOUT(tag, X86_PCITAG_DEV) >= 16))) {
+               return 0xffffffff;
+       }
+
        pci_conf_lock(&ocl, pci_conf_selector(tag, reg));
        data = inl(pci_conf_port(tag, reg));
        pci_conf_unlock(&ocl);
@@ -502,6 +518,11 @@ pci_conf_write(pci_chipset_tag_t pc, pci
                return;
        }
 
+       if (__predict_false(reg >= PCI_CONF_SIZE ||
+           (pci_mode == 2 && __SHIFTOUT(tag, X86_PCITAG_DEV) >= 16))) {
+               return;
+       }
+
        pci_conf_lock(&ocl, pci_conf_selector(tag, reg));
        outl(pci_conf_port(tag, reg), data);
        pci_conf_unlock(&ocl);
@@ -540,7 +561,7 @@ pci_mode_detect(void)
 
                if (PCI_VENDOR(pcim1_quirk_tbl[i].id) == PCI_VENDOR_INVALID)
                        continue;
-               t.mode1 = pcim1_quirk_tbl[i].tag.mode1;
+               t = pcim1_quirk_tbl[i].tag;
                idreg = pci_conf_read(NULL, t, PCI_ID_REG); /* needs "pci_mode" 
*/
                if (idreg == pcim1_quirk_tbl[i].id) {
 #ifdef DEBUG
Index: sys/arch/xen/xen/xpci_xenbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xpci_xenbus.c,v
retrieving revision 1.12
diff -u -a -p -r1.12 xpci_xenbus.c
--- sys/arch/xen/xen/xpci_xenbus.c      5 Dec 2012 01:46:22 -0000       1.12
+++ sys/arch/xen/xen/xpci_xenbus.c      6 Dec 2012 02:47:54 -0000
@@ -385,10 +385,15 @@ pcitag_t
 pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
 {
        pcitag_t tag;
-       KASSERT((function & ~0x7) == 0);
-       KASSERT((device & ~0x1f) == 0);
-       KASSERT((bus & ~0xff) == 0);
-       tag.mode1 = (bus << 8) | (device << 3) | (function << 0);
+
+       KASSERT(function < 8);
+       KASSERT(device < 32);
+       KASSERT(bus < 256);
+
+       tag = __SHIFTIN((function), X86_PCITAG_FUNC);
+       tag |=__SHIFTIN((device), X86_PCITAG_DEV);
+       tag |= __SHIFTIN((bus), X86_PCITAG_BUS);
+
        return tag;
 }
 
@@ -397,11 +402,11 @@ pci_decompose_tag(pci_chipset_tag_t pc, 
     int *bp, int *dp, int *fp)
 {
        if (bp != NULL)
-               *bp = (tag.mode1 >> 8) & 0xff;
+               *bp = __SHIFTOUT(tag, X86_PCITAG_BUS);
        if (dp != NULL)
-               *dp = (tag.mode1 >> 3) & 0x1f;
+               *dp = __SHIFTOUT(tag, X86_PCITAG_DEV);
        if (fp != NULL)
-               *fp = (tag.mode1 >> 0) & 0x7;
+               *fp = __SHIFTOUT(tag, X86_PCITAG_FUNC);
        return;
 }
 
@@ -433,15 +438,15 @@ static int
 xpci_conf_read( pci_chipset_tag_t pc, pcitag_t tag, int reg, int size,
     pcireg_t *value)
 {
-       int bus, dev, func;
        struct xen_pci_op op = {
                .cmd    = XEN_PCI_OP_conf_read,
                .domain = 0, /* XXX */
        };
-       pci_decompose_tag(pc, tag, &bus, &dev, &func);
-       DPRINTF(("pci_conf_read %d:%d:%d reg 0x%x", bus, dev, func, reg));
-       op.bus = bus;
-       op.devfn = (dev << 3) | func;
+       DPRINTF(("xpci_conf_read %d:%d:%d reg 0x%x",
+           __SHIFTOUT(tag, X86_PCITAG_BUS), __SHIFTOUT(tag, X86_PCITAG_DEV),
+           __SHIFTOUT(tag, X86_PCITAG_FUNC), reg));
+       op.bus = __SHIFTOUT(tag, X86_PCITAG_BUS);
+       op.devfn = __SHIFTOUT(tag, X86_PCITAG_DEVFUNC);
        op.offset = reg;
        op.size   = size;
        xpci_do_op(&op);
@@ -489,15 +494,15 @@ static int
 xpci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, int size,
     pcireg_t data)
 {
-       int bus, dev, func;
        struct xen_pci_op op = {
                .cmd    = XEN_PCI_OP_conf_write,
                .domain = 0, /* XXX */
        };
-       pci_decompose_tag(pc, tag, &bus, &dev, &func);
-       DPRINTF(("pci_conf_write %d:%d:%d reg 0x%x val 0x%x", bus, dev, func, 
reg, data));
-       op.bus = bus;
-       op.devfn = (dev << 3) | func;
+       DPRINTF(("xpci_conf_write %d:%d:%d reg 0x%x val 0x%x",
+           __SHIFTOUT(tag, X86_PCITAG_BUS), __SHIFTOUT(tag, X86_PCITAG_DEV),
+           __SHIFTOUT(tag, X86_PCITAG_FUNC), reg, data));
+       op.bus = __SHIFTOUT(tag, X86_PCITAG_BUS);
+       op.devfn = __SHIFTOUT(tag, X86_PCITAG_DEVFUNC);
        op.offset = reg;
        op.size   = size;
        op.value = data;


Home | Main Index | Thread Index | Old Index