]> Zhao Yanbai Git Server - minix.git/commitdiff
PCI: expose BAR sizes
authorDavid van Moolenbroek <david@minix3.org>
Thu, 1 Jul 2010 09:10:16 +0000 (09:10 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 1 Jul 2010 09:10:16 +0000 (09:10 +0000)
drivers/atl2/atl2.c
drivers/atl2/atl2.h
drivers/pci/main.c
drivers/pci/pci.c
drivers/pci/pci.h
include/minix/com.h
include/minix/syslib.h
lib/libsys/Makefile
lib/libsys/pci_get_bar.c [new file with mode: 0644]

index 670949006f7ece30add177b6a11e9242661e9b04..381eb56b9fd1aa1cb82e6fee2f83a4485c96c01f 100644 (file)
@@ -38,6 +38,7 @@ PRIVATE struct {
        int hook_id;            /* IRQ hook ID */
        int mode;               /* datalink mode */
        char *base;             /* base address of memory-mapped registers */
+       u32_t size;             /* size of memory-mapped area */
        u32_t hwaddr[2];        /* MAC address, in register representation */
 
        u8_t *txd_base;         /* local address of TxD ring buffer base */
@@ -514,7 +515,7 @@ PRIVATE void atl2_init(int devind)
        /* Initialize the device.
         */
        u32_t bar;
-       int r;
+       int r, flag;
 
        /* Initialize global state. */
        state.devind = devind;
@@ -524,12 +525,13 @@ PRIVATE void atl2_init(int devind)
 
        memset(&state.stat, 0, sizeof(state.stat));
 
-       bar = pci_attr_r32(devind, PCI_BAR) & 0xfffffff0;
+       if ((r = pci_get_bar(devind, PCI_BAR, &bar, &state.size, &flag)) != OK)
+               panic("unable to retrieve bar: %d", r);
 
-       /* FIXME: hardcoded length, as PCI doesn't expose the size, and it is
-        * not our job to compute the size from the BAR ourselves.
-        */
-       state.base = vm_map_phys(SELF, (void *) bar, ATL2_MMAP_SIZE);
+       if (state.size < ATL2_MIN_MMAP_SIZE || flag)
+               panic("invalid register bar");
+
+       state.base = vm_map_phys(SELF, (void *) bar, state.size);
        if (state.base == MAP_FAILED)
                panic("unable to map in registers");
 
@@ -1214,7 +1216,7 @@ PRIVATE void sef_cb_signal_handler(int signo)
        free_contig(state.rxd_base_u,
                state.rxd_align + ATL2_RXD_COUNT * ATL2_RXD_SIZE);
 
-       vm_unmap_phys(SELF, state.base, ATL2_MMAP_SIZE);
+       vm_unmap_phys(SELF, state.base, state.size);
 
        /* We cannot free the PCI device at this time. */
 
index 06812bcd00738ce290a60aefb44efad1dcfab00d..85c5e4362a923d91456cc22368c874c6126fef51 100644 (file)
@@ -1,6 +1,6 @@
 /* Attansic/Atheros L2 FastEthernet driver, by D.C. van Moolenbroek */
 
-#define ATL2_MMAP_SIZE                 0x40000 /* memory-mapped registers */
+#define ATL2_MIN_MMAP_SIZE             0x1608  /* min. register memory size */
 
 /* The first three are configurable to a certain extent; the last is not. */
 #define ATL2_TXD_BUFSIZE               8192    /* TxD ring buffer size */
index 8ddd0cc4da45d17ada1f60d2243f28d14c108ded..4d2ba273d25e32fc59009c5307ad65466c26893e 100644 (file)
@@ -23,6 +23,7 @@ FORWARD _PROTOTYPE( void do_attr_r32, (message *mp)                   );
 FORWARD _PROTOTYPE( void do_attr_w8, (message *mp)                     );
 FORWARD _PROTOTYPE( void do_attr_w16, (message *mp)                    );
 FORWARD _PROTOTYPE( void do_attr_w32, (message *mp)                    );
+FORWARD _PROTOTYPE( void do_get_bar, (message *mp)                     );
 FORWARD _PROTOTYPE( void do_rescan_bus, (message *mp)                  );
 FORWARD _PROTOTYPE( void reply, (message *mp, int result)              );
 FORWARD _PROTOTYPE( struct rs_pci *find_acl, (int endpoint)            );
@@ -77,6 +78,7 @@ int main(void)
                case BUSC_PCI_SLOT_NAME_S: do_slot_name_s(&m); break;
                case BUSC_PCI_SET_ACL: do_set_acl(&m); break;
                case BUSC_PCI_DEL_ACL: do_del_acl(&m); break;
+               case BUSC_PCI_GET_BAR: do_get_bar(&m); break;
                default:
                        printf("PCI: got message from %d, type %d\n",
                                m.m_source, m.m_type);
@@ -562,6 +564,32 @@ message *mp;
        }
 }
 
+PRIVATE void do_get_bar(mp)
+message *mp;
+{
+       int r, devind, port, ioflag;
+       u32_t base, size;
+
+       devind= mp->BUSC_PGB_DEVIND;
+       port= mp->BUSC_PGB_PORT;
+
+       mp->m_type= pci_get_bar_s(devind, port, &base, &size, &ioflag);
+
+       if (mp->m_type == OK)
+       {
+               mp->BUSC_PGB_BASE= base;
+               mp->BUSC_PGB_SIZE= size;
+               mp->BUSC_PGB_IOFLAG= ioflag;
+       }
+
+       r= send(mp->m_source, mp);
+       if (r != 0)
+       {
+               printf("do_get_bar: unable to send to %d: %d\n",
+                       mp->m_source, r);
+       }
+}
+
 PRIVATE void do_rescan_bus(mp)
 message *mp;
 {
index b72f6eb31cbce89835c1de17a4abafe4585e4c36..90971452b8ab17623ec022b29091e56504889eb2 100644 (file)
@@ -516,6 +516,36 @@ PUBLIC char *pci_dev_name(u16_t vid, u16_t did)
        return NULL;
 }
 
+/*===========================================================================*
+ *                             pci_get_bar_s                                *
+ *===========================================================================*/
+PUBLIC int pci_get_bar_s(int devind, int port, u32_t *base, u32_t *size,
+       int *ioflag)
+{
+       int i, reg;
+
+       if (devind < 0 || devind >= nr_pcidev)
+               return EINVAL;
+
+       for (i= 0; i < pcidev[devind].pd_bar_nr; i++)
+       {
+               reg= PCI_BAR+4*pcidev[devind].pd_bar[i].pb_nr;
+
+               if (reg == port)
+               {
+                       if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE)
+                               return EINVAL;
+
+                       *base= pcidev[devind].pd_bar[i].pb_base;
+                       *size= pcidev[devind].pd_bar[i].pb_size;
+                       *ioflag=
+                               !!(pcidev[devind].pd_bar[i].pb_flags & PBF_IO);
+                       return OK;
+               }
+       }
+       return EINVAL;
+}
+
 /*===========================================================================*
  *                             pci_attr_r8_s                                *
  *===========================================================================*/
index 9f91f31917140b02249fd426e2ea973510981812..af0a066534345636d5bd90846941014733104d19 100644 (file)
@@ -105,6 +105,8 @@ _PROTOTYPE( int pci_next_dev_a, (struct rs_pci *aclp, int *devindp,
 
 _PROTOTYPE( int pci_attr_r8_s, (int devind, int port, u8_t *vp)                );
 _PROTOTYPE( int pci_attr_r32_s, (int devind, int port, u32_t *vp)      );
+_PROTOTYPE( int pci_get_bar_s, (int devind, int port, u32_t *base,
+                                       u32_t *size, int *ioflag)       );
 _PROTOTYPE( int pci_slot_name_s, (int devind, char **cpp)              );
 _PROTOTYPE( int pci_ids_s, (int devind, u16_t *vidp, u16_t *didp)      );
 
index 5a184f4a5c466e8879a911d83b790909a5082d62..fe7a25a97a54ae9bfb0a86deb3f5d61db2013d03 100644 (file)
 #define BUSC_PCI_DEL_ACL       (BUSC_RQ_BASE + 18)     /* Delete the ACL of a
                                                         * driver 
                                                         */
+#define BUSC_PCI_GET_BAR       (BUSC_RQ_BASE + 19)     /* Get Base Address
+                                                        * Register properties
+                                                        */
+#define   BUSC_PGB_DEVIND      m2_i1                   /* device index */
+#define   BUSC_PGB_PORT                m2_i2                   /* port (BAR offset) */
+#define   BUSC_PGB_BASE                m2_l1                   /* BAR base address */
+#define   BUSC_PGB_SIZE                m2_l2                   /* BAR size */
+#define   BUSC_PGB_IOFLAG      m2_i1                   /* I/O space? */
 #define IOMMU_MAP              (BUSC_RQ_BASE + 32)     /* Ask IOMMU to map
                                                         * a segment of memory
                                                         */
index 9b5131f55ee7b22e5c073413da2f9267011edd7f..762a6b1814de4943daaa60f90cea8f1ca0759eb4 100644 (file)
@@ -250,6 +250,8 @@ _PROTOTYPE( char *pci_dev_name, (u16_t vid, u16_t did)                      );
 _PROTOTYPE( char *pci_slot_name, (int devind)                          );
 _PROTOTYPE( int pci_set_acl, (struct rs_pci *rs_pci)                   );
 _PROTOTYPE( int pci_del_acl, (endpoint_t proc_ep)                      );
+_PROTOTYPE( int pci_get_bar, (int devind, int port, u32_t *base,
+                                       u32_t *size, int *ioflag)       );
 
 /* Profiling. */
 _PROTOTYPE( int sys_sprof, (int action, int size, int freq,
index 1a80971b8fcf0fe49070305c05cb4c016737cbad..ad76629e867a59dba643a017de7cb7f7b061fa6a 100644 (file)
@@ -17,6 +17,7 @@ SRCS=  \
        pci_dev_name.c \
        pci_find_dev.c \
        pci_first_dev.c \
+       pci_get_bar.c \
        pci_ids.c \
        pci_init.c \
        pci_init1.c \
diff --git a/lib/libsys/pci_get_bar.c b/lib/libsys/pci_get_bar.c
new file mode 100644 (file)
index 0000000..6d977f9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+pci_get_bar.c
+*/
+
+#include "pci.h"
+#include "syslib.h"
+#include <minix/sysutil.h>
+
+/*===========================================================================*
+ *                             pci_get_bar                                  *
+ *===========================================================================*/
+PUBLIC int pci_get_bar(devind, port, base, size, ioflag)
+int devind;
+int port;
+u32_t *base;
+u32_t *size;
+int *ioflag;
+{
+       int r;
+       message m;
+
+       m.m_type= BUSC_PCI_GET_BAR;
+       m.BUSC_PGB_DEVIND= devind;
+       m.BUSC_PGB_PORT= port;
+
+       r= sendrec(pci_procnr, &m);
+       if (r != 0)
+               panic("pci_get_bar: can't talk to PCI: %d", r);
+
+       if (m.m_type == 0)
+       {
+               *base= m.BUSC_PGB_BASE;
+               *size= m.BUSC_PGB_SIZE;
+               *ioflag= m.BUSC_PGB_IOFLAG;
+       }
+       return m.m_type;
+}
+