Subversion Repositories f9daq

Rev

Rev 23 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. //-------------------------------------------------------------------------
  2. // WINNT driver for PCICC32 interface from ARW Elektronik, Germany --------
  3. // all around irq handling
  4. //
  5. // (c) 1999-2002 ARW Elektronik
  6. //
  7. // this source code is published under GPL (Open Source). You can use, redistrubute and
  8. // modify it unless this header   is not modified or deleted. No warranty is given that
  9. // this software will work like expected.
  10. // This product is not authorized for use as critical component in life support systems
  11. // wihout the express written approval of ARW Elektronik Germany.
  12. //
  13. // Please announce changes and hints to ARW Elektronik
  14. //
  15. // what                                            who          when
  16. // started                                         AR           01.08.1999
  17. // first release 1.0                                                       AR                   17.10.1999
  18. // IoConnectInterrupt, share vector now true       AR           04.03.2000
  19. // globalInterruptEnabledStatus() added            AR           24.02.2001
  20. // added IRQ handling                              AR           24.02.2001
  21. // added WITH_IRQS switch to switsch off irqs      AR           04.10.2001
  22. // changed making procedure (only VCC > 6.0)       AR           30.05.2002
  23. //
  24.  
  25. //-------------------------------------------------------------------------
  26. // INCLUDES
  27. //
  28. #define WITH_IRQS     // comment out for interrupt handling excludes
  29. // ACHTUNG TEST
  30.  
  31. //-------------------------------------------------------------------------
  32. // INCLUDES
  33. //
  34. #include <ntddk.h>
  35. #include <pcicc32_drv.h>
  36. #include <pcicc32_i.h>
  37. #include <pcicc32.h>
  38. #include <pcicc32_local.h>
  39.  
  40. //------------------------------------------------------------------------
  41. // DEFINES
  42. //
  43. #ifndef DWORD
  44. #define DWORD ULONG
  45. #endif
  46.  
  47. #ifndef WORD
  48. #define WORD USHORT
  49. #endif
  50.  
  51. //------------------------------------------------------------------------
  52. // GLOBALS
  53. //
  54.  
  55. //------------------------------------------------------------------------
  56. // FUNCTIONS
  57. //
  58.  
  59. //------------------------------------------------------------------------
  60. // enable and disable of interrupts
  61. //
  62. void globalInterruptEnable(PCIADA *pciada)
  63. {
  64. #ifdef WITH_IRQS
  65.    WRITE_REGISTER_USHORT(pciada->pwIntCSR, ENABLE_PCIADA_IRQS);
  66. #endif
  67. }
  68.  
  69. void globalInterruptDisable(PCIADA *pciada)
  70. {
  71.    WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
  72. }
  73.  
  74. unsigned short globalInterruptEnabledStatus(PCIADA *pciada)
  75. {
  76.         unsigned short wStatus;
  77.  
  78.         wStatus = READ_REGISTER_USHORT(pciada->pwIntCSR);
  79.  
  80.         if ((wStatus & ENABLE_PCIADA_IRQS) == ENABLE_PCIADA_IRQS)
  81.                 return 1;
  82.  
  83.         return 0;
  84. }
  85.  
  86. //------------------------------------------------------------------------
  87. // determine which interrupt and evaluates status if appropriate
  88. //
  89. static int evaluateIrqStatus(PCIADA *pciada, ULONG *dwIrqStatus)
  90. {
  91.         volatile USHORT  wCntrl;
  92.         int     result = 0;
  93.  
  94.         wCntrl = READ_REGISTER_USHORT(pciada->pwCntrl);
  95.     if (wCntrl & 0x100)   // pciada switched on ?
  96.         {
  97.                 volatile USHORT wIntCSR = READ_REGISTER_USHORT(pciada->pwIntCSR);
  98.  
  99.                 if (wIntCSR & 0x0040) // are the interrupts enabled?
  100.                 {
  101.                         if (wIntCSR & 0x20)
  102.                         {
  103.                                 // it's the pci interrupt # 2
  104.                                 globalInterruptDisable(pciada); // disable following interrupts
  105.  
  106.                                 // get current Cntrl - and clear interrupt
  107.                                 WRITE_REGISTER_USHORT(pciada->pwCntrl, (USHORT)(wCntrl & ~0x0100));     // disable
  108.                                 WRITE_REGISTER_USHORT(pciada->pwCntrl,  wCntrl);            // enable again
  109.                                
  110.                                 *dwIrqStatus = CONNECTION_TIMEOUT;
  111.  
  112.                                 result = 1;
  113.                         }
  114.  
  115.                         if (wIntCSR & 0x04)
  116.                         {
  117.                                 globalInterruptDisable(pciada); // disable following interrupts
  118.  
  119.                                 *dwIrqStatus =  READ_REGISTER_ULONG(_DWORD_NAF(pciada->pvVirtIfr, 28, 2, 0));
  120.  
  121.                                 // clear pending interrupt - LAM-FF
  122.                                 WRITE_REGISTER_USHORT(_WORD_NAF(pciada->pvVirtIfr, 28, 0, 16), 0);
  123.  
  124.                                 result = 1;
  125.                         }
  126.                 }
  127.         }
  128.  
  129.         return result;
  130. }
  131.  
  132. //------------------------------------------------------------------------
  133. // main interrupt handler function
  134. //
  135. static BOOLEAN irq_service(PKINTERRUPT Interrupt, PVOID ServiceContext)
  136. {
  137.         PCIADA *pciada = (PCIADA *)ServiceContext;
  138.  
  139. #ifndef WITH_IRQS
  140.         return FALSE;
  141. #endif
  142.  
  143.         if (!evaluateIrqStatus(pciada, &pciada->dwIrqStatus))
  144.         {
  145.                 // KdPrint(("Not my irq.\n"));
  146.                 return FALSE;
  147.         }
  148.  
  149.         // fire custom deffered procedure call
  150.         KeInsertQueueDpc(&pciada->kDPCobj, (PVOID)pciada, (PVOID)&pciada->dwIrqStatus);
  151.    
  152.         KdPrint(("irq_service(0x%08x)\n", pciada->dwIrqStatus));
  153.         return TRUE;
  154. }
  155.  
  156. //------------------------------------------------------------------------
  157. //  translate interrupt resources for PCIADAs to hardware independent ones
  158. //
  159. NTSTATUS PCICC32TranslateInterrupt(PDEVICE_OBJECT device_Obj)
  160. {
  161.         int              i;
  162.         NTSTATUS         result = STATUS_SUCCESS;
  163.         DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
  164.         int                              nPCIADAs = pDevExt->nPCIADAs;
  165.         PCIADA           *pciada;
  166.  
  167.     KdPrint(("PCICC32TranslateInterrupt()\n"));
  168.  
  169.         for (i = 0; i < nPCIADAs; i++)
  170.         {
  171.                 pciada = &pDevExt->pciada[i];
  172.  
  173.                 KdPrint(("In  - Bus:%d, IrqLine:%d\n", pciada->Bus, pciada->Irql));
  174.  
  175.                 if (pciada->Irql)
  176.                 {
  177.                         pciada->Vector = HalGetInterruptVector(PCIBus, pciada->Bus,
  178.                                 pciada->Irql, pciada->Vector,
  179.                                                 &pciada->Irql, &pciada->Affinity);
  180.  
  181.                         KdPrint(("Out - Irql:%d, Vector: %d, Affinity:%d\n", pciada->Irql, pciada->Vector, pciada->Affinity));
  182.  
  183.                 }
  184.                 else
  185.                         result = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
  186.         }
  187.  
  188.         return result;
  189. }
  190.  
  191. //------------------------------------------------------------------------
  192. //  connect service routines to all PCIADA interrupts
  193. //
  194. NTSTATUS PCICC32ConnectInterrupt(PDEVICE_OBJECT device_Obj)
  195. {
  196. #ifdef WITH_IRQS
  197.         int              i;
  198.         NTSTATUS         result = STATUS_SUCCESS;
  199.         DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
  200.         int                              nPCIADAs = pDevExt->nPCIADAs;
  201.         PCIADA           *pciada;
  202.  
  203.     KdPrint(("PCICC32ConnectInterrupt()\n"));
  204.  
  205.         // connect the interrupts to service routines
  206.         for (i = 0; i < nPCIADAs; i++)
  207.         {
  208.                 pciada = &pDevExt->pciada[i];
  209.  
  210.                 pciada->InterruptObject = NULL;
  211.  
  212.                 if (pciada->Vector)
  213.                 result = IoConnectInterrupt(&pciada->InterruptObject,
  214.                         irq_service,
  215.                                 (PVOID)pciada,
  216.                                         NULL,
  217.                                                 pciada->Vector,
  218.                                                         pciada->Irql,
  219.                                                                 pciada->Irql,
  220.                                                                         LevelSensitive,
  221.                                                                                 TRUE,
  222.                                                                                         pciada->Affinity,
  223.                                                                                                 FALSE);
  224.  
  225.                 KdPrint(("irq_service:%p, VirtVect:%d, Irql:%d, hIrql:%d, Aff:0x%08x, Status:0x%08x\n",
  226.                                 irq_service, pciada->Vector, pciada->Irql,
  227.                                         pciada->Irql, pciada->Affinity, result));
  228.  
  229.                 if (result != STATUS_SUCCESS)
  230.                         break;
  231.         }
  232.  
  233.         if (result == STATUS_SUCCESS)
  234.         {
  235.                 KdPrint(("PCICC32ConnectInterrupt() OK.\n"));
  236.         }
  237.  
  238.         return result;
  239. #else
  240.         return STATUS_SUCCESS;
  241. #endif
  242. }
  243.  
  244. //------------------------------------------------------------------------
  245. //  dis-connect service routines to all PCIADA interrupts
  246. //
  247. NTSTATUS PCICC32DisConnectInterrupt(PDEVICE_OBJECT device_Obj)
  248. {
  249. #ifdef WITH_IRQS
  250.         int              i;
  251.         DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
  252.         int                              nPCIADAs = pDevExt->nPCIADAs;
  253.         PCIADA           *pciada;
  254.  
  255.     KdPrint(("DisConnectInterrupt()\n"));
  256.  
  257.         // dis connect the interrupts to service routines
  258.         for (i = 0; i < nPCIADAs; i++)
  259.         {
  260.                 pciada = &pDevExt->pciada[i];
  261.  
  262.                 KdPrint(("IrqObj:0x%08x\n", pciada->InterruptObject));
  263.  
  264.                 if (pciada->InterruptObject)
  265.                 {
  266.                   IoDisconnectInterrupt(pciada->InterruptObject);
  267.                   pciada->InterruptObject = 0;
  268.                 }
  269.         }
  270. #endif
  271.  
  272.         return STATUS_SUCCESS;
  273. }
  274.  
  275.  
  276.