+
+/* ============ BEGIN temp til old PROMs are no longer supported =============
+ *
+ * The OS should not make direct access to the PROM flash memory. Access to
+ * this region must be serialized with a PROM lock. If SAL on one cpu is
+ * updating the FLASH error log at the same time another cpu is accessing the
+ * PROM, data corruption will occur.
+ *
+ * To solve the problem, all flash PROM access has been moved to SAL. Because
+ * not all systems will have instant PROM updates, we need to support a new OS
+ * running on a system with old PROMs.
+ *
+ * This code should be deleted after 1 OS/PROM release has occurred & the OS
+ * no longer supports downrev PROMs. (PROM support should be in the 3.50
+ * PROMs).
+ */
+#define SUPPORT_OLD_PROMS
+#ifdef SUPPORT_OLD_PROMS
+
+
+#define FIT_SIGNATURE 0x2020205f5449465ful
+
+/* Sub-regions determined by bits in Node Offset */
+#define LB_PROM_SPACE 0x0000000700000000ul /* Local LB PROM */
+
+/* Offset of PROM banner pointers in SAL A and SAL B */
+#define SAL_A_BANNER_OFFSET (1 * 16)
+#define SAL_B_BANNER_OFFSET (3 * 16)
+
+/* Architected IA64 firmware space */
+#define FW_BASE 0x00000000FF000000
+#define FW_TOP 0x0000000100000000
+
+static unsigned long
+convert_fw_addr(nasid_t nasid, unsigned long addr)
+{
+ /* snag just the node-relative offset */
+ addr &= ~0ul >> (63-35);
+ /* the pointer to SAL A is relative to IA-64 compatibility
+ * space. However, the PROM is mapped at a different offset
+ * in MMR space (both local and global)
+ */
+ addr += 0x700000000;
+ return GLOBAL_MMR_ADDR(nasid, addr);
+}
+
+static int
+valid_fw_addr(unsigned long addr)
+{
+ addr &= ~(1ul << 63); /* Clear cached/uncached bit */
+ return (addr >= FW_BASE && addr < FW_TOP);
+}
+
+static unsigned long *
+lookup_fit(int nasid)
+{
+ unsigned long *fitp;
+ unsigned long fit_paddr;
+ unsigned long *fit_vaddr;
+
+ fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
+ fit_paddr = readq(fitp);
+ fit_vaddr = (unsigned long *) convert_fw_addr(nasid, fit_paddr);
+ return fit_vaddr;
+}
+#endif /* SUPPORT_OLD_PROMS */
+/* ============ END temp til old PROMs are no longer supported ============= */
+
+static int
+get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
+ char *banner, int banlen)
+{
+ int ret;
+
+ ret = ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
+
+#ifdef SUPPORT_OLD_PROMS
+ /* The following is hack is temporary until PROMs are updated */
+ if (ret == SALRET_NOT_IMPLEMENTED) {
+ unsigned long *fitadr = lookup_fit(nasid);
+ int nentries;
+
+ if (readq(fitadr) != FIT_SIGNATURE) {
+ printk(KERN_WARNING "Unrecognized FIT signature");
+ return -2;
+ }
+
+ nentries = (unsigned int) (readq(fitadr + 1) & 0xffffff);
+ if (index >= nentries)
+ return -2;
+
+ fentry[0] = readq(fitadr + 2 * index);
+ fentry[1] = readq(fitadr + 2 * index + 1);
+ ret = 0;
+
+ if (banner && FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A) {
+ unsigned long i, qw, *bwp, *qwp;
+
+ banner[0] = '\0';
+ qw = fentry[0]; /* Address of SAL A */
+ if (!valid_fw_addr(qw))
+ return 0;
+
+ qw += SAL_A_BANNER_OFFSET;
+ qw = convert_fw_addr(nasid, qw);
+
+ qw = readq(qw); /* Address of banner */
+ if (!valid_fw_addr(qw))
+ return 0;
+ qw = convert_fw_addr(nasid, qw);
+ qwp = (unsigned long *) qw;
+ bwp = (unsigned long *) banner;
+ for (i=0; i<banlen/8; i++)
+ bwp[i] = qwp[i];
+ }
+ }
+#endif /* SUPPORT_OLD_PROMS */
+ return ret;
+}
+
+
+/*
+ * These two routines display the FIT table for each node.