PCI: add 64-bit BAR support
This commit is contained in:
parent
b31119abf5
commit
6a5660a431
@ -91,7 +91,7 @@ PRIVATE struct {
|
|||||||
{ 0x0000, 0x0000 }
|
{ 0x0000, 0x0000 }
|
||||||
};
|
};
|
||||||
|
|
||||||
long instance;
|
PRIVATE long instance;
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* atl2_read_vpd *
|
* atl2_read_vpd *
|
||||||
@ -524,14 +524,6 @@ PRIVATE void atl2_init(int devind)
|
|||||||
|
|
||||||
memset(&state.stat, 0, sizeof(state.stat));
|
memset(&state.stat, 0, sizeof(state.stat));
|
||||||
|
|
||||||
/* FIXME: zero out the upper half of the 64-bit BAR. This is currently
|
|
||||||
* needed because the BIOS sets it to a nonzero value, and our PCI
|
|
||||||
* driver does not yet recognize 64-bit BARs at all. If either ever
|
|
||||||
* gets fixed, this will be a no-op, but for the time being, we simply
|
|
||||||
* hope that it will do the job.
|
|
||||||
*/
|
|
||||||
pci_attr_w32(devind, PCI_BAR_2, 0);
|
|
||||||
|
|
||||||
bar = pci_attr_r32(devind, PCI_BAR) & 0xfffffff0;
|
bar = pci_attr_r32(devind, PCI_BAR) & 0xfffffff0;
|
||||||
|
|
||||||
/* FIXME: hardcoded length, as PCI doesn't expose the size, and it is
|
/* FIXME: hardcoded length, as PCI doesn't expose the size, and it is
|
||||||
@ -1243,7 +1235,8 @@ PRIVATE void atl2_dump(void)
|
|||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
{
|
{
|
||||||
/* Initialize the atl2 driver. */
|
/* Initialize the atl2 driver.
|
||||||
|
*/
|
||||||
u32_t inet_endpt;
|
u32_t inet_endpt;
|
||||||
int r, devind;
|
int r, devind;
|
||||||
#if ATL2_FKEY
|
#if ATL2_FKEY
|
||||||
@ -1286,6 +1279,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void sef_local_startup(void)
|
PRIVATE void sef_local_startup(void)
|
||||||
{
|
{
|
||||||
|
/* Initialize SEF.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Register init callbacks. */
|
/* Register init callbacks. */
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
sef_setcb_init_restart(sef_cb_init_fresh);
|
||||||
|
@ -97,10 +97,11 @@ FORWARD _PROTOTYPE( void pci_intel_init, (void) );
|
|||||||
FORWARD _PROTOTYPE( void probe_bus, (int busind) );
|
FORWARD _PROTOTYPE( void probe_bus, (int busind) );
|
||||||
FORWARD _PROTOTYPE( int is_duplicate, (U8_t busnr, U8_t dev, U8_t func) );
|
FORWARD _PROTOTYPE( int is_duplicate, (U8_t busnr, U8_t dev, U8_t func) );
|
||||||
FORWARD _PROTOTYPE( void record_irq, (int devind) );
|
FORWARD _PROTOTYPE( void record_irq, (int devind) );
|
||||||
FORWARD _PROTOTYPE( void record_bars, (int devind) );
|
FORWARD _PROTOTYPE( void record_bars_normal, (int devind) );
|
||||||
FORWARD _PROTOTYPE( void record_bars_bridge, (int devind) );
|
FORWARD _PROTOTYPE( void record_bars_bridge, (int devind) );
|
||||||
FORWARD _PROTOTYPE( void record_bars_cardbus, (int devind) );
|
FORWARD _PROTOTYPE( void record_bars_cardbus, (int devind) );
|
||||||
FORWARD _PROTOTYPE( void record_bar, (int devind, int bar_nr) );
|
FORWARD _PROTOTYPE( void record_bars, (int devind, int last_reg) );
|
||||||
|
FORWARD _PROTOTYPE( int record_bar, (int devind, int bar_nr, int last) );
|
||||||
FORWARD _PROTOTYPE( void complete_bridges, (void) );
|
FORWARD _PROTOTYPE( void complete_bridges, (void) );
|
||||||
FORWARD _PROTOTYPE( void complete_bars, (void) );
|
FORWARD _PROTOTYPE( void complete_bars, (void) );
|
||||||
FORWARD _PROTOTYPE( void update_bridge4dev_io, (int devind,
|
FORWARD _PROTOTYPE( void update_bridge4dev_io, (int devind,
|
||||||
@ -870,7 +871,7 @@ printf("probe_bus(%d)\n", busind);
|
|||||||
switch(headt & PHT_MASK)
|
switch(headt & PHT_MASK)
|
||||||
{
|
{
|
||||||
case PHT_NORMAL:
|
case PHT_NORMAL:
|
||||||
record_bars(devind);
|
record_bars_normal(devind);
|
||||||
break;
|
break;
|
||||||
case PHT_BRIDGE:
|
case PHT_BRIDGE:
|
||||||
record_bars_bridge(devind);
|
record_bars_bridge(devind);
|
||||||
@ -993,18 +994,15 @@ int devind;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* record_bars *
|
* record_bars_normal *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void record_bars(devind)
|
PRIVATE void record_bars_normal(devind)
|
||||||
int devind;
|
int devind;
|
||||||
{
|
{
|
||||||
int i, j, reg, prefetch, type, clear_01, clear_23, pb_nr;
|
int i, j, clear_01, clear_23, pb_nr;
|
||||||
u32_t bar, bar2;
|
|
||||||
|
|
||||||
for (i= 0, reg= PCI_BAR; reg <= PCI_BAR_6; i++, reg += 4)
|
/* The BAR area of normal devices is six DWORDs in size. */
|
||||||
{
|
record_bars(devind, PCI_BAR_6);
|
||||||
record_bar(devind, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special case code for IDE controllers in compatibility mode */
|
/* Special case code for IDE controllers in compatibility mode */
|
||||||
if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
|
if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
|
||||||
@ -1067,8 +1065,10 @@ int devind;
|
|||||||
{
|
{
|
||||||
u32_t base, limit, size;
|
u32_t base, limit, size;
|
||||||
|
|
||||||
record_bar(devind, 0);
|
/* The generic BAR area of PCI-to-PCI bridges is two DWORDs in size.
|
||||||
record_bar(devind, 1);
|
* It may contain up to two 32-bit BARs, or one 64-bit BAR.
|
||||||
|
*/
|
||||||
|
record_bars(devind, PCI_BAR_2);
|
||||||
|
|
||||||
base= ((pci_attr_r8_u(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) |
|
base= ((pci_attr_r8_u(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) |
|
||||||
(pci_attr_r16(devind, PPB_IOBASEU16) << 16);
|
(pci_attr_r16(devind, PPB_IOBASEU16) << 16);
|
||||||
@ -1117,7 +1117,8 @@ int devind;
|
|||||||
{
|
{
|
||||||
u32_t base, limit, size;
|
u32_t base, limit, size;
|
||||||
|
|
||||||
record_bar(devind, 0);
|
/* The generic BAR area of CardBus devices is one DWORD in size. */
|
||||||
|
record_bars(devind, PCI_BAR);
|
||||||
|
|
||||||
base= pci_attr_r32_u(devind, CBB_MEMBASE_0);
|
base= pci_attr_r32_u(devind, CBB_MEMBASE_0);
|
||||||
limit= pci_attr_r32_u(devind, CBB_MEMLIMIT_0) |
|
limit= pci_attr_r32_u(devind, CBB_MEMLIMIT_0) |
|
||||||
@ -1160,17 +1161,34 @@ int devind;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* record_bars *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE void record_bars(devind, last_reg)
|
||||||
|
{
|
||||||
|
int i, reg, width;
|
||||||
|
|
||||||
|
for (i= 0, reg= PCI_BAR; reg <= last_reg; i += width, reg += 4 * width)
|
||||||
|
{
|
||||||
|
width = record_bar(devind, i, reg == last_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* record_bar *
|
* record_bar *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void record_bar(devind, bar_nr)
|
PRIVATE int record_bar(devind, bar_nr, last)
|
||||||
int devind;
|
int devind;
|
||||||
int bar_nr;
|
int bar_nr;
|
||||||
|
int last;
|
||||||
{
|
{
|
||||||
int reg, prefetch, type, dev_bar_nr;
|
int reg, prefetch, type, dev_bar_nr, width;
|
||||||
u32_t bar, bar2;
|
u32_t bar, bar2;
|
||||||
u16_t cmd;
|
u16_t cmd;
|
||||||
|
|
||||||
|
/* Start by assuming that this is a 32-bit bar, taking up one DWORD. */
|
||||||
|
width = 1;
|
||||||
|
|
||||||
reg= PCI_BAR+4*bar_nr;
|
reg= PCI_BAR+4*bar_nr;
|
||||||
|
|
||||||
bar= pci_attr_r32_u(devind, reg);
|
bar= pci_attr_r32_u(devind, reg);
|
||||||
@ -1210,6 +1228,56 @@ int bar_nr;
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
type= (bar & PCI_BAR_TYPE);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case PCI_TYPE_32:
|
||||||
|
case PCI_TYPE_32_1M:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCI_TYPE_64:
|
||||||
|
/* A 64-bit BAR takes up two consecutive DWORDs. */
|
||||||
|
if (last)
|
||||||
|
{
|
||||||
|
printf("PCI: device %d.%d.%d BAR %d extends"
|
||||||
|
" beyond designated area\n",
|
||||||
|
pcidev[devind].pd_busnr,
|
||||||
|
pcidev[devind].pd_dev,
|
||||||
|
pcidev[devind].pd_func, bar_nr);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
width++;
|
||||||
|
|
||||||
|
bar2= pci_attr_r32_u(devind, reg+4);
|
||||||
|
|
||||||
|
/* If the upper 32 bits of the BAR are not zero, the
|
||||||
|
* memory is inaccessible to us; ignore the BAR.
|
||||||
|
*/
|
||||||
|
if (bar2 != 0)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
printf("\tbar_%d: (64-bit BAR with"
|
||||||
|
" high bits set)\n", bar_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Ignore the BAR. */
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
printf("\tbar_%d: (unknown type %x)\n",
|
||||||
|
bar_nr, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable mem access before probing for BAR's size */
|
/* Disable mem access before probing for BAR's size */
|
||||||
cmd = pci_attr_r16(devind, PCI_CR);
|
cmd = pci_attr_r16(devind, PCI_CR);
|
||||||
pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_MEM_EN);
|
pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_MEM_EN);
|
||||||
@ -1223,20 +1291,18 @@ int bar_nr;
|
|||||||
pci_attr_w16(devind, PCI_CR, cmd);
|
pci_attr_w16(devind, PCI_CR, cmd);
|
||||||
|
|
||||||
if (bar2 == 0)
|
if (bar2 == 0)
|
||||||
return; /* Reg. is not implemented */
|
return width; /* Reg. is not implemented */
|
||||||
|
|
||||||
prefetch= !!(bar & PCI_BAR_PREFETCH);
|
prefetch= !!(bar & PCI_BAR_PREFETCH);
|
||||||
type= (bar & PCI_BAR_TYPE);
|
|
||||||
bar &= ~(u32_t)0xf; /* Clear non-address bits */
|
bar &= ~(u32_t)0xf; /* Clear non-address bits */
|
||||||
bar2 &= ~(u32_t)0xf;
|
bar2 &= ~(u32_t)0xf;
|
||||||
bar2= (~bar2)+1;
|
bar2= (~bar2)+1;
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
printf("\tbar_%d: 0x%x bytes at 0x%x%s memory\n",
|
printf("\tbar_%d: 0x%x bytes at 0x%x%s memory%s\n",
|
||||||
bar_nr, bar2, bar,
|
bar_nr, bar2, bar,
|
||||||
prefetch ? " prefetchable" : "");
|
prefetch ? " prefetchable" : "",
|
||||||
if (type != 0)
|
type == PCI_TYPE_64 ? ", 64-bit" : "");
|
||||||
printf("type = 0x%x\n", type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_bar_nr= pcidev[devind].pd_bar_nr++;
|
dev_bar_nr= pcidev[devind].pd_bar_nr++;
|
||||||
@ -1250,6 +1316,8 @@ int bar_nr;
|
|||||||
PBF_INCOMPLETE;
|
PBF_INCOMPLETE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -32,6 +32,9 @@ Created: Jan 2000 by Philip Homburg <philip@cs.vu.nl>
|
|||||||
#define PCI_BAR 0x10 /* Base Address Register */
|
#define PCI_BAR 0x10 /* Base Address Register */
|
||||||
#define PCI_BAR_IO 0x00000001 /* Reg. refers to I/O space */
|
#define PCI_BAR_IO 0x00000001 /* Reg. refers to I/O space */
|
||||||
#define PCI_BAR_TYPE 0x00000006 /* Memory BAR type */
|
#define PCI_BAR_TYPE 0x00000006 /* Memory BAR type */
|
||||||
|
#define PCI_TYPE_32 0x00000000 /* 32-bit BAR */
|
||||||
|
#define PCI_TYPE_32_1M 0x00000002 /* 32-bit below 1MB (legacy) */
|
||||||
|
#define PCI_TYPE_64 0x00000004 /* 64-bit BAR */
|
||||||
#define PCI_BAR_PREFETCH 0x00000008 /* Memory is prefetchable */
|
#define PCI_BAR_PREFETCH 0x00000008 /* Memory is prefetchable */
|
||||||
#define PCI_BAR_2 0x14 /* Base Address Register */
|
#define PCI_BAR_2 0x14 /* Base Address Register */
|
||||||
#define PCI_BAR_3 0x18 /* Base Address Register */
|
#define PCI_BAR_3 0x18 /* Base Address Register */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user