PCI: add 64-bit BAR support
This commit is contained in:
		
							parent
							
								
									b31119abf5
								
							
						
					
					
						commit
						6a5660a431
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user