Subversion Repositories f9daq

Rev

Rev 19 | Rev 46 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. //-------------------------------------------------------------------------
  2. // WINNT driver for PCIVME interface from ARW Elektronik, Germany ---------
  3. // the main body of the driver
  4. //
  5. // (c) 1999-2004 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. // $Log: pcivme_drv.c,v $
  16. // Revision 1.3  2004/07/24 07:07:26  klaus
  17. // Update copyright to 2004
  18. //
  19. //
  20. // what                                            who          when
  21. // started                                         AR           15.06.1999
  22. // first release 1.0                               AR           17.10.1999
  23. // fixed error in PLX9050Bug                       AR           28.02.2000
  24. // PLX9050Bugfix bug fixed                         AR           03.03.2000
  25. // PCICC32 CAMAC Interface conflict solved         AR           03.03.2000
  26. // Version 1.1 released                            AR           03.03.2000
  27. // register all used resources, the idle too       AR           25.11.2001
  28. // changed resource allocation caused by WIN2000   AR           08.06.2002
  29. //
  30.  
  31. //-------------------------------------------------------------------------
  32. // INCLUDES
  33. //
  34.  
  35. #include <ntddk.h>
  36. #include <devioctl.h>
  37. #include <pcivme_drv.h>
  38. #include <pcivme_v.h>
  39. #include <pcivme_io.h>
  40. #include <pcivme_i.h>
  41. #include <pcivme.h>
  42. #include <pciif.h>
  43. #include <pcivme_fifo.h>
  44.  
  45. //------------------------------------------------------------------------
  46. // DEFINES
  47. //
  48. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
  49.  
  50. #ifndef DWORD
  51. #define DWORD ULONG
  52. #endif
  53.  
  54. #ifndef WORD
  55. #define WORD USHORT
  56. #endif
  57.  
  58. #define CTL_INDEX(x) ((x >> 2) & 0x7FF)  // get user control code as index
  59. #define IRQ_LIST_LENGTH 128     // max count of irqs in FIFO for each file_obj
  60.  
  61. #define RESOURCE_ENTRY_COUNT 6          // WIN2000 forces to claim all entries
  62.  
  63. #define DOS_DEVICE_NAME L"\\DosDevices\\PCIVME:"
  64.  
  65. //------------------------------------------------------------------------
  66. // GLOBALS
  67. //
  68.  
  69. //------------------------------------------------------------------------
  70. // FUNCTIONS
  71. //
  72.  
  73. //------------------------------------------------------------------------
  74. // exchange the pointer to Bus Error
  75. //
  76. PBOOLEAN ExchangePointer(PBOOLEAN *current, PBOOLEAN next)
  77. {
  78.         PBOOLEAN pb;
  79.  
  80.         pb       = *current;
  81.         *current = next;
  82.  
  83.         return pb;
  84. }
  85.  
  86. //------------------------------------------------------------------------
  87. // get the vmemm number out of the filename
  88. //
  89. NTSTATUS InterpreteFileName(PCHAR name, int *nVmemm)
  90. {
  91.         char *ptr = name;
  92.     char *n   = "vmemm";
  93.         int  h = -1;  // high part
  94.         int  l = -1;  // low part
  95.  
  96.         if (*ptr == '\\') ptr++; // jump over leading ...
  97.  
  98.     while (*n)                           // compare the basename
  99.           if (*n == tolower(*ptr))     
  100.           {
  101.                   n++;
  102.                   ptr++;
  103.           }
  104.           else
  105.                   return STATUS_NO_SUCH_FILE;
  106.  
  107.         h = *ptr - '0';                  // get the number
  108.         ptr++;
  109.         l = *ptr - '0';
  110.  
  111.         if (*ptr == 0)                   // still over the end ??
  112.         {
  113.                 l = h;
  114.                 h = 0;
  115.         }
  116.         else
  117.           ptr++;
  118.  
  119.         if ((h < 0) || (l < 0) || (*ptr != 0))  // anything wrong ??
  120.                   return STATUS_NO_SUCH_FILE;
  121.  
  122.         *nVmemm = (h * 10) + l;  // calculate number
  123.  
  124.         if (*nVmemm >= PCIVME_MAX_VMEMM) // out of range ??
  125.                   return STATUS_NO_SUCH_FILE;
  126.  
  127.         return STATUS_SUCCESS;
  128. }
  129.  
  130. //------------------------------------------------------------------------
  131. // the ultimate driver unload
  132. VOID PCIVMEUnload(PDRIVER_OBJECT driverObj)
  133. {
  134.         int              i;
  135.         UNICODE_STRING symbol_name;
  136.         if (!driverObj->DeviceObject) {
  137.                 KdPrint(("PCIVMEUnload() DeviceObject does not exist \n"));
  138.                 return;
  139.         }
  140.         DEVICE_EXT *ext = (DEVICE_EXT*)(driverObj->DeviceObject->DeviceExtension);
  141.         int         nPCIADAs = ext->nPCIADAs;
  142.         PCIADA      *pciada;
  143.  
  144.         KdPrint(("PCIVMEUnload() InitState %d \n", ext->nInitState ));
  145.  
  146.         //if (ext->LowerDeviceObject) IoDetachDevice(ext->LowerDeviceObject);
  147.         //IoDeleteDevice(driverObj->DeviceObject);
  148.         if (ext->nInitState!=100) return;
  149.  
  150.         switch (ext->nInitState)
  151.         {
  152.                 case 8:
  153.                 case 7:
  154.                         // stop interrupts and shut off
  155.                         PCIVMEDeInitPCIADAs(driverObj->DeviceObject);
  156.                         PCIVMEDisConnectInterrupt(driverObj->DeviceObject);
  157.  
  158.                         // remove interrupt lists
  159.                         for (i = 0; i < nPCIADAs; i++)
  160.                         {
  161.                                 pciada = &ext->pciada[i];
  162.  
  163.                                 // removeQueueFromList(...)
  164.                                 while (IsListEmpty(&pciada->IrqListList) == FALSE)
  165.                                 {
  166.                                         PLIST_ENTRY pList;
  167.                                         FIFO_LIST   *next;
  168.                                
  169.                                         KdPrint(("RemoveHeadList(0x%08x)\n", &pciada->IrqListList));
  170.                                         pList = RemoveHeadList(&pciada->IrqListList);
  171.                                         next  = CONTAINING_RECORD(pList, FIFO_LIST, entry);
  172.  
  173.                                         ExFreePool((PVOID)next);
  174.                                 }
  175.                         }
  176.                 case 6:
  177.                         // InitializeIRPQueue has no counterpart
  178.                 case 5:
  179.                         // KeInitializeDpc has no counterpart
  180.                 case 4:
  181.                         // release io spaces
  182.                         for (i = 0; i < nPCIADAs; i++)
  183.                         {
  184.                                 pciada = &ext->pciada[i];
  185.  
  186.                                 if (pciada->pvVirtLcr != NULL)
  187.                                         MmUnmapIoSpace(pciada->pvVirtLcr, LCR_SPACE);
  188.                                 if (pciada->pvVirtIfr != NULL)
  189.                                         MmUnmapIoSpace(pciada->pvVirtIfr, IFR_SPACE);
  190.                         }
  191.                 case 3:
  192.                         // HalGetInterruptVector has no counterpart
  193.                 case 2:
  194.                         // HalTranslateBusAddress has no counterpart
  195.                 case 1:
  196.                         // PCIVMEFreeResources(driverObj->DeviceObject); // not used in pnp
  197.                 default:
  198.                 case 0:
  199.                         RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
  200.  
  201.                         // delete the symbolicLink in the registry
  202.                         IoDeleteSymbolicLink( &symbol_name);
  203.  
  204.                         // delete the deviceObject
  205.                         if (ext->LowerDeviceObject) IoDetachDevice(ext->LowerDeviceObject);
  206.                         IoDeleteDevice(driverObj->DeviceObject);
  207.         }
  208.        
  209.         KdPrint(("PCIVMEUnload() OK.\n"));
  210. }
  211.  
  212.  
  213. //------------------------------------------------------------------------
  214. // called at CreateFile()
  215. NTSTATUS PCIVMEOpen(PDEVICE_OBJECT deviceObj, PIRP Irp)
  216. {
  217.         NTSTATUS result = STATUS_SUCCESS;
  218.     ANSI_STRING name;
  219.     int nVmemm;
  220.         int i;
  221.         DEVICE_EXT      *pDevExt = (DEVICE_EXT *)(deviceObj->DeviceExtension);
  222.         PCIADA      *pciada;
  223.         FILE_OBJ        *file_obj = (FILE_OBJ *)NULL;
  224.  
  225.         name.Buffer = NULL;
  226.     name.MaximumLength = 80;
  227.  
  228.         result = RtlUnicodeStringToAnsiString(&name, &(Irp->Tail.Overlay.OriginalFileObject->FileName), TRUE);
  229.         if (result != STATUS_SUCCESS) goto fin;
  230.  
  231.         result = InterpreteFileName(name.Buffer, &nVmemm);
  232.     if (result != STATUS_SUCCESS) goto fin;
  233.  
  234.     KdPrint(("PCIVMEOpen(%d)\n", nVmemm));
  235.         RtlFreeAnsiString(&name);
  236.  
  237.     file_obj = (FILE_OBJ *)ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJ),'nepo');
  238.         if (file_obj == (FILE_OBJ *)NULL)
  239.         {
  240.                 result = STATUS_NO_MEMORY;
  241.                 goto fin;
  242.         }
  243.  
  244.         file_obj->uwAssociatedVMEMM = (USHORT) nVmemm;
  245.         file_obj->bAddressModifier  = 0x39;
  246.         file_obj->bAccessType       = BYTE_ACCESS;
  247.         file_obj->bIncrement        = BYTE_ACCESS; // increments each byte
  248.         file_obj->dwAccessBase      = 0;           // normal setting for all but extended
  249.  
  250.         file_obj->bQueueIrq                     = FALSE;
  251.         result = InitializeFIFO(IRQ_LIST_LENGTH, &file_obj->pIrqListHandle);
  252.         if (result != STATUS_SUCCESS) goto fin;
  253.  
  254.     Irp->Tail.Overlay.OriginalFileObject->FsContext = (PVOID)file_obj;
  255.  
  256.         result = PCIVMEScanVMEMM(deviceObj);
  257.         if (result != STATUS_SUCCESS) goto fin;
  258.  
  259.         for (i = 0; i < pDevExt->nPCIADAs; i++)
  260.         {
  261.           pciada = &pDevExt->pciada[i];
  262.  
  263.           if (pciada->wModuleNumber == nVmemm)
  264.           {
  265.                   pDevExt->vmemm[nVmemm] = pciada; // create association
  266.                   pciada->dwLinkCount++;
  267.                   break;
  268.           }
  269.         }
  270.  
  271.         if (i >= pDevExt->nPCIADAs)
  272.         {
  273.                 result = STATUS_NO_SUCH_FILE;
  274.                 goto fin;
  275.         }
  276.  
  277.         fin:
  278.         Irp->IoStatus.Status = result;
  279.         Irp->IoStatus.Information = 0;
  280.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  281.  
  282.         // be careful when releasing allocated memory !
  283.         if (result != STATUS_SUCCESS)
  284.                 if (file_obj != (FILE_OBJ *)NULL)
  285.                         if (file_obj->pIrqListHandle != (PVOID)NULL)
  286.                                 DestroyFIFO(file_obj->pIrqListHandle);
  287.  
  288.         return result;
  289. }
  290.  
  291. //------------------------------------------------------------------------
  292. // called at close()
  293. NTSTATUS PCIVMEClose(PDEVICE_OBJECT deviceObj, PIRP Irp)
  294. {
  295.         DEVICE_EXT      *pDevExt  = (DEVICE_EXT *)(deviceObj->DeviceExtension);
  296.         FILE_OBJ    *file_obj = (FILE_OBJ *)NULL;
  297.         PCIADA      *pciada;                   
  298.  
  299.         file_obj = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  300.  
  301.     KdPrint(("PCIVMEClose(%d)\n", file_obj->uwAssociatedVMEMM));
  302.  
  303.         if (file_obj != (FILE_OBJ *)NULL)
  304.         {
  305.                 pciada = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  306.                 pciada->dwLinkCount--;
  307.  
  308.                 // remove the ListEntry(s) associated with this path
  309.         removeQueueFromList(file_obj, pciada);
  310.  
  311.             // empty and remove the interrupt queue (if there is anything stored)
  312.                 DestroyFIFO(file_obj->pIrqListHandle);
  313.                
  314.                 ExFreePool(file_obj);
  315.                 Irp->Tail.Overlay.OriginalFileObject->FsContext = (FILE_OBJ *)NULL;
  316.         }
  317.  
  318.         KdPrint(("PCIVMEClose OK\n"));
  319.  
  320.     Irp->IoStatus.Status = STATUS_SUCCESS;
  321.         Irp->IoStatus.Information = 0;
  322.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  323.  
  324.         return STATUS_SUCCESS;
  325. }
  326.  
  327. //------------------------------------------------------------------------
  328. // called at
  329. NTSTATUS PCIVMEShutdown(PDEVICE_OBJECT deviceObj, PIRP  irp  )
  330. {
  331.         UNREFERENCED_PARAMETER(irp);
  332.  
  333.     KdPrint(("PCIVMEShutdown()\n"));
  334.  
  335.         // deinit interfaces and interrupts
  336.         PCIVMEDeInitPCIADAs(deviceObj);
  337.  
  338.     KdPrint(("PCIVMEShutdown() OK\n"));
  339.  
  340.         return STATUS_SUCCESS;
  341. }
  342.  
  343. //------------------------------------------------------------------------
  344. // called at ioctl()
  345. NTSTATUS PCIVMEDeviceControl(PDEVICE_OBJECT deviceObj, PIRP Irp)
  346. {
  347.         PIO_STACK_LOCATION IrpStack;
  348.         int   nIndex;
  349.  
  350.         IrpStack  = IoGetCurrentIrpStackLocation(Irp);
  351.         nIndex    = CTL_INDEX(IrpStack->Parameters.DeviceIoControl.IoControlCode);
  352.  
  353.     KdPrint(("PCIVMEDeviceControl(%d / 0x%08x)\n", nIndex, Irp->Tail.Overlay.OriginalFileObject));
  354.  
  355.         if (nIndex > CTL_INDEX(PCIVME_LAST_CTL_CODE))
  356.         {
  357.                 Irp->IoStatus.Status      = STATUS_UNSUCCESSFUL;
  358.                 Irp->IoStatus.Information = 0;
  359.                 IoCompleteRequest(Irp,IO_NO_INCREMENT);
  360.  
  361.         KdPrint(("PCIVMEDeviceControl() FAIL.\n"));
  362.  
  363.                 return STATUS_UNSUCCESSFUL;
  364.         }
  365.  
  366.         return ioctl[nIndex](deviceObj, Irp, IrpStack);
  367. }
  368.  
  369.  
  370. //------------------------------------------------------------------------
  371. // called at read()
  372. NTSTATUS PCIVMERead(PDEVICE_OBJECT device_Obj, PIRP Irp)
  373. {
  374.         NTSTATUS        Status        = STATUS_SUCCESS;
  375.         PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  376.         PVOID           pOutputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
  377.         LARGE_INTEGER *fileOffset = (LARGE_INTEGER *)&Irp->Tail.Overlay.OriginalFileObject->CurrentByteOffset;
  378.         FILE_OBJ        *file_obj           = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  379.         DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
  380.   PCIADA      *pciada             = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  381.         register ULONG Address  = IrpStack->Parameters.Read.ByteOffset.LowPart  + file_obj->dwAccessBase;  
  382.         ULONG storeLength                   = 0;
  383.         PBOOLEAN pbPrevBusError;
  384.  
  385.         KdPrint(("PCIVMERead(%d)\n", file_obj->uwAssociatedVMEMM));
  386.  
  387.         // do here in between what has to be done -----------------
  388.   if (Address & file_obj->dwAddressMask)     // don't do unaligned transfers
  389.                 Status = STATUS_DATATYPE_MISALIGNMENT;
  390.         else
  391.         {
  392.                 register ULONG Length = IrpStack->Parameters.Read.Length;    
  393.                 register ULONG blockLength;
  394.                 register ULONG pageAddress;
  395.                 register ULONG toNextPage;
  396.                 KIRQL              oldIrql;
  397.  
  398.                 Length     &= ~file_obj->dwAddressMask; // align to integer increments
  399.                 storeLength = Length;
  400.                
  401.                 // lock other users out
  402.                 KeAcquireSpinLock(&pciada->AccessLock, &oldIrql);
  403.  
  404.                 // check for modifier
  405.                 if (pciada->bModifier != file_obj->bAddressModifier)
  406.                 {
  407.                         WRITE_REGISTER_UCHAR(pciada->pbModifier, file_obj->bAddressModifier);
  408.                         pciada->bModifier = file_obj->bAddressModifier;
  409.                 }
  410.                
  411.                 // do the read ---
  412.                 file_obj->bBusError = FALSE;
  413.                 pbPrevBusError = ExchangePointer(&pciada->pbBusError, &file_obj->bBusError);
  414.                 while (Length)
  415.                 {
  416.                         pageAddress = Address & ~VME_ADR_MASK;
  417.                         if (pageAddress != pciada->dwVMEPage)
  418.                         {
  419.                                 WRITE_REGISTER_ULONG(pciada->pdwVMEAdr, pageAddress);
  420.                                 pciada->dwVMEPage = pageAddress;
  421.                         }
  422.  
  423.                         toNextPage  = (pageAddress + VME_ADR_MASK + 1) - Address;
  424.                         blockLength = (toNextPage < Length) ? toNextPage : Length;
  425.  
  426.                         KdPrint(("Address 0x%08x, blockLength %d, Length %d\n",
  427.                                                                                 Address, blockLength, Length));
  428.  
  429.                         file_obj->fRead(pOutputBuffer , blockLength, (PVOID)((PUCHAR)pciada->pvVME + (Address & VME_ADR_MASK)));
  430.  
  431.                         Length  -= blockLength;
  432.                         Address += blockLength;
  433.                         pOutputBuffer = (PVOID)((PUCHAR)pOutputBuffer + blockLength);
  434.                 }
  435.  
  436.                 // release the lock
  437.                 KeReleaseSpinLock(&pciada->AccessLock, oldIrql);
  438.                 ExchangePointer(&pciada->pbBusError, pbPrevBusError);
  439.                 if (file_obj->bBusError) Status = STATUS_ACCESS_VIOLATION;
  440.  
  441.             if (file_obj->bIncrement)  // only when increment to next is on
  442.                         *fileOffset =
  443.                                 RtlLargeIntegerAdd(*fileOffset, RtlConvertUlongToLargeInteger(storeLength));
  444.         }
  445.         // do here in between what has to be done end -------------
  446.  
  447.         Irp->IoStatus.Status      = Status;  
  448.         Irp->IoStatus.Information = storeLength;  
  449.         IoCompleteRequest(Irp,IO_NO_INCREMENT);  
  450.  
  451.     KdPrint(("PCIVMERead(), Status = 0x%08x\n", Status));
  452.  
  453.         return Status;
  454. }
  455.  
  456.  
  457. //------------------------------------------------------------------------
  458. // called at write()
  459. NTSTATUS PCIVMEWrite(PDEVICE_OBJECT device_Obj, PIRP Irp)
  460. {
  461.         NTSTATUS        Status        = STATUS_SUCCESS;
  462.         PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  463.         PVOID           pInputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
  464.         LARGE_INTEGER *fileOffset = (LARGE_INTEGER *)&Irp->Tail.Overlay.OriginalFileObject->CurrentByteOffset;
  465.         FILE_OBJ        *file_obj           = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  466.         DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
  467.   PCIADA      *pciada             = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  468.         register ULONG Address  = IrpStack->Parameters.Write.ByteOffset.LowPart + file_obj->dwAccessBase;  
  469.         ULONG storeLength                   = 0;
  470.         PBOOLEAN pbPrevBusError;
  471.  
  472.         KdPrint(("PCIVMEWrite(%d)\n", file_obj->uwAssociatedVMEMM));
  473.  
  474.         // do here in between what has to be done -----------------
  475.   if (Address & file_obj->dwAddressMask)     // don't do unaligned transfers
  476.                 Status = STATUS_DATATYPE_MISALIGNMENT;
  477.         else
  478.         {
  479.                 register ULONG Length = IrpStack->Parameters.Write.Length;    
  480.                 register ULONG blockLength;
  481.                 register ULONG pageAddress;
  482.                 register ULONG toNextPage;
  483.                 KIRQL              oldIrql;
  484.  
  485.                 Length     &= ~file_obj->dwAddressMask; // align to integer increments
  486.                 storeLength = Length;
  487.                                                        // check for modifier
  488.                 // lock other users out
  489.                 KeAcquireSpinLock(&pciada->AccessLock, &oldIrql);
  490.  
  491.                 if (pciada->bModifier != file_obj->bAddressModifier)
  492.                 {
  493.                         WRITE_REGISTER_UCHAR(pciada->pbModifier, file_obj->bAddressModifier);
  494.                         pciada->bModifier = file_obj->bAddressModifier;
  495.                 }
  496.                
  497.                 // do the read ---
  498.                 file_obj->bBusError = FALSE;
  499.                 pbPrevBusError = ExchangePointer(&pciada->pbBusError, &file_obj->bBusError);
  500.                 while (Length)
  501.                 {
  502.                         pageAddress = Address & ~VME_ADR_MASK;
  503.                         if (pageAddress != pciada->dwVMEPage)
  504.                         {
  505.                                 WRITE_REGISTER_ULONG(pciada->pdwVMEAdr, pageAddress);
  506.                                 pciada->dwVMEPage = pageAddress;
  507.                         }
  508.  
  509.                         toNextPage  = (pageAddress + VME_ADR_MASK + 1) - Address;
  510.                         blockLength = (toNextPage < Length) ? toNextPage : Length;
  511.  
  512.                         KdPrint(("Address 0x%08x, blockLength %d, Length %d\n",
  513.                                                                                 Address, blockLength, Length));
  514.  
  515.                         file_obj->fWrite((PVOID)((PUCHAR)pciada->pvVME + (Address & VME_ADR_MASK)) , blockLength, pInputBuffer);
  516.  
  517.                         Length  -= blockLength;
  518.                         Address += blockLength;
  519.                         pInputBuffer = (PVOID)((PUCHAR)pInputBuffer + blockLength);
  520.                 }
  521.  
  522.                 // release the lock
  523.                 KeReleaseSpinLock(&pciada->AccessLock, oldIrql);
  524.                 ExchangePointer(&pciada->pbBusError, pbPrevBusError);
  525.                 if (file_obj->bBusError) Status = STATUS_ACCESS_VIOLATION;
  526.  
  527.                 if (file_obj->bIncrement)  // only when increment to next is on
  528.                         *fileOffset =   RtlLargeIntegerAdd(*fileOffset, RtlConvertUlongToLargeInteger(storeLength));
  529.         }
  530.         // do here in between what has to be done end -------------
  531.  
  532.         Irp->IoStatus.Status      = Status;  
  533.         Irp->IoStatus.Information = storeLength;  
  534.         IoCompleteRequest(Irp,IO_NO_INCREMENT);  
  535.  
  536.     KdPrint(("PCIVMEWrite(), Status = 0x%08x\n", Status));
  537.  
  538.         return Status;
  539. }
  540.  
  541. #ifdef DO_CLEANUP
  542. //------------------------------------------------------------------------
  543. // called at cancel of a path
  544. NTSTATUS PCIVMECancel(PDEVICE_OBJECT device_Obj, PIRP Irp)
  545. {
  546.         FILE_OBJ *file_obj = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  547.         PIRP     pIrpCancel;
  548.  
  549.         KdPrint(("PCIVMECancel()\n"));
  550.  
  551.         // remove all queued IRPs of this file_obj
  552.         do
  553.         {
  554.                 pIrpCancel = RemoveIRPfromQueue(device_Obj, file_obj);
  555.  
  556.                 if (pIrpCancel == (PIRP)NULL)
  557.                 {
  558.                         IoReleaseCancelSpinLock(pIrpCancel->CancelIrql);
  559.                         break;
  560.                 }
  561.                 else
  562.                 {
  563.                         IoAcquireCancelSpinLock(pIrpCancel->CancelIrql);
  564.  
  565.                         // mark irp as not pending
  566.                         IoSetCancelRoutine(pIrpCancel, NULL);
  567.  
  568.                         IoReleaseCancelSpinLock(pIrpCancel->CancelIrql);
  569.  
  570.                         pIrpCancel->IoStatus.Status = STATUS_CANCELLED;
  571.                         pIrpCancel->IoStatus.Information = 0;
  572.                 }
  573.         } while (pIrpCancel != (PIRP)NULL);
  574.  
  575.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  576.  
  577.         KdPrint(("PCIVMECancel(OK)\n"));
  578.  
  579.         return STATUS_SUCCESS;
  580. }
  581. #endif
  582.  
  583. //------------------------------------------------------------------------
  584. // search for pciada's
  585. //
  586. NTSTATUS SearchDevices(PDEVICE_OBJECT device_Obj)
  587. {
  588.   PCI_SLOT_NUMBER   SlotNumber;
  589.   PCI_COMMON_CONFIG pci_config;
  590.   PCIADA            *pciada;
  591.   ULONG             length;
  592.   int               *found;
  593.   int               i,j,k;
  594.  
  595.   KdPrint(("SearchDevices()\n"));
  596.  
  597.   // prepare structures ----------------------------------------
  598.   found = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
  599.   *found = 0;
  600.   for (i = 0; i < PCIVME_MAX_PCIADA; i++)
  601.   {
  602.         pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  603.  
  604.         pciada->Bus                = -1;
  605.     pciada->Slot.u.AsULONG     = 0xFFFFFFFF;
  606.   }
  607.  
  608.   // search for pciada's ---------------------------------------
  609.   SlotNumber.u.bits.Reserved = 0;
  610.  
  611.   for (j = 0; j < PCI_MAX_BUSES; j++)
  612.   {
  613.     for (i = 0; i < PCI_MAX_DEVICES; i++)
  614.         {
  615.           SlotNumber.u.bits.DeviceNumber = i;
  616.           for (k = 0; k < PCI_MAX_FUNCTION; k++)
  617.           {
  618.                 SlotNumber.u.bits.FunctionNumber = k;
  619.             length = HalGetBusData( PCIConfiguration,         // Bustype
  620.                                                             j,                                    // PCI-Busnumber
  621.                                                             SlotNumber.u.AsULONG,     // Slotnumber
  622.                                                             (PVOID) &(pci_config),    // Pointer for the PCI-Information
  623.                                                             sizeof(PCI_COMMON_CONFIG) );
  624.  
  625.                 if ((pci_config.VendorID    == PCIVME_VENDOR_ID) &&
  626.                         (pci_config.DeviceID    == PCIVME_DEVICE_ID) &&
  627.                         (pci_config.u.type0.SubSystemID == PCIVME_SUBSYS_ID) &&
  628.                         (pci_config.u.type0.SubVendorID == PCIVME_SUBVEN_ID) &&
  629.                         (pci_config.u.type0.BaseAddresses[2]))
  630.                 {
  631.                pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[*found];
  632.  
  633.                memcpy(&pciada->PCIDevice, &pci_config, sizeof(pci_config));
  634.                    pciada->Slot = SlotNumber;
  635.                    pciada->Bus  = j;
  636.  
  637.                    KdPrint(("PCIADA found @ Bus/Slot %d/%d.\n", pciada->Bus, pciada->Slot.u.AsULONG));
  638.  
  639.                    (*found)++;
  640.                    if (*found >= PCIVME_MAX_PCIADA) return STATUS_SUCCESS;
  641.                 }
  642.           }
  643.         }              
  644.   }
  645.   KdPrint(("SearchDevices() found %d devices\n", (*found)));
  646.   return STATUS_SUCCESS;
  647. }
  648.  
  649. //---------------------------------------------------------------
  650. // function to call for bug fix of PLX9050 build in bug
  651. //
  652. NTSTATUS PLX9050BugFix(PDEVICE_OBJECT device_Obj)
  653. {
  654.         // http://permalink.gmane.org/gmane.linux.kernel.pci/18419
  655.         DEVICE_EXT *DeviceExtension = (DEVICE_EXT*)device_Obj->DeviceExtension;
  656.         int i;
  657.         ULONG dwData;
  658.         PCIADA *pciada;
  659.  
  660.         KdPrint(("PLX9050BugFix()\n"));
  661.  
  662.         for (i = 0; i < DeviceExtension->nPCIADAs; i++)
  663.         {
  664.                 pciada = &DeviceExtension->pciada[i];
  665.  
  666.                 if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[0]) & 0x80)
  667.                 {      
  668.                         KdPrint(("Changing address 0:0x%p with 4:0x%p\n",
  669.                                 pciada->PCIDevice.u.type0.BaseAddresses[0],
  670.                                 pciada->PCIDevice.u.type0.BaseAddresses[4]));
  671.  
  672.                         pciada->PCIDevice.u.type0.BaseAddresses[0] =           // exchange
  673.                                 pciada->PCIDevice.u.type0.BaseAddresses[4];
  674.                         pciada->PCIDevice.u.type0.BaseAddresses[4] = dwData;
  675.  
  676.                         if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  677.                                   pciada->Slot.u.AsULONG,
  678.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[0],
  679.                                                 0x10, 4) != 4)
  680.                         return STATUS_UNSUCCESSFUL;
  681.  
  682.                         if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  683.                                   pciada->Slot.u.AsULONG,
  684.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[4],
  685.                                                 0x20, 4) != 4)
  686.                         return STATUS_UNSUCCESSFUL;
  687.                 }
  688.      
  689.                 if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[1]) & 0x80)
  690.                 {
  691.                         KdPrint(("Changing address 1:0x%p with 5:0x%p\n",
  692.                                 pciada->PCIDevice.u.type0.BaseAddresses[1],
  693.                                 pciada->PCIDevice.u.type0.BaseAddresses[5]));
  694.  
  695.                   pciada->PCIDevice.u.type0.BaseAddresses[1] =           // exchange
  696.                                 pciada->PCIDevice.u.type0.BaseAddresses[5];
  697.                   pciada->PCIDevice.u.type0.BaseAddresses[5] = dwData;
  698.  
  699.                   if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  700.                                   pciada->Slot.u.AsULONG,
  701.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[1],
  702.                                                 0x14, 4) != 4)
  703.                         return STATUS_UNSUCCESSFUL;
  704.  
  705.                   if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  706.                                   pciada->Slot.u.AsULONG,
  707.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[5],
  708.                                                 0x24, 4) != 4)
  709.                         return STATUS_UNSUCCESSFUL;
  710.                 }
  711.         }
  712.  
  713.         return STATUS_SUCCESS;
  714. }
  715.  
  716. static VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list)
  717. {                                                       // ShowResources
  718.         PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = list->PartialDescriptors;
  719.         ULONG nres = list->Count;
  720.         ULONG i;
  721.  
  722.         for (i = 0; i < nres; ++i, ++resource)
  723.         {                                               // for each resource
  724.                 ULONG type = resource->Type;
  725.  
  726.                 static char* namelow[] = {
  727.                         "CmResourceTypeNull",//                0   // ResType_All or ResType_None (0x0000)
  728.                         "CmResourceTypePort",//               1   // ResType_IO (0x0002)
  729.                         "CmResourceTypeInterrupt",//          2   // ResType_IRQ (0x0004)
  730.                         "CmResourceTypeMemory",//             3   // ResType_Mem (0x0001)
  731.                         "CmResourceTypeDma",//                4   // ResType_DMA (0x0003)
  732.                         "CmResourceTypeDeviceSpecific",//      5   // ResType_ClassSpecific (0xFFFF)
  733.                         "CmResourceTypeBusNumber",//          6   // ResType_BusNumber (0x0006)
  734.                         "CmResourceTypeMemoryLarge" //        7   // ResType_MemLarge (0x0007)
  735.                 };
  736.                 static char* namehigh[] = {
  737.                         //"CmResourceTypeNonArbitrated" ,//    128   // Not arbitrated if 0x80 bit set
  738.                         "CmResourceTypeConfigData",//       128   // ResType_Reserved (0x8000)
  739.                         "CmResourceTypeDevicePrivate",//    129   // ResType_DevicePrivate (0x8001)
  740.                         "CmResourceTypePcCardConfig",//     130   // ResType_PcCardConfig (0x8002)
  741.                         "CmResourceTypeMfCardConfig",//     131   // ResType_MfCardConfig (0x8003)
  742.                         "CmResourceTypeConnection" //       132   // ResType_Connection (0x8004)
  743.                 };
  744.  
  745.                 if (type<8) KdPrint((" [%d] type %s", type, type < arraysize(namelow) ? namelow[type] : "unknown"));
  746.                 if (type>127) KdPrint((" [%d] type %s", type, type-128 < arraysize(namehigh) ? namehigh[type-128] : "unknown"));
  747.                 switch (type)
  748.                 {                                       // select on resource type
  749.                 case CmResourceTypePort:
  750.                                 KdPrint((" start ADDR=0x%p  0x%8X%8.8lX length %X\n",
  751.                                 resource->u.Port.Start, resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,
  752.                                 resource->u.Port.Length));
  753.                         break;
  754.                 case CmResourceTypeMemory:
  755.                         KdPrint((" %d start ADDR=0x%p \n", i,  resource->u.Memory.Start ));
  756.                         break;
  757.  
  758.                 case CmResourceTypeInterrupt:
  759.                         KdPrint(("  IRQL %d, vector %d, affinity %d\n",
  760.                                 resource->u.Interrupt.Level, resource->u.Interrupt.Vector,
  761.                                 resource->u.Interrupt.Affinity));
  762.                         break;
  763.  
  764.                 case CmResourceTypeDma:
  765.                         KdPrint(("  channel %d, port %X\n",
  766.                                 resource->u.Dma.Channel, resource->u.Dma.Port));
  767.  
  768.                        
  769.                        
  770.                 }                                       // select on resource type
  771.         }                                               // for each resource
  772. }                                                       // ShowResources
  773.  
  774.  
  775. //------------------------------------------------------------------------
  776. //  reserve resources for PCIADAs
  777. //
  778. NTSTATUS PCIVMEExtractResources(PCIADA *pciada, PIRP irp)
  779. {
  780.         //PCM_RESOURCE_LIST pResourceList;
  781.         ///PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
  782.         PCM_PARTIAL_RESOURCE_LIST pPartialList = NULL;
  783.         PCM_PARTIAL_RESOURCE_LIST pListTranslated = NULL;
  784.         PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialDescriptor;
  785.         int i;
  786.         int bug = 0;
  787.  
  788.         KdPrint(("PCIVMEExtractResources()\n"));
  789.  
  790.         ///pResourceList   = pList;
  791.         ///pFullDescriptor = pResourceList->List;
  792.         ///pPartialList    = &pFullDescriptor->PartialResourceList;
  793.         PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);
  794.         if (stack->Parameters.StartDevice.AllocatedResources)
  795.         pPartialList = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
  796.         KdPrint(("Allocated Resources:------------------\n"));
  797.         ShowResources(pPartialList);
  798.        
  799.         int plcount = 0;
  800.         for (i=0; i<(int)pPartialList->Count; i++)
  801.         {
  802.                 pPartialDescriptor = &pPartialList->PartialDescriptors[i];
  803.                
  804.                 switch (pPartialDescriptor->Type)
  805.                 {
  806.                         case CmResourceTypeInterrupt:
  807.                                 pciada->Irql     = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
  808.                                 pciada->Vector   = pPartialDescriptor->u.Interrupt.Vector;
  809.                                 pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
  810.  
  811.                                 KdPrint(("AllocatedResources Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
  812.                                         pciada->Irql, pciada->Vector, pciada->Affinity));
  813.                                 break;
  814.                         case CmResourceTypeDma:
  815.                                 KdPrint(("AllocatedResources Dma    : \n"));
  816.                                 break;
  817.                         case CmResourceTypePort:
  818.  
  819.                                 KdPrint(("AllocatedResources Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
  820.                                 break;
  821.                         case CmResourceTypeMemory:
  822.                                 // special handling of PLXBUG here because of WIN2000
  823.                                 // WIN2000 doesn't recognize late address changes
  824.                                 if (!bug)
  825.                                 {
  826.                                         if (plcount == 0)
  827.                                         {
  828.                                                 pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  829.  
  830.                                                 if (pciada->pvPhysLcr.LowPart & 0x80) {
  831.                                                         bug = 1;
  832.                                                         KdPrint(("AllocatedResources PLXBug\n"));
  833.                                                 }
  834.                                         }
  835.                                 }
  836.                                 else
  837.                                 {
  838.                                         if (plcount == 3)
  839.                                                 pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  840.                                 }
  841.  
  842.                                 if (plcount == 2){
  843.                                         pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
  844.                                         KdPrint(("PCIVMEExtractResources() IFR=0x%p \n", pciada->pvPhysIfr));
  845.                                 }
  846.                                 KdPrint(("[%d] AllocatedResources Memory : 0x%p\n", plcount, (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
  847.                                 break;
  848.                 }
  849.                 if (pPartialDescriptor->Type < 8) plcount++;
  850.         }
  851.  
  852.         KdPrint(("PCIVMEExtractResources() LCR=0x%p IFR=0x%p \n", pciada->pvPhysLcr, pciada->pvPhysIfr));
  853.  
  854.         if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
  855.                 pListTranslated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
  856.         KdPrint(("Translated Resources:------------------\n"));
  857.         ShowResources(pListTranslated);
  858.         plcount = 0;
  859.         bug     = 0;
  860.         for (i = 0; i<(int)pPartialList->Count; i++)
  861.         {
  862.                 pPartialDescriptor = &pListTranslated->PartialDescriptors[i];
  863.  
  864.                 switch (pPartialDescriptor->Type)
  865.                 {
  866.                 case CmResourceTypeInterrupt:
  867.                         pciada->Irql = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
  868.                         pciada->Vector = pPartialDescriptor->u.Interrupt.Vector;
  869.                         pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
  870.  
  871.                         KdPrint(("AllocatedResourcesTranslated Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
  872.                                 pciada->Irql, pciada->Vector, pciada->Affinity));
  873.                         break;
  874.                 case CmResourceTypeDma:
  875.                         KdPrint(("AllocatedResourcesTranslated Dma    : \n"));
  876.                         break;
  877.                 case CmResourceTypePort:
  878.  
  879.                         KdPrint(("AllocatedResourcesTranslated Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
  880.                         break;
  881.                 case CmResourceTypeMemory:
  882.                         // special handling of PLXBUG here because of WIN2000
  883.                         // WIN2000 doesn't recognize late address changes
  884.                         if (!bug)
  885.                         {
  886.                                 if (plcount == 0)
  887.                                 {
  888.                                         pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  889.                                         KdPrint(("0 PCIVMEExtractResources() LCR=0x%p \n", pciada->pvPhysLcr));
  890.                                         if (pciada->pvPhysLcr.LowPart & 0x80) {
  891.                                                 bug = 1;
  892.                                                 KdPrint(("AllocatedResourcesTranslated PLXBug\n"));
  893.                                         }
  894.                                 }
  895.                         }
  896.                         else
  897.                         {
  898.                                 if (plcount == 3){
  899.                                         pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  900.                                         KdPrint(("3 PCIVMEExtractResources() LCR=0x%p \n", pciada->pvPhysLcr));
  901.                                 }
  902.                         }
  903.  
  904.                         if (plcount == 2){
  905.                                 pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
  906.                                 KdPrint(("2 PCIVMEExtractResources() IFR=0x%p \n", pciada->pvPhysIfr));
  907.                         }
  908.  
  909.                         KdPrint(("[%d] AllocatedResourcesTranslated Memory : 0x%p\n", plcount, (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
  910.                         break;
  911.                 }
  912.                 if (pPartialDescriptor->Type < 8) plcount++;
  913.         }
  914.  
  915.  
  916.  
  917.         if (pciada->Irql == 0)
  918.                 return STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
  919.  
  920.         KdPrint(("PCIVMEExtractResources() Translated LCR=0x%p IFR=0x%p \n", pciada->pvPhysLcr, pciada->pvPhysIfr));
  921.  
  922.         return STATUS_SUCCESS;
  923. }
  924.  
  925. NTSTATUS PCIVMEReserveResources(PDEVICE_OBJECT device_Obj, PIRP irp)
  926. {
  927.         //PCM_RESOURCE_LIST pList = NULL;
  928.         NTSTATUS result = STATUS_SUCCESS;
  929.         int i;
  930.         DEVICE_EXT *pDevExt = (DEVICE_EXT*)(device_Obj->DeviceExtension);
  931.         int nPCIADAs = pDevExt->nPCIADAs;
  932.         PCIADA *pciada;
  933.     UNICODE_STRING DriverClassName;
  934.    
  935.         KdPrint(("PCIVMEReserveResources()\n"));
  936.  
  937.         // prepare resource claiming
  938.         //RtlInitUnicodeString(&DriverClassName, L"PCICC32");
  939.         RtlInitUnicodeString(&DriverClassName, L"PCIVME");
  940.         // cycle through all busses and slots assigned to PCIADAs
  941.         for (i = 0; i < nPCIADAs; i++)
  942.     {
  943.                 pciada = &pDevExt->pciada[i];
  944.  
  945.                 //result = HalAssignSlotResources(NULL, &DriverClassName, device_Obj->DriverObject, device_Obj,
  946.                 //      PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, &pList);
  947.                 /*
  948.                 result = IoReportDetectedDevice(device_Obj->DriverObject, PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, pList, NULL, FALSE, &device_Obj);
  949.                 if (result != STATUS_SUCCESS){
  950.                         KdPrint(("PCIVMEReserveResources(0x%08x) HalAssignSlotResources  ***ERROR*** faliure to get slot information\n", result));
  951.                         break;
  952.                 }
  953.                 */
  954.                 result = PCIVMEExtractResources(pciada, irp);
  955.  
  956.                 if (result != STATUS_SUCCESS){
  957.                         KdPrint(("PCIVMEReserveResources(0x%08x) PCIVMEExtractResources\n", result));
  958.                         break;
  959.                 }
  960.         }
  961.  
  962.         // its my part to free allocated resources
  963.         //if (pList != NULL) ExFreePoolWithTag(pList,'nepo');
  964.  
  965.         KdPrint(("PCIVMEReserveResources(0x%08x)\n", result));
  966.  
  967.         return result;
  968. };
  969.  
  970.  
  971. //------------------------------------------------------------------------
  972. //  free resources from PCIADAs
  973. //
  974. NTSTATUS PCIVMEFreeResources(PDEVICE_OBJECT device_Obj)
  975. {
  976.         CM_RESOURCE_LIST ResList;
  977.         BOOLEAN          bConflict;
  978.     UNICODE_STRING   DriverClassName;
  979.  
  980.     KdPrint(("PCIVMEFreeResources()\n"));
  981.  
  982.         RtlInitUnicodeString(&DriverClassName, L"PCIVME");
  983.  
  984.         ResList.Count = 0;
  985.  
  986.         IoReportResourceUsage(&DriverClassName, device_Obj->DriverObject,
  987.                                          &ResList, sizeof(ResList), device_Obj,
  988.                                                                          NULL, 0, FALSE, &bConflict);
  989.         return STATUS_SUCCESS;
  990. };
  991.  
  992.  
  993. //------------------------------------------------------------------------
  994. //  translate memory resources to neutral for PCIADAs
  995. //
  996. NTSTATUS PCIVMETranslateBusAddresses(PDEVICE_OBJECT device_Obj,  PIRP irp)
  997. {
  998.         int              i;
  999.         NTSTATUS         result = STATUS_SUCCESS;
  1000.         int nPCIADAs = ((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
  1001.         ULONG            memType0, memType2;
  1002.         PCIADA           *pciada;
  1003.         PCM_PARTIAL_RESOURCE_LIST pPartialList = NULL;
  1004.         PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);
  1005.         if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
  1006.        pPartialList = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
  1007.  
  1008.    
  1009.         for (i = 0; i < nPCIADAs; i++)
  1010.         {
  1011.       pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  1012.  
  1013.           memType0 = memType2 = 0;
  1014.           /*
  1015.           if (!(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysLcr, &memType0,
  1016.                                                                &pciada->pvPhysLcr)) ||
  1017.               !(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysIfr, &memType2,
  1018.                                                                &pciada->pvPhysIfr)))
  1019.           {
  1020.                   result = STATUS_UNSUCCESSFUL;
  1021.                   break;
  1022.           }
  1023.           */
  1024.           KdPrint(("PCIADA %d TranslateBusAddresseses() -- no translation is made\n", i));
  1025.  
  1026.           if ((memType0) || (memType2))
  1027.           {
  1028.                   result = STATUS_UNSUCCESSFUL;
  1029.                   break;
  1030.           }
  1031.         }
  1032.    
  1033.         return result;
  1034. }
  1035.  
  1036. //------------------------------------------------------------------------
  1037. //  map address spaces to virtual addresses
  1038. //
  1039. NTSTATUS PCIVMEMapIOspace(PDEVICE_OBJECT device_Obj)
  1040. {
  1041.         int              i;
  1042.         DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
  1043.         int                              nPCIADAs = pDevExt->nPCIADAs;
  1044.         PCIADA           *pciada;
  1045.  
  1046.         KdPrint(("PCIVMEMapIOspace()\n"));
  1047.  
  1048.         for (i = 0; i < nPCIADAs; i++)
  1049.         {
  1050.        pciada = &pDevExt->pciada[i];
  1051.  
  1052.        if ((pciada->pvVirtLcr = MmMapIoSpace(pciada->pvPhysLcr, LCR_SPACE, FALSE)) == NULL)
  1053.           return STATUS_UNSUCCESSFUL;
  1054.        if ((pciada->pvVirtIfr = MmMapIoSpace(pciada->pvPhysIfr, IFR_SPACE, FALSE)) == NULL)
  1055.           return STATUS_UNSUCCESSFUL;
  1056.  
  1057.            KdPrint(("PCIADA %d: LCR 0x%08x IFR 0x%08x\n",
  1058.                                          i, pciada->pvVirtLcr, pciada->pvVirtIfr));
  1059.  
  1060.            pciada->pwIntCSR = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x4C);
  1061.            pciada->pwCntrl  = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x50);
  1062.         }
  1063.  
  1064.         return STATUS_SUCCESS;
  1065. }
  1066.  
  1067.  
  1068. //------------------------------------------------------------------------
  1069. //  initializes and registers a DPC routine for each pciada
  1070. //
  1071. NTSTATUS InitializeCustomDPCObjects(PDEVICE_OBJECT device_object)
  1072. {
  1073.         int              i;
  1074.         int nPCIADAs = ((DEVICE_EXT*)(device_object->DeviceExtension))->nPCIADAs;
  1075.         PCIADA           *pciada;
  1076.  
  1077.         KdPrint(("InitializeCustomDPCObject()\n"));
  1078.  
  1079.         for (i = 0; i < nPCIADAs; i++)
  1080.         {
  1081.                 pciada = &((DEVICE_EXT*)(device_object->DeviceExtension))->pciada[i];
  1082.                 KeInitializeDpc(&pciada->kDPCobj, fMyDefferedRoutine, (PVOID)device_object);
  1083.         }
  1084.  
  1085.         return STATUS_SUCCESS;
  1086. }
  1087.  
  1088. //------------------------------------------------------------------------
  1089. //  initializes the queue for storing IRPs waiting for vectors
  1090. //
  1091. NTSTATUS InitializeIRPQueue(PDEVICE_OBJECT device_Obj)
  1092. {
  1093.         DEVICE_EXT *pDevExt = ((DEVICE_EXT*)(device_Obj->DeviceExtension));
  1094.  
  1095.         KdPrint(("InitializeIRPQueue()\n"));
  1096.  
  1097.         KeInitializeSpinLock(&pDevExt->IRPLock);
  1098.         InitializeListHead(&pDevExt->IRPList);
  1099.  
  1100.         return STATUS_SUCCESS;
  1101. }
  1102.  
  1103. //------------------------------------------------------------------------
  1104. // init structures a.s.o.
  1105. //
  1106. VOID PCIVMESoftInit(PDEVICE_OBJECT device_Obj)
  1107. {
  1108.         int i;
  1109.         PCIADA *pciada;
  1110.  
  1111.         for (i = 0; i < PCIVME_MAX_PCIADA; i++)
  1112.         {
  1113.                 pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  1114.  
  1115.                 pciada->pvPhysLcr.QuadPart = pciada->pvPhysIfr.QuadPart = 0;
  1116.                 pciada->pvVirtLcr = pciada->pvVirtIfr = NULL;
  1117.  
  1118.                 pciada->bConnected     = FALSE;   // connection still not verified
  1119.                 pciada->bWordMode      = TRUE;
  1120.                 pciada->bSysControl    = FALSE;
  1121.                 pciada->wModuleNumber  = 0xFFFF;
  1122.                 pciada->wFPGAVersion   = 0xFFFF;
  1123.                 pciada->wModuleType    = 1;       // always VMEMM
  1124.  
  1125.                 pciada->InterruptObject = NULL;
  1126.                 pciada->Irql                    = 0;
  1127.                 pciada->Vector          = 0;
  1128.                 pciada->Affinity                = 0;
  1129.  
  1130.                 pciada->dwLinkCount     = 0;
  1131.                                        
  1132.                 KeInitializeSpinLock(&pciada->IrqListLock);
  1133.                 KeInitializeSpinLock(&pciada->AccessLock);
  1134.  
  1135.                 InitializeListHead(&pciada->IrqListList);  // start of list of irq fifos
  1136.  
  1137.                 pciada->nInterruptHandlers = 0;
  1138.         }
  1139.  
  1140.         // no vmemm associated to any PCIADA
  1141.         for (i = 0; i < PCIVME_MAX_VMEMM; i++)
  1142.           ((DEVICE_EXT*)(device_Obj->DeviceExtension))->vmemm[i] = NULL;
  1143. }
  1144.  
  1145. NTSTATUS OnRequestComplete(PDEVICE_OBJECT fdo, PIRP Irp, PKEVENT pev)
  1146. {
  1147.         UNREFERENCED_PARAMETER(fdo);
  1148.         UNREFERENCED_PARAMETER(Irp);
  1149.         KeSetEvent(pev, 0, FALSE);
  1150.         return STATUS_MORE_PROCESSING_REQUIRED;
  1151. }
  1152.  
  1153. NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR Information)
  1154. {
  1155.         Irp->IoStatus.Status = status;
  1156.         Irp->IoStatus.Information = Information;
  1157.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1158.         return status;
  1159. }
  1160. NTSTATUS ForwardAndWait(PDEVICE_OBJECT fdo, PIRP Irp)
  1161. {
  1162.         KEVENT event;
  1163.         KeInitializeEvent(&event, NotificationEvent, FALSE);
  1164.         IoCopyCurrentIrpStackLocationToNext(Irp);
  1165.         IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete, (PVOID)&event, TRUE, TRUE, TRUE);
  1166.         PDEVICE_EXT pdx = (PDEVICE_EXT ) fdo->DeviceExtension;
  1167.         IoCallDriver(pdx->LowerDeviceObject, Irp);
  1168.         KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  1169.         return Irp->IoStatus.Status;
  1170. }
  1171.  
  1172. NTSTATUS HandleStartDevice(PDEVICE_OBJECT fdo, PIRP Irp)
  1173. {
  1174.         PIO_STACK_LOCATION stack;
  1175.         Irp->IoStatus.Status = STATUS_SUCCESS;
  1176.         NTSTATUS status = ForwardAndWait(fdo, Irp);
  1177.         if (!NT_SUCCESS(status))
  1178.                 return CompleteRequest(Irp, status, Irp->IoStatus.Information);
  1179.        
  1180.         stack = IoGetCurrentIrpStackLocation(Irp);
  1181.         status = PCIVMEStartDevice(fdo, Irp);
  1182.         return CompleteRequest(Irp, status, Irp->IoStatus.Information);
  1183. }
  1184.  
  1185.  
  1186. NTSTATUS DefaultPnpHandler(PDEVICE_OBJECT fdo, PIRP Irp)
  1187. {
  1188.         IoSkipCurrentIrpStackLocation(Irp);
  1189.         PDEVICE_EXT pdx = (PDEVICE_EXT )fdo->DeviceExtension;
  1190.         return IoCallDriver(pdx->LowerDeviceObject, Irp);
  1191. }
  1192.  
  1193. NTSTATUS HandleStopDevice(PDEVICE_OBJECT fdo, PIRP Irp)
  1194. {
  1195.         IoSkipCurrentIrpStackLocation(Irp);
  1196.         UNICODE_STRING symbol_name;
  1197.         RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
  1198.     // delete the symbolicLink in the registry
  1199.         IoDeleteSymbolicLink(&symbol_name);
  1200.         DEVICE_EXT *ext = (DEVICE_EXT*)(fdo->DeviceExtension);
  1201.         // delete the deviceObject
  1202.         if (ext->LowerDeviceObject) IoDetachDevice(ext->LowerDeviceObject);
  1203.         IoDeleteDevice(fdo);
  1204.         KdPrint(("HandleStopDevice (OK)\n"));
  1205.         return STATUS_SUCCESS;
  1206. }
  1207.  
  1208.  
  1209. NTSTATUS PCIVMEDispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
  1210. {
  1211.         PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
  1212.         ULONG fcn = stack->MinorFunction;
  1213.         static char* pnpname[] = {
  1214.                 "IRP_MN_START_DEVICE",
  1215.                 "IRP_MN_QUERY_REMOVE_DEVICE",
  1216.                 "IRP_MN_REMOVE_DEVICE",
  1217.                 "IRP_MN_CANCEL_REMOVE_DEVICE",
  1218.                 "IRP_MN_STOP_DEVICE",
  1219.                 "IRP_MN_QUERY_STOP_DEVICE",
  1220.                 "IRP_MN_CANCEL_STOP_DEVICE",
  1221.                 "IRP_MN_QUERY_DEVICE_RELATIONS",
  1222.                 "IRP_MN_QUERY_INTERFACE",
  1223.                 "IRP_MN_QUERY_CAPABILITIES",
  1224.                 "IRP_MN_QUERY_RESOURCES",
  1225.                 "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
  1226.                 "IRP_MN_QUERY_DEVICE_TEXT",
  1227.                 "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
  1228.                 "",
  1229.                 "IRP_MN_READ_CONFIG",
  1230.                 "IRP_MN_WRITE_CONFIG",
  1231.                 "IRP_MN_EJECT",
  1232.                 "IRP_MN_SET_LOCK",
  1233.                 "IRP_MN_QUERY_ID",
  1234.                 "IRP_MN_QUERY_PNP_DEVICE_STATE",
  1235.                 "IRP_MN_QUERY_BUS_INFORMATION",
  1236.                 "IRP_MN_DEVICE_USAGE_NOTIFICATION",
  1237.                 "IRP_MN_SURPRISE_REMOVAL",
  1238.                 "IRP_MN_QUERY_LEGACY_BUS_INFORMATION",
  1239.         };
  1240.  
  1241.         if (fcn < arraysize(pnpname))
  1242.                 KdPrint(("PCIVMEDispatchPnp  - IRP_MJ_PNP (%s)\n", pnpname[fcn]));
  1243.         else
  1244.                 KdPrint(( "PCIVMEDispatchPnp - IRP_MJ_PNP (%2.2X)\n", fcn));
  1245.  
  1246.         static NTSTATUS(*fcntab[])(PDEVICE_OBJECT, PIRP) = {
  1247.                 HandleStartDevice,         // IRP_MN_START_DEVICE
  1248.                 HandleStopDevice         // IRP_MN_QUERY_REMOVE_DEVICE
  1249.         };
  1250.  
  1251.         if (fcn >= arraysize(fcntab))
  1252.                 return DefaultPnpHandler(fdo, Irp);
  1253.         return (*fcntab[fcn])(fdo, Irp);
  1254. }
  1255.  
  1256.  
  1257. NTSTATUS PCIVMEStartDevice(PDEVICE_OBJECT device_object, PIRP irp){
  1258.         NTSTATUS result = STATUS_SUCCESS;
  1259.         int            nPCIADAs;                                // count of PCIADAs
  1260.         DEVICE_EXT     *DeviceExtension = NULL;
  1261.         DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
  1262.         // init pciada structures ------------------------------------
  1263.         PCIVMESoftInit(device_object);
  1264.  
  1265.         // search for PCIADAs ----------------------------------------
  1266.         result = SearchDevices(device_object);
  1267.         nPCIADAs = DeviceExtension->nPCIADAs;
  1268.  
  1269.         if ((result != STATUS_SUCCESS) || !(nPCIADAs))
  1270.         {
  1271.                 KdPrint(("PCIVMEStartDevice Device not found\n"));
  1272.                 PCIVMEUnload(DeviceExtension->driverObj);
  1273.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1274.         }
  1275.  
  1276.         // request exclusive ownership of .. ---------------------------------
  1277.         if ((result = PCIVMEReserveResources(device_object, irp)) != STATUS_SUCCESS)
  1278.         {
  1279.                 KdPrint(("PCIVMEStartDevice Resource not reserved PCIVMEReserveResources \n"));
  1280.                 PCIVMEUnload(DeviceExtension->driverObj);
  1281.                 return result;
  1282.         }
  1283.         else
  1284.                 DeviceExtension->nInitState++;
  1285.         // fix PLX9050 Bug -------------------------------------------
  1286.         if ((result = PLX9050BugFix(device_object)) != STATUS_SUCCESS)
  1287.         {
  1288.                 KdPrint(("PCIVMEStartDevice PLX9050BugFix\n"));
  1289.                 PCIVMEUnload(DeviceExtension->driverObj);
  1290.                 return result;
  1291.         }
  1292.  
  1293.         DeviceExtension->nInitState += 2;
  1294.         /*
  1295.         // translate BUS relative addresses ----------------------------------
  1296.         if ((result = PCIVMETranslateBusAddresses(device_object,irp)) != STATUS_SUCCESS)
  1297.         {
  1298.                 PCIVMEUnload(DeviceExtension->driverObj);
  1299.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1300.         }
  1301.         else
  1302.                 DeviceExtension->nInitState++;
  1303.  
  1304.        
  1305.         // translate Interrupt Resources used --------------------------------
  1306.         if ((result = PCIVMETranslateInterrupts(device_object)) != STATUS_SUCCESS)
  1307.         {
  1308.                 PCIVMEUnload(DeviceExtension->driverObj);
  1309.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1310.         }
  1311.         else
  1312.                 DeviceExtension->nInitState++;
  1313.         */
  1314.  
  1315.         // map address spaces to virtual addresses ---------------------------
  1316.         if ((result = PCIVMEMapIOspace(device_object)) != STATUS_SUCCESS)
  1317.         {
  1318.                 PCIVMEUnload(DeviceExtension->driverObj);
  1319.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1320.         }
  1321.         else
  1322.                 DeviceExtension->nInitState++;
  1323.  
  1324.         // initialze my custom DPC objects -----------------------------------
  1325.         if ((result = InitializeCustomDPCObjects(device_object)) != STATUS_SUCCESS)
  1326.         {
  1327.                 PCIVMEUnload(DeviceExtension->driverObj);
  1328.                 return result;
  1329.         }
  1330.         else
  1331.                 DeviceExtension->nInitState++;
  1332.  
  1333.         // initialze the queue for IRPs waiting for vectors ------------------
  1334.         if ((result = InitializeIRPQueue(device_object)) != STATUS_SUCCESS)
  1335.         {
  1336.                 PCIVMEUnload(DeviceExtension->driverObj);
  1337.                 return result;
  1338.         }
  1339.         else
  1340.                 DeviceExtension->nInitState++;
  1341.  
  1342.         // connect interrupts to service routines ----------------------------
  1343.         if ((result = PCIVMEConnectInterrupt(device_object)) != STATUS_SUCCESS)
  1344.         {
  1345.                 PCIVMEUnload(DeviceExtension->driverObj);
  1346.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1347.         }
  1348.         else
  1349.                 DeviceExtension->nInitState++;
  1350.  
  1351.         // scan all connected VMEMM for info and later use -------------------
  1352.         if ((result = PCIVMEScanVMEMM(device_object)) != STATUS_SUCCESS)
  1353.         {
  1354.                 PCIVMEUnload(DeviceExtension->driverObj);
  1355.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1356.         }
  1357.  
  1358.         device_object->Flags &= ~DO_DEVICE_INITIALIZING;
  1359.         return result;
  1360. }
  1361.  
  1362. NTSTATUS PCIVMEAddDevice(PDRIVER_OBJECT driverObj,  PDEVICE_OBJECT  pdo)
  1363.         {                                                       // AddDevice
  1364.        
  1365.         UNICODE_STRING device_name;
  1366.         UNICODE_STRING symbol_name;
  1367.         NTSTATUS result = STATUS_SUCCESS;
  1368.         //int            nPCIADAs;                              // count of PCIADAs
  1369.         DEVICE_EXT     *DeviceExtension = NULL;
  1370.         PDEVICE_OBJECT device_object;
  1371.         RtlInitUnicodeString(&device_name, L"\\Device\\PCIVME");
  1372.         KdPrint(("PCIVME AddDevice() v%d.%d\n", (DRIVER_VERSION >> 16) & 0xff, DRIVER_VERSION & 0xff));
  1373.         /* DeviceObject durch IO-Manager erzeugen */
  1374.         result = IoCreateDevice( driverObj,           // DriverObject received by the DriverEntry Call
  1375.                                                          sizeof(DEVICE_EXT),  // required Memory for the DeviceExtension
  1376.                                                          &device_name,        // Name of the device in the device-Directory
  1377.                                                          FILE_DEVICE_UNKNOWN, // Device-ID              
  1378.                                                          0,                   // Device-Characteristics normal 0
  1379.                                                          FALSE,               // TRUE : one Thread can open the driver
  1380.                                                          &device_object);     // DeviceObject returned from the IO-Manager
  1381.  
  1382.         // defines how the data are handled between user / kernel Adress-Space  
  1383.         device_object->Flags |= DO_DIRECT_IO;
  1384.  
  1385. #if 0
  1386.         // register the shutdown notification entry
  1387.     IoRegisterShutdownNotification(device_object);
  1388. #endif
  1389.  
  1390.         // anounce driver as symbolic device ---------------------------------
  1391.         if (result == STATUS_SUCCESS)
  1392.         {
  1393.                 /* now the symbolic Link is created. If there is no S.L. a program cannot connect to the driver */
  1394.                 RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
  1395.                 result = IoCreateSymbolicLink(&symbol_name,&device_name);
  1396.                 if (result != STATUS_SUCCESS)
  1397.                 {
  1398.        
  1399.                         IoDeleteDevice(device_object);
  1400.                         return result;
  1401.                 }
  1402.         }
  1403.         else
  1404.                 return result;
  1405.  
  1406.  
  1407.         DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
  1408.  
  1409.         DeviceExtension->actualIrp  = NULL;
  1410.         DeviceExtension->driverObj  = driverObj;
  1411.         DeviceExtension->nInitState = 0;
  1412.  
  1413.        
  1414.         DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(device_object, pdo);
  1415.     KdPrint(("AddDevice() OK.\n"));
  1416.  
  1417.         return result;
  1418. }
  1419.  
  1420. //------------------------------------------------------------------------
  1421. // the ultimate starting point of a driver
  1422. NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath)
  1423. {
  1424.         UNREFERENCED_PARAMETER(regPath);
  1425.        
  1426.         KdPrint(("PCIVME DriverEntry() v%d.%d\n", (DRIVER_VERSION >> 16) & 0xff, DRIVER_VERSION & 0xff));
  1427.  
  1428.         driverObj->DriverUnload = PCIVMEUnload;
  1429.         driverObj->DriverExtension->AddDevice = PCIVMEAddDevice;
  1430.         driverObj->MajorFunction[IRP_MJ_CREATE] = PCIVMEOpen;
  1431.         driverObj->MajorFunction[IRP_MJ_CLOSE] = PCIVMEClose;
  1432.         driverObj->MajorFunction[IRP_MJ_READ] = PCIVMERead;
  1433.         driverObj->MajorFunction[IRP_MJ_WRITE] = PCIVMEWrite;
  1434.         driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PCIVMEDeviceControl;
  1435. #ifdef DO_CLEANUP
  1436.         driverObj->MajorFunction[IRP_MJ_CLEANUP] = PCIVMECancel;
  1437. #endif
  1438.         driverObj->MajorFunction[IRP_MJ_SHUTDOWN] = PCIVMEShutdown;
  1439.         driverObj->MajorFunction[IRP_MJ_PNP] = PCIVMEDispatchPnp;
  1440.         return  STATUS_SUCCESS;;
  1441. }