Index: linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c
===================================================================
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:279 @
 {
 	int ret;
 
-	ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port);
-	if (ret)
-		return ret;
+	//ret = request_irq(port->irq, ulite_isr, IRQF_NO_THREAD, "uartlite", port);
+	ret = request_any_context_irq(port->irq, ulite_isr, 0, "uartlite", port);
+	if (ret < 0){
+          printk(KERN_ERR "uartlite: request_any_context_irq returned with error %d\n",ret);
+                 return ret;
+        }
 
 	ret = readb(port->membase + ULITE_STATUS);
 
Index: linux-3.12.33-rt47-i386/drivers/uio/uio_scu3.c
===================================================================
--- linux-3.12.33-rt47-i386.orig/drivers/uio/uio_scu3.c	2015-09-04 11:32:09.480247712 +0200
+++ linux-3.12.33-rt47-i386/drivers/uio/uio_scu3.c	2015-09-15 17:03:57.388810674 +0200
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:159 @
 }
 static DEVICE_ATTR(scu3_id, S_IRUGO, show_id,0);
 
+
+
+
+
+/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */
+/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */
+/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
+
+DEFINE_RAW_SPINLOCK(scu3_vpic_lock);
+static int scu3_vpic_irq_base;
+
+static void mask_scu3_vpic_irq(struct irq_data *data)
+{
+  unsigned long flags;
+//   printk(KERN_INFO PFX "mask_scu3_vpic_irq irq=0x%x hwirq=0x%lx mask=0x%x chip=0x%p chip_data=0x%p\n"
+//          ,data->irq
+//          ,data->hwirq
+//          ,data->mask
+//          ,data->chip
+//          ,data->chip_data
+//          );
+  raw_spin_lock_irqsave(&scu3_vpic_lock, flags);
+  SCU3_INT_FRG_REG &= ~data->mask;
+  raw_spin_unlock_irqrestore(&scu3_vpic_lock, flags);
+
+}
+static void unmask_scu3_vpic_irq(struct irq_data *data)
+{
+  unsigned long flags;
+//   printk(KERN_INFO PFX "unmask_scu3_vpic_irq irq=0x%x hwirq=0x%lx mask=0x%x chip=0x%p chip_data=0x%p\n"
+//          ,data->irq
+//          ,data->hwirq
+//          ,data->mask
+//          ,data->chip
+//          ,data->chip_data
+//          );
+  raw_spin_lock_irqsave(&scu3_vpic_lock, flags);
+  SCU3_INT_FRG_REG |= data->mask;
+  raw_spin_unlock_irqrestore(&scu3_vpic_lock, flags);
+}
+static struct irq_chip scu3_vpic_chip __read_mostly = {
+	.name		= "scu3-vpic",
+	.irq_mask	= mask_scu3_vpic_irq,
+	.irq_unmask	= unmask_scu3_vpic_irq,
+};
+
+
+// Die Instanz des vpic besteht aus drei allocierten Interruptnummern
+// und deren irq_desc-Datenstrukturen.
+// Die  scu3_vpic_irq_base enthält den Anfang des Nummernbereichs
+int init_scu3_vpic(void)
+{
+    scu3_vpic_irq_base = irq_alloc_descs(-1, 0, 3, 0);
+    if(scu3_vpic_irq_base < 0) {
+      printk(KERN_ERR PFX "irq_alloc_descs failed %d\n",scu3_vpic_irq_base);
+      return -1;
+    }
+    printk(KERN_INFO PFX "irq_alloc_descs from: %d\n",scu3_vpic_irq_base);
+    return 0;
+}
+// Die einzelnen virt. irqs werden als nested_thread-irqs initialisiert.
+// 'vpic_irq' ist der relative offset ab scu3_vpic_irq_base 0..2
+// 'mask'     ist die hw-bit-maske fur das SCU3_INT_FRG_REG
+int init_scu3_vpic_irq(int vpic_irq, unsigned mask)
+{
+  int              ret;
+  struct irq_desc *desc;
+  int              irq = scu3_vpic_irq_base + vpic_irq;
+
+  ret = irq_set_chip(irq, &scu3_vpic_chip);
+  if(ret) {
+    printk(KERN_ERR PFX "irq_set_chip failed %d\n",ret);
+    return -1;
+  }
+
+  // /home/husteret/build/SYS/SfcLeanOs-RT/trunk/Src/kernel/Objs/i486-linux/linux-3.12.33-rt47-x86_64/drivers/gpio/gpio-davinci.c:442
+  //irq_set_handler(irq, handle_simple_irq);
+
+  // ../gpio/gpio-adnp.c:420
+  // set thread_fn without extra thread
+  // !!!! uartlite must use request_any_context_irq instead of request_irq
+  // !!!! request_any_context_irq delivers ret-val 1 != 0 !!!
+  irq_set_nested_thread(irq, true);
+  irq_set_noprobe(irq);
+  //irq_settings_set_nothread(desc);
+
+  desc = irq_to_desc(irq);
+  irq_desc_get_irq_data(desc)->mask = mask; //set the bitmask for
+  return irq;
+}
+
+/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */
+/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */
+/* Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC Virtual PIC */
+
+
+
 static irqreturn_t uio_scu3_handler(int irq, struct uio_info *dev_info)
 {
-  u16 req=SCU3_INT_STATUS_REG & MY_INTS; //INT_MASK;
+  u16 allreq = SCU3_INT_STATUS_REG;
 
-  if(!req)   /* shared irq? */
+  if(allreq & SCU3_INT_SER_1) handle_nested_irq(scu3_vpic_irq_base+0);
+  if(allreq & SCU3_INT_SER_2) handle_nested_irq(scu3_vpic_irq_base+1);
+  if(allreq & SCU3_INT_SER_3) handle_nested_irq(scu3_vpic_irq_base+2);
+
+  if((allreq & MY_INTS)==0)   /* shared irq? */
   {
+    // !!!!!!!! Achtung !!!!!!
+    // Wir muessen hier IRQ_NONE liefern damit uio den userhandler nicht aufruft.
+    // Aus Sicht des Kernels ist das aber sehr wahrsch. falsch weil der int durch
+    // eine sio ausgeloest wurde, d.h. es wurde etwas ge-HANDLED
+    // Dies ist hoffenlich nicht so tragisch weil der kernel dank vpic keinen shared-int
+    // behandeln muss
     return IRQ_NONE;
   }
   SCU3_INT_FRG_REG &= ~(MY_INTS); //INT_OFF_MASK;
   return IRQ_HANDLED;
 
-// old
-// static irqreturn_t uio_scu3_handler(int irq, struct uio_info *dev_info)
-// {
-//   u16 req=((SCU3_INT_STATUS_REG & 0xff) << 8) | (SCU3_FI_STATUS_REG & 0xff);
-//
-//   if(!req)   /* shared irq? */
-//   {
-//     return IRQ_NONE;
-//   }
-//   //SCU3_FI_FRG_REG  = 0; nicht sperren damit weiterhin alle flanken sichtbar
-//   SCU3_FI_EOI_REG  = 0xff; //Fast Input Ints mit EOI beseitigen
-//   SCU3_INT_FRG_REG = 0; //Hier gehts nicht mit EOI weil die Quellen noch anstehen
-//   return IRQ_HANDLED;
-/* Fast IO register
-Achtung!! see Fast_input_bit.vhd
-1. komisches interupt-Sperrverhalten.
-2. kein Intrequest Register
-
-
-1. Beim sperren der ints mit SCU3_FI_FRG_REG=0 wird die Int-erkennung halb
-ausgeschaltet. Zwischenzeitlich anfallende Ints werden bei der wiederfreigabe
-genau dann gemeldet wenn der Pegel vor der Sperre ungleich dem Pegel hinter der
-Sperre ist.
-T              1    2             3   4   5           6   7 8 9
-INPUT_REG    --______----    -----____----------   ---____--_______
-
-               |    |             |                   |
-               v    v             v                   v
-
-FRG_REG     _------------    -------______---      -----______-
-
-               |    |             | |     |           | |
-               v    v             v v     v           v v     kein int
-
-STATUS_REG   __i--__i--__    _____i-______i---__   ___i-___________
-                  ^    ^                      ^
-EOI_REG      _____-____-_    _________________-_
-
-Im Bsp. wird also zum Zeitpunkt 5 ein Int ausgeloest, zum Zeitpunkt 9
-jedoch nicht, weil der Pegel vor der Int-Sperre einmal ungleich (T=5) und beim
-zweiten Mal identisch (T=9) mit dem aktuellen Pegel ist.
-
-Dies fuehrt im schlimmsten Fall dazu, dass die Software auf dem falschen Pegel
-festklemmt. Im Bsp. erkennt die Pollingloop die Pegel bei T=6 u. T=7, aber
-T=8 kommt ausgerechnet in dem Zeitraum zwischen Pollingloop Ende und
-Int-Freigabe.
-Abhilfe: FRG_REG nicht verwenden. (Lediglich zur Komplettsperre)
-
-
-2. Das STATUS_REG ist nur dann verfuegbar wenn das FRG_REG=1 und solange noch
-kein EOI ausgeloest wurde.
-*/
 }
 
+
 static struct uio_info     *uinfo2 = 0;
 static dma_addr_t       dmem_baddr = 0; //bus addr
 static void            *dmem_vaddr = 0;
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:372 @
   printk(KERN_INFO PFX "sio_init %d: pres %p\n",
            num,&uart_res);
 
-//   pres[0].flags = IORESOURCE_MEM;
-//   pres[0].start = base;
-//   pres[0].end   = base + 16;
-//   pres[1].flags = IORESOURCE_IRQ;
-//   pres[1].start = irq;
-//   pres[1].end   = irq;
-
-  SCU3_INT_FRG_REG  |= intmsk; //sio_int_masks[num];
+  //SCU3_INT_FRG_REG  |= intmsk; //sio_int_masks[num];
 
 //   pdev = platform_device_register_simple("uartlite", num, pres, 2);
   pdev = platform_device_register_simple("uartlite", num,
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:384 @
   {
     printk(KERN_ERR PFX "Unable to register platform device '%s'#%d: err=%d\n",
            "uartlite", num, ret);
-    SCU3_INT_FRG_REG  &= ~intmsk;//sio_int_masks[num];
+    //SCU3_INT_FRG_REG  &= ~intmsk;//sio_int_masks[num];
   }
   else
   {
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:437 @
   printk(KERN_INFO PFX "1 pdev->irq = %d\n",pdev->irq);
   //info->irq_flags            = IRQF_DISABLED | IRQF_SHARED;
   // see below: SCU3_INT_FRG_REG = 0;
-  info->irq_flags            = IRQF_SHARED;
+  info->irq_flags            = 0; //IRQF_SHARED;
   info->handler              = uio_scu3_handler;
 
   mmio_start = pci_resource_start(pdev, 0); //resource_size_t = phys_addr_t = u64/u32
@ linux-3.12.33-rt47-i386/drivers/tty/serial/uartlite.c:523 @
     printk(KERN_ERR PFX "bad uio_register_device\n");
     goto out_err;
   }
-  printk(KERN_INFO PFX "sio_init\n");
   initState|=8; //device registered
 
+  printk(KERN_INFO PFX "sio_init\n");
+  /* vpic   */
+  do{ //allow early exit
+    struct Tab {unsigned ofs,mask,msk2;};
+    struct Tab sioResrc[]={
+      {0x500000,SCU3_INT_SER_1,0x10},
+      {0x600000,SCU3_INT_SER_2,0x20},
+      {0xf00000,SCU3_INT_SER_3,0x40},
+    };
+    int i;
+    if( init_scu3_vpic() < 0) break;
 
-  if(sio_init(0, mmio_start+0x500000, pci_irq,SCU3_INT_SER_1)==0)
-    initState|=0x10; //sio0 initialized
-  if(sio_init(1, mmio_start+0x600000, pci_irq,SCU3_INT_SER_2)==0)
-    initState|=0x20; //sio1 initialized
-  if(sio_init(2, mmio_start+0xf00000, pci_irq,SCU3_INT_SER_3)==0)
-    initState|=0x40; //sio2 initialized
+    for(i=0;i<3;i++){
+      int irq = init_scu3_vpic_irq(i,sioResrc[i].mask);
+      if( irq < 0) break;
+
+      // !!!! uartlite must use request_any_context_irq instead of request_irq
+      // !!!! request_any_context_irq delivers ret-val 1 != 0 !!!
+      if(sio_init(i, mmio_start+sioResrc[i].ofs, irq,0)==0)
+        initState|=sioResrc[i].msk2; //sio0 initialized
+    }
+  }while(0);
 
   if(dmem_init(pdev)==0)
     initState|=0x80; //dma memory