, T2_ISA_SG_LENGTH);

	*(vulp)T2_HBASE = 0x0; /* Disable HOLES. */

	/* Zero HAE.  */
	*(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */
	*(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */
	*(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */

	/*
	 * We also now zero out HAE_4, the dense memory HAE, so that
	 * we need not account for its "offset" when accessing dense
	 * memory resources which we allocated in our normal way. This
	 * HAE would need to stay untouched were we to keep the SRM
	 * resource settings.
	 *
	 * Thus we can now run standard X servers on SABLE/LYNX. :-)
	 */
	*(vulp)T2_HAE_4 = 0; mb();
}

void
t2_kill_arch(int mode)
{
	/*
	 * Restore the DMA Window registers.
	 */
	*(vulp)T2_WBASE1 = t2_saved_config.window[0].wbase;
	*(vulp)T2_WMASK1 = t2_saved_config.window[0].wmask;
	*(vulp)T2_TBASE1 = t2_saved_config.window[0].tbase;
	*(vulp)T2_WBASE2 = t2_saved_config.window[1].wbase;
	*(vulp)T2_WMASK2 = t2_saved_config.window[1].wmask;
	*(vulp)T2_TBASE2 = t2_saved_config.window[1].tbase;
	mb();

	*(vulp)T2_HAE_1 = srm_hae;
	*(vulp)T2_HAE_2 = t2_saved_config.hae_2;
	*(vulp)T2_HAE_3 = t2_saved_config.hae_3;
	*(vulp)T2_HAE_4 = t2_saved_config.hae_4;
	*(vulp)T2_HBASE = t2_saved_config.hbase;
	mb();
	*(vulp)T2_HBASE; /* READ it back to ensure WRITE occurred. */
}

void
t2_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
{
	unsigned long t2_iocsr;

	t2_iocsr = *(vulp)T2_IOCSR;

	/* set the TLB Clear bit */
	*(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 28);
	mb();
	*(vulp)T2_IOCSR; /* read it back to make sure */

	/* clear the TLB Clear bit */
	*(vulp)T2_IOCSR = t2_iocsr & ~(0x1UL << 28);
	mb();
	*(vulp)T2_IOCSR; /* read it back to make sure */
}

#define SIC_SEIC (1UL << 33)    /* System Event Clear */

static void
t2_clear_errors(int cpu)
{
	struct sable_cpu_csr *cpu_regs;

	cpu_regs = (struct sable_cpu_csr *)T2_CPUn_BASE(cpu);
		
	cpu_regs->sic &= ~SIC_SEIC;

	/* Clear CPU errors.  */
	cpu_regs->bcce |= cpu_regs->bcce;
	cpu_regs->cbe  |= cpu_regs->cbe;
	cpu_regs->bcue |= cpu_regs->bcue;
	cpu_regs->dter |= cpu_regs->dter;

	*(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
	*(vulp)T2_PERR1 |= *(vulp)T2_PERR1;

	mb();
	mb();  /* magic */
}

/*
 * SABLE seems to have a "broadcast" style machine check, in that all
 * CPUs receive it. And, the issuing CPU, in the case of PCI Config
 * space read/write faults, will also receive a second mcheck, upon
 * lowering IPL during completion processing in pci_read_config_byte()
 * et al.
 *
 * Hence all the taken/expected/any_expected/last_taken stuff...
 */
void
t2_machine_check(unsigned long vector, unsigned long la_ptr)
{
	int cpu = smp_processor_id();
#ifdef CONFIG_VERBOSE_MCHECK
	struct el_common *mchk_header = (struct el_common *)la_ptr;
#endif

	/* Clear the error before any reporting.  */
	mb();
	mb();  /* magic */
	draina();
	t2_clear_errors(cpu);

	/* This should not actually be done until the logout frame is
	   examined, but, since we don't do that, go on and do this... */
	wrmces(0x7);
	mb();

	/* Now, do testing for the anomalous conditions. */
	if (!mcheck_expected(cpu) && t2_mcheck_any_expected) {
		/*
		 * FUNKY: Received mcheck on a CPU and not
		 * expecting it, but another CPU is expecting one.
		 *
		 * Just dismiss it for now on this CPU...
		 */
#ifdef CONFIG_VERBOSE_MCHECK
		if (alpha_verbose_mcheck > 1) {
			printk("t2_machine_check(cpu%d): any_expected 0x%x -"
			       " (assumed) spurious -"
			       " code 0x%x\n", cpu, t2_mcheck_any_expected,
			       (unsigned int)mchk_header->code);
		}
#endif
		return;
	}

	if (!mcheck_expected(cpu) && !t2_mcheck_any_expected) {
		if (t2_mcheck_last_taken & (1 << cpu)) {
#ifdef CONFIG_VERBOSE_MCHECK
		    if (alpha_verbose_mcheck > 1) {
			printk("t2_machine_check(cpu%d): last_taken 0x%x - "
			       "unexpected mcheck - code 0x%x\n",
			       cpu, t2_mcheck_last_taken,
			       (unsigned int)mchk_header->code);
		    }
#endif
		    t2_mcheck_last_taken = 0;
		    mb();
		    return;
		} else {
			t2_mcheck_last_taken = 0;
			mb();
		}
	}

#ifdef CONFIG_VERBOSE_MCHECK
	if (alpha_verbose_mcheck > 1) {
		printk("%s t2_mcheck(cpu%d): last_taken 0x%x - "
		       "any_expected 0x%x - code 0x%x\n",
		       (mcheck_expected(cpu) ? "EX" : "UN"), cpu,
		       t2_mcheck_last_taken, t2_mcheck_any_expected,
		       (unsigned int)mchk_header->code);
	}
#endif

	process_mcheck_info(vector, la_ptr, "T2", mcheck_expected(cpu));
}
