+ int oldaddr = addr;
+ int v;
+ struct pte pte;
+
+ addr &= ~0xc0000000;
+ v = btop(addr);
+ switch (oldaddr&0xc0000000) {
+
+ case 0xc0000000:
+ case 0x80000000:
+ /*
+ * In system space get system pte. If
+ * valid or reclaimable then physical address
+ * is combination of its page number and the page
+ * offset of the original address.
+ */
+ if (v >= slr)
+ goto oor;
+ addr = ((long)(sbr+v)) &~ 0x80000000;
+ goto simple;
+
+ case 0x40000000:
+ /*
+ * In p1 space must not be in shadow region.
+ */
+ if (v < pcb.pcb_p1lr)
+ goto oor;
+ addr = pcb.pcb_p1br+v;
+ break;
+
+ case 0x00000000:
+ /*
+ * In p0 space must not be off end of region.
+ */
+ if (v >= pcb.pcb_p0lr)
+ goto oor;
+ addr = pcb.pcb_p0br+v;
+ break;
+ oor:
+ errflg = "address out of segment";
+ return (-1);
+ }
+ /*
+ * For p0/p1 address, user-level page table should
+ * be in kernel vm. Do second-level indirect by recursing.
+ */
+ if ((addr & 0x80000000) == 0) {
+ errflg = "bad p0br or p1br in pcb";
+ return (-1);
+ }
+ addr = vtophys(addr);
+simple:
+ /*
+ * Addr is now address of the pte of the page we
+ * are interested in; get the pte and paste up the
+ * physical address.
+ */
+ if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
+ errflg = "page table botch";
+ return (-1);
+ }
+ /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
+ if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
+ errflg = "page not valid/reclaimable";
+ return (-1);
+ }
+ return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));