arch/alpha/kernel/core_t2.c

Source file repositories/reference/linux-study-clean/arch/alpha/kernel/core_t2.c

File Facts

System
Linux kernel
Corpus path
arch/alpha/kernel/core_t2.c
Extension
.c
Size
16699 bytes
Lines
625
Domain
Architecture Layer
Bucket
arch/alpha
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (device > 8) {
			DBG(("mk_conf_addr: device (%d)>20, returning -1\n",
			     device));
			return -1;
		}

		*type1 = 0;
		addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where);
	} else {
		/* Type 1 configuration cycle.  */
		*type1 = 1;
		addr = (bus << 16) | (device_fn << 8) | (where);
	}
	*pci_addr = addr;
	DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
	return 0;
}

/*
 * NOTE: both conf_read() and conf_write() may set HAE_3 when needing
 *       to do type1 access. This is protected by the use of spinlock IRQ
 *       primitives in the wrapper functions pci_{read,write}_config_*()
 *       defined in drivers/pci/pci.c.
 */
static unsigned int
conf_read(unsigned long addr, unsigned char type1)
{
	unsigned int value, cpu, taken;
	unsigned long t2_cfg = 0;

	cpu = smp_processor_id();

	DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));

	/* If Type1 access, must set T2 CFG.  */
	if (type1) {
		t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
		*(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
		mb();
	}
	mb();
	draina();

	mcheck_expected(cpu) = 1;
	mcheck_taken(cpu) = 0;
	t2_mcheck_any_expected |= (1 << cpu);
	mb();

	/* Access configuration space. */
	value = *(vuip)addr;
	mb();
	mb();  /* magic */

	/* Wait for possible mcheck. Also, this lets other CPUs clear
	   their mchecks as well, as they can reliably tell when
	   another CPU is in the midst of handling a real mcheck via
	   the "taken" function. */
	udelay(100);

	if ((taken = mcheck_taken(cpu))) {
		mcheck_taken(cpu) = 0;
		t2_mcheck_last_taken |= (1 << cpu);
		value = 0xffffffffU;
		mb();
	}
	mcheck_expected(cpu) = 0;
	t2_mcheck_any_expected = 0;
	mb();

	/* If Type1 access, must reset T2 CFG so normal IO space ops work.  */
	if (type1) {
		*(vulp)T2_HAE_3 = t2_cfg;
		mb();
	}

	return value;
}

static void
conf_write(unsigned long addr, unsigned int value, unsigned char type1)
{
	unsigned int cpu, taken;
	unsigned long t2_cfg = 0;

	cpu = smp_processor_id();

	/* If Type1 access, must set T2 CFG.  */
	if (type1) {
		t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
		*(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;

Annotation

Implementation Notes