pcireg_t ttwoga_conf_read(void *cpv, pcitag_t tag, int offset) { struct ttwoga_config *tcp = cpv; pcireg_t *datap, data; int b, d, f, ba; paddr_t addr; uint64_t old_hae3; if ((unsigned int)offset >= PCI_CONF_SIZE) return (pcireg_t) -1; pci_decompose_tag(&tcp->tc_pc, tag, &b, &d, &f); addr = b ? tag : ttwoga_make_type0addr(d, f); if (addr == (paddr_t)-1) return ((pcireg_t) -1); TTWOGA_CONF_LOCK(); alpha_mb(); old_hae3 = T2GA(tcp, T2_HAE0_3) & ~HAE0_3_PCA; T2GA(tcp, T2_HAE0_3) = old_hae3 | ((b ? 1UL : 0UL) << HAE0_3_PCA_SHIFT); alpha_mb(); alpha_mb(); datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(tcp->tc_sysmap->tsmap_conf_base | addr << 5UL | /* address shift */ (offset & ~0x03) << 5UL | /* address shift */ 0x3 << 3UL); /* 4-byte, size shift */ data = (pcireg_t)-1; if (!(ba = badaddr(datap, sizeof *datap))) data = *datap; alpha_mb(); T2GA(tcp, T2_HAE0_3) = old_hae3; alpha_mb(); alpha_mb(); alpha_pal_draina(); alpha_mb(); alpha_mb(); TTWOGA_CONF_UNLOCK(); #if 0 printf("ttwoga_conf_read: tag 0x%lx, reg 0x%x -> 0x%x @ %p%s\n", tag, offset, data, datap, ba ? " (badaddr)" : ""); #endif return (data); }
int badaddr_read(void *addr, size_t size, void *rptr) { struct mchkinfo *mcp = &curcpu()->ci_mcinfo; long rcpt; int rv; /* Get rid of any stale machine checks that have been waiting. */ alpha_pal_draina(); /* Tell the trap code to expect a machine check. */ mcp->mc_received = 0; mcp->mc_expected = 1; /* Read from the test address, and make sure the read happens. */ alpha_mb(); switch (size) { case sizeof (u_int8_t): rcpt = *(volatile u_int8_t *)addr; break; case sizeof (u_int16_t): rcpt = *(volatile u_int16_t *)addr; break; case sizeof (u_int32_t): rcpt = *(volatile u_int32_t *)addr; break; case sizeof (u_int64_t): rcpt = *(volatile u_int64_t *)addr; break; default: panic("badaddr: invalid size (%ld)", size); } alpha_mb(); alpha_mb(); /* MAGIC ON SOME SYSTEMS */ /* Make sure we took the machine check, if we caused one. */ alpha_pal_draina(); /* disallow further machine checks */ mcp->mc_expected = 0; rv = mcp->mc_received; mcp->mc_received = 0; /* * And copy back read results (if no fault occurred). */ if (rptr && rv == 0) { switch (size) { case sizeof (u_int8_t): *(volatile u_int8_t *)rptr = rcpt; break; case sizeof (u_int16_t): *(volatile u_int16_t *)rptr = rcpt; break; case sizeof (u_int32_t): *(volatile u_int32_t *)rptr = rcpt; break; case sizeof (u_int64_t): *(volatile u_int64_t *)rptr = rcpt; break; } } /* Return non-zero (i.e. true) if it's a bad address. */ return (rv); }