+ flush_icache_range(ebase + 0x200, ebase + 0x204);
+ }
+ return (void *)old_handler;
+}
+
+#ifdef CONFIG_CPU_MIPSR2
+/*
+ * MIPSR2 shadow register set allocation
+ * FIXME: SMP...
+ */
+
+static struct shadow_registers {
+ /*
+ * Number of shadow register sets supported
+ */
+ unsigned long sr_supported;
+ /*
+ * Bitmap of allocated shadow registers
+ */
+ unsigned long sr_allocated;
+} shadow_registers;
+
+static void mips_srs_init(void)
+{
+#ifdef CONFIG_CPU_MIPSR2_SRS
+ shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
+ printk(KERN_INFO "%d MIPSR2 register sets available\n",
+ shadow_registers.sr_supported);
+#endif
+ shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */
+}
+
+int mips_srs_max(void)
+{
+ return shadow_registers.sr_supported;
+}
+
+int mips_srs_alloc(void)
+{
+ struct shadow_registers *sr = &shadow_registers;
+ int set;
+
+again:
+ set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
+ if (set >= sr->sr_supported)
+ return -1;
+
+ if (test_and_set_bit(set, &sr->sr_allocated))
+ goto again;
+
+ return set;
+}
+
+void mips_srs_free(int set)
+{
+ struct shadow_registers *sr = &shadow_registers;
+
+ clear_bit(set, &sr->sr_allocated);
+}
+
+static void *set_vi_srs_handler(int n, void *addr, int srs)
+{
+ unsigned long handler;
+ unsigned long old_handler = vi_handlers[n];
+ u32 *w;
+ unsigned char *b;
+
+ if (!cpu_has_veic && !cpu_has_vint)
+ BUG();
+
+ if (addr == NULL) {
+ handler = (unsigned long) do_default_vi;
+ srs = 0;
+ } else
+ handler = (unsigned long) addr;
+ vi_handlers[n] = (unsigned long) addr;
+
+ b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING);
+
+ if (srs >= mips_srs_max())
+ panic("Shadow register set %d not supported", srs);
+
+ if (cpu_has_veic) {
+ if (board_bind_eic_interrupt)
+ board_bind_eic_interrupt (n, srs);
+ } else if (cpu_has_vint) {
+ /* SRSMap is only defined if shadow sets are implemented */
+ if (mips_srs_max() > 1)
+ change_c0_srsmap (0xf << n*4, srs << n*4);