PCI: expose BAR sizes

This commit is contained in:
David van Moolenbroek 2010-07-01 09:10:16 +00:00
parent 9e4312453d
commit 2488cc6442
9 changed files with 119 additions and 8 deletions

View 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. */

View 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 */

View 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;
{

View 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 *
*===========================================================================*/

View 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) );

View file

@ -171,6 +171,14 @@
#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
*/

View 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,

View 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 \

38
lib/libsys/pci_get_bar.c Normal file
View file

@ -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;
}