PCI: add 64-bit BAR support
This commit is contained in:
parent
b31119abf5
commit
6a5660a431
3 changed files with 99 additions and 32 deletions
|
@ -91,7 +91,7 @@ PRIVATE struct {
|
|||
{ 0x0000, 0x0000 }
|
||||
};
|
||||
|
||||
long instance;
|
||||
PRIVATE long instance;
|
||||
|
||||
/*===========================================================================*
|
||||
* atl2_read_vpd *
|
||||
|
@ -524,14 +524,6 @@ PRIVATE void atl2_init(int devind)
|
|||
|
||||
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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Initialize the atl2 driver. */
|
||||
/* Initialize the atl2 driver.
|
||||
*/
|
||||
u32_t inet_endpt;
|
||||
int r, devind;
|
||||
#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)
|
||||
{
|
||||
/* Initialize SEF.
|
||||
*/
|
||||
|
||||
/* Register init callbacks. */
|
||||
sef_setcb_init_fresh(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( int is_duplicate, (U8_t busnr, U8_t dev, U8_t func) );
|
||||
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_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_bars, (void) );
|
||||
FORWARD _PROTOTYPE( void update_bridge4dev_io, (int devind,
|
||||
|
@ -870,7 +871,7 @@ printf("probe_bus(%d)\n", busind);
|
|||
switch(headt & PHT_MASK)
|
||||
{
|
||||
case PHT_NORMAL:
|
||||
record_bars(devind);
|
||||
record_bars_normal(devind);
|
||||
break;
|
||||
case PHT_BRIDGE:
|
||||
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 i, j, reg, prefetch, type, clear_01, clear_23, pb_nr;
|
||||
u32_t bar, bar2;
|
||||
int i, j, clear_01, clear_23, pb_nr;
|
||||
|
||||
for (i= 0, reg= PCI_BAR; reg <= PCI_BAR_6; i++, reg += 4)
|
||||
{
|
||||
record_bar(devind, i);
|
||||
}
|
||||
/* The BAR area of normal devices is six DWORDs in size. */
|
||||
record_bars(devind, PCI_BAR_6);
|
||||
|
||||
/* Special case code for IDE controllers in compatibility mode */
|
||||
if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
|
||||
|
@ -1067,8 +1065,10 @@ int devind;
|
|||
{
|
||||
u32_t base, limit, size;
|
||||
|
||||
record_bar(devind, 0);
|
||||
record_bar(devind, 1);
|
||||
/* The generic BAR area of PCI-to-PCI bridges is two DWORDs in size.
|
||||
* 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) |
|
||||
(pci_attr_r16(devind, PPB_IOBASEU16) << 16);
|
||||
|
@ -1117,7 +1117,8 @@ int devind;
|
|||
{
|
||||
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);
|
||||
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 *
|
||||
*===========================================================================*/
|
||||
PRIVATE void record_bar(devind, bar_nr)
|
||||
PRIVATE int record_bar(devind, bar_nr, last)
|
||||
int devind;
|
||||
int bar_nr;
|
||||
int last;
|
||||
{
|
||||
int reg, prefetch, type, dev_bar_nr;
|
||||
int reg, prefetch, type, dev_bar_nr, width;
|
||||
u32_t bar, bar2;
|
||||
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;
|
||||
|
||||
bar= pci_attr_r32_u(devind, reg);
|
||||
|
@ -1210,6 +1228,56 @@ int bar_nr;
|
|||
}
|
||||
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 */
|
||||
cmd = pci_attr_r16(devind, PCI_CR);
|
||||
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);
|
||||
|
||||
if (bar2 == 0)
|
||||
return; /* Reg. is not implemented */
|
||||
return width; /* Reg. is not implemented */
|
||||
|
||||
prefetch= !!(bar & PCI_BAR_PREFETCH);
|
||||
type= (bar & PCI_BAR_TYPE);
|
||||
bar &= ~(u32_t)0xf; /* Clear non-address bits */
|
||||
bar2 &= ~(u32_t)0xf;
|
||||
bar2= (~bar2)+1;
|
||||
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,
|
||||
prefetch ? " prefetchable" : "");
|
||||
if (type != 0)
|
||||
printf("type = 0x%x\n", type);
|
||||
prefetch ? " prefetchable" : "",
|
||||
type == PCI_TYPE_64 ? ", 64-bit" : "");
|
||||
}
|
||||
|
||||
dev_bar_nr= pcidev[devind].pd_bar_nr++;
|
||||
|
@ -1250,6 +1316,8 @@ int bar_nr;
|
|||
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_IO 0x00000001 /* Reg. refers to I/O space */
|
||||
#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_2 0x14 /* Base Address Register */
|
||||
#define PCI_BAR_3 0x18 /* Base Address Register */
|
||||
|
|
Loading…
Reference in a new issue