Subversion Repositories f9daq

Rev

Rev 41 | 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. #ifndef DWORD
  49. #define DWORD ULONG
  50. #endif
  51.  
  52. #ifndef WORD
  53. #define WORD USHORT
  54. #endif
  55.  
  56. #define CTL_INDEX(x) ((x >> 2) & 0x7FF)  // get user control code as index
  57. #define IRQ_LIST_LENGTH 128     // max count of irqs in FIFO for each file_obj
  58.  
  59. #define RESOURCE_ENTRY_COUNT 6          // WIN2000 forces to claim all entries
  60.  
  61. #define DOS_DEVICE_NAME L"\\DosDevices\\PCIVME:"
  62.  
  63. //------------------------------------------------------------------------
  64. // GLOBALS
  65. //
  66.  
  67. //------------------------------------------------------------------------
  68. // FUNCTIONS
  69. //
  70.  
  71. //------------------------------------------------------------------------
  72. // exchange the pointer to Bus Error
  73. //
  74. PBOOLEAN ExchangePointer(PBOOLEAN *current, PBOOLEAN next)
  75. {
  76.         PBOOLEAN pb;
  77.  
  78.         pb       = *current;
  79.         *current = next;
  80.  
  81.         return pb;
  82. }
  83.  
  84. //------------------------------------------------------------------------
  85. // get the vmemm number out of the filename
  86. //
  87. NTSTATUS InterpreteFileName(PCHAR name, int *nVmemm)
  88. {
  89.         char *ptr = name;
  90.     char *n   = "vmemm";
  91.         int  h = -1;  // high part
  92.         int  l = -1;  // low part
  93.  
  94.         if (*ptr == '\\') ptr++; // jump over leading ...
  95.  
  96.     while (*n)                           // compare the basename
  97.           if (*n == tolower(*ptr))     
  98.           {
  99.                   n++;
  100.                   ptr++;
  101.           }
  102.           else
  103.                   return STATUS_NO_SUCH_FILE;
  104.  
  105.         h = *ptr - '0';                  // get the number
  106.         ptr++;
  107.         l = *ptr - '0';
  108.  
  109.         if (*ptr == 0)                   // still over the end ??
  110.         {
  111.                 l = h;
  112.                 h = 0;
  113.         }
  114.         else
  115.           ptr++;
  116.  
  117.         if ((h < 0) || (l < 0) || (*ptr != 0))  // anything wrong ??
  118.                   return STATUS_NO_SUCH_FILE;
  119.  
  120.         *nVmemm = (h * 10) + l;  // calculate number
  121.  
  122.         if (*nVmemm >= PCIVME_MAX_VMEMM) // out of range ??
  123.                   return STATUS_NO_SUCH_FILE;
  124.  
  125.         return STATUS_SUCCESS;
  126. }
  127.  
  128. //------------------------------------------------------------------------
  129. // the ultimate driver unload
  130. VOID PCIVMEUnload(PDRIVER_OBJECT driverObj)
  131. {
  132.         int              i;
  133.         UNICODE_STRING symbol_name;
  134.         DEVICE_EXT *ext = (DEVICE_EXT*)(driverObj->DeviceObject->DeviceExtension);
  135.         int         nPCIADAs = ext->nPCIADAs;
  136.         PCIADA      *pciada;
  137.  
  138.     KdPrint(("PCIVMEUnload()\n"));
  139.  
  140.         switch (ext->nInitState)
  141.         {
  142.                 case 8:
  143.                 case 7:
  144.                         // stop interrupts and shut off
  145.                         PCIVMEDeInitPCIADAs(driverObj->DeviceObject);
  146.                         PCIVMEDisConnectInterrupt(driverObj->DeviceObject);
  147.  
  148.                         // remove interrupt lists
  149.                         for (i = 0; i < nPCIADAs; i++)
  150.                         {
  151.                                 pciada = &ext->pciada[i];
  152.  
  153.                                 // removeQueueFromList(...)
  154.                                 while (IsListEmpty(&pciada->IrqListList) == FALSE)
  155.                                 {
  156.                                         PLIST_ENTRY pList;
  157.                                         FIFO_LIST   *next;
  158.                                
  159.                                         KdPrint(("RemoveHeadList(0x%08x)\n", &pciada->IrqListList));
  160.                                         pList = RemoveHeadList(&pciada->IrqListList);
  161.                                         next  = CONTAINING_RECORD(pList, FIFO_LIST, entry);
  162.  
  163.                                         ExFreePool((PVOID)next);
  164.                                 }
  165.                         }
  166.                 case 6:
  167.                         // InitializeIRPQueue has no counterpart
  168.                 case 5:
  169.                         // KeInitializeDpc has no counterpart
  170.                 case 4:
  171.                         // release io spaces
  172.                         for (i = 0; i < nPCIADAs; i++)
  173.                         {
  174.                                 pciada = &ext->pciada[i];
  175.  
  176.                                 if (pciada->pvVirtLcr != NULL)
  177.                                         MmUnmapIoSpace(pciada->pvVirtLcr, LCR_SPACE);
  178.                                 if (pciada->pvVirtIfr != NULL)
  179.                                         MmUnmapIoSpace(pciada->pvVirtIfr, IFR_SPACE);
  180.                         }
  181.                 case 3:
  182.                         // HalGetInterruptVector has no counterpart
  183.                 case 2:
  184.                         // HalTranslateBusAddress has no counterpart
  185.                 case 1:
  186.                         PCIVMEFreeResources(driverObj->DeviceObject);
  187.                 default:
  188.                 case 0:
  189.                         RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
  190.  
  191.                         // delete the symbolicLink in the registry
  192.                         IoDeleteSymbolicLink( &symbol_name);
  193.  
  194.                         // delete the deviceObject
  195.                         IoDeleteDevice(driverObj->DeviceObject);
  196.         }
  197.  
  198.         KdPrint(("PCIVMEUnload() OK.\n"));
  199. }
  200.  
  201.  
  202. //------------------------------------------------------------------------
  203. // called at CreateFile()
  204. NTSTATUS PCIVMEOpen(PDEVICE_OBJECT deviceObj, PIRP Irp)
  205. {
  206.         NTSTATUS result = STATUS_SUCCESS;
  207.     ANSI_STRING name;
  208.     int nVmemm;
  209.         int i;
  210.         DEVICE_EXT      *pDevExt = (DEVICE_EXT *)(deviceObj->DeviceExtension);
  211.         PCIADA      *pciada;
  212.         FILE_OBJ        *file_obj = (FILE_OBJ *)NULL;
  213.  
  214.         name.Buffer = NULL;
  215.     name.MaximumLength = 80;
  216.  
  217.         result = RtlUnicodeStringToAnsiString(&name, &(Irp->Tail.Overlay.OriginalFileObject->FileName), TRUE);
  218.         if (result != STATUS_SUCCESS) goto fin;
  219.  
  220.         result = InterpreteFileName(name.Buffer, &nVmemm);
  221.     if (result != STATUS_SUCCESS) goto fin;
  222.  
  223.     KdPrint(("PCIVMEOpen(%d)\n", nVmemm));
  224.         RtlFreeAnsiString(&name);
  225.  
  226.     file_obj = (FILE_OBJ *)ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJ),'nepo');
  227.         if (file_obj == (FILE_OBJ *)NULL)
  228.         {
  229.                 result = STATUS_NO_MEMORY;
  230.                 goto fin;
  231.         }
  232.  
  233.         file_obj->uwAssociatedVMEMM = (USHORT) nVmemm;
  234.         file_obj->bAddressModifier  = 0x39;
  235.         file_obj->bAccessType       = BYTE_ACCESS;
  236.         file_obj->bIncrement        = BYTE_ACCESS; // increments each byte
  237.         file_obj->dwAccessBase      = 0;           // normal setting for all but extended
  238.  
  239.         file_obj->bQueueIrq                     = FALSE;
  240.         result = InitializeFIFO(IRQ_LIST_LENGTH, &file_obj->pIrqListHandle);
  241.         if (result != STATUS_SUCCESS) goto fin;
  242.  
  243.     Irp->Tail.Overlay.OriginalFileObject->FsContext = (PVOID)file_obj;
  244.  
  245.         result = PCIVMEScanVMEMM(deviceObj);
  246.         if (result != STATUS_SUCCESS) goto fin;
  247.  
  248.         for (i = 0; i < pDevExt->nPCIADAs; i++)
  249.         {
  250.           pciada = &pDevExt->pciada[i];
  251.  
  252.           if (pciada->wModuleNumber == nVmemm)
  253.           {
  254.                   pDevExt->vmemm[nVmemm] = pciada; // create association
  255.                   pciada->dwLinkCount++;
  256.                   break;
  257.           }
  258.         }
  259.  
  260.         if (i >= pDevExt->nPCIADAs)
  261.         {
  262.                 result = STATUS_NO_SUCH_FILE;
  263.                 goto fin;
  264.         }
  265.  
  266.         fin:
  267.         Irp->IoStatus.Status = result;
  268.         Irp->IoStatus.Information = 0;
  269.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  270.  
  271.         // be careful when releasing allocated memory !
  272.         if (result != STATUS_SUCCESS)
  273.                 if (file_obj != (FILE_OBJ *)NULL)
  274.                         if (file_obj->pIrqListHandle != (PVOID)NULL)
  275.                                 DestroyFIFO(file_obj->pIrqListHandle);
  276.  
  277.         return result;
  278. }
  279.  
  280. //------------------------------------------------------------------------
  281. // called at close()
  282. NTSTATUS PCIVMEClose(PDEVICE_OBJECT deviceObj, PIRP Irp)
  283. {
  284.         DEVICE_EXT      *pDevExt  = (DEVICE_EXT *)(deviceObj->DeviceExtension);
  285.         FILE_OBJ    *file_obj = (FILE_OBJ *)NULL;
  286.         PCIADA      *pciada;                   
  287.  
  288.         file_obj = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  289.  
  290.     KdPrint(("PCIVMEClose(%d)\n", file_obj->uwAssociatedVMEMM));
  291.  
  292.         if (file_obj != (FILE_OBJ *)NULL)
  293.         {
  294.                 pciada = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  295.                 pciada->dwLinkCount--;
  296.  
  297.                 // remove the ListEntry(s) associated with this path
  298.         removeQueueFromList(file_obj, pciada);
  299.  
  300.             // empty and remove the interrupt queue (if there is anything stored)
  301.                 DestroyFIFO(file_obj->pIrqListHandle);
  302.                
  303.                 ExFreePool(file_obj);
  304.                 Irp->Tail.Overlay.OriginalFileObject->FsContext = (FILE_OBJ *)NULL;
  305.         }
  306.  
  307.         KdPrint(("PCIVMEClose OK\n"));
  308.  
  309.     Irp->IoStatus.Status = STATUS_SUCCESS;
  310.         Irp->IoStatus.Information = 0;
  311.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  312.  
  313.         return STATUS_SUCCESS;
  314. }
  315.  
  316. //------------------------------------------------------------------------
  317. // called at
  318. NTSTATUS PCIVMEShutdown(PDEVICE_OBJECT deviceObj, PIRP  irp  )
  319. {
  320.         UNREFERENCED_PARAMETER(irp);
  321.  
  322.     KdPrint(("PCIVMEShutdown()\n"));
  323.  
  324.         // deinit interfaces and interrupts
  325.         PCIVMEDeInitPCIADAs(deviceObj);
  326.  
  327.     KdPrint(("PCIVMEShutdown() OK\n"));
  328.  
  329.         return STATUS_SUCCESS;
  330. }
  331.  
  332. //------------------------------------------------------------------------
  333. // called at ioctl()
  334. NTSTATUS PCIVMEDeviceControl(PDEVICE_OBJECT deviceObj, PIRP Irp)
  335. {
  336.         PIO_STACK_LOCATION IrpStack;
  337.         int   nIndex;
  338.  
  339.         IrpStack  = IoGetCurrentIrpStackLocation(Irp);
  340.         nIndex    = CTL_INDEX(IrpStack->Parameters.DeviceIoControl.IoControlCode);
  341.  
  342.     KdPrint(("PCIVMEDeviceControl(%d / 0x%08x)\n", nIndex, Irp->Tail.Overlay.OriginalFileObject));
  343.  
  344.         if (nIndex > CTL_INDEX(PCIVME_LAST_CTL_CODE))
  345.         {
  346.                 Irp->IoStatus.Status      = STATUS_UNSUCCESSFUL;
  347.                 Irp->IoStatus.Information = 0;
  348.                 IoCompleteRequest(Irp,IO_NO_INCREMENT);
  349.  
  350.         KdPrint(("PCIVMEDeviceControl() FAIL.\n"));
  351.  
  352.                 return STATUS_UNSUCCESSFUL;
  353.         }
  354.  
  355.         return ioctl[nIndex](deviceObj, Irp, IrpStack);
  356. }
  357.  
  358.  
  359. //------------------------------------------------------------------------
  360. // called at read()
  361. NTSTATUS PCIVMERead(PDEVICE_OBJECT device_Obj, PIRP Irp)
  362. {
  363.         NTSTATUS        Status        = STATUS_SUCCESS;
  364.         PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  365.         PVOID           pOutputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
  366.         LARGE_INTEGER *fileOffset = (LARGE_INTEGER *)&Irp->Tail.Overlay.OriginalFileObject->CurrentByteOffset;
  367.         FILE_OBJ        *file_obj           = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  368.         DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
  369.   PCIADA      *pciada             = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  370.         register ULONG Address  = IrpStack->Parameters.Read.ByteOffset.LowPart  + file_obj->dwAccessBase;  
  371.         ULONG storeLength                   = 0;
  372.         PBOOLEAN pbPrevBusError;
  373.  
  374.         KdPrint(("PCIVMERead(%d)\n", file_obj->uwAssociatedVMEMM));
  375.  
  376.         // do here in between what has to be done -----------------
  377.   if (Address & file_obj->dwAddressMask)     // don't do unaligned transfers
  378.                 Status = STATUS_DATATYPE_MISALIGNMENT;
  379.         else
  380.         {
  381.                 register ULONG Length = IrpStack->Parameters.Read.Length;    
  382.                 register ULONG blockLength;
  383.                 register ULONG pageAddress;
  384.                 register ULONG toNextPage;
  385.                 KIRQL              oldIrql;
  386.  
  387.                 Length     &= ~file_obj->dwAddressMask; // align to integer increments
  388.                 storeLength = Length;
  389.                
  390.                 // lock other users out
  391.                 KeAcquireSpinLock(&pciada->AccessLock, &oldIrql);
  392.  
  393.                 // check for modifier
  394.                 if (pciada->bModifier != file_obj->bAddressModifier)
  395.                 {
  396.                         WRITE_REGISTER_UCHAR(pciada->pbModifier, file_obj->bAddressModifier);
  397.                         pciada->bModifier = file_obj->bAddressModifier;
  398.                 }
  399.                
  400.                 // do the read ---
  401.                 file_obj->bBusError = FALSE;
  402.                 pbPrevBusError = ExchangePointer(&pciada->pbBusError, &file_obj->bBusError);
  403.                 while (Length)
  404.                 {
  405.                         pageAddress = Address & ~VME_ADR_MASK;
  406.                         if (pageAddress != pciada->dwVMEPage)
  407.                         {
  408.                                 WRITE_REGISTER_ULONG(pciada->pdwVMEAdr, pageAddress);
  409.                                 pciada->dwVMEPage = pageAddress;
  410.                         }
  411.  
  412.                         toNextPage  = (pageAddress + VME_ADR_MASK + 1) - Address;
  413.                         blockLength = (toNextPage < Length) ? toNextPage : Length;
  414.  
  415.                         KdPrint(("Address 0x%08x, blockLength %d, Length %d\n",
  416.                                                                                 Address, blockLength, Length));
  417.  
  418.                         file_obj->fRead(pOutputBuffer , blockLength, (PVOID)((PUCHAR)pciada->pvVME + (Address & VME_ADR_MASK)));
  419.  
  420.                         Length  -= blockLength;
  421.                         Address += blockLength;
  422.                         pOutputBuffer = (PVOID)((PUCHAR)pOutputBuffer + blockLength);
  423.                 }
  424.  
  425.                 // release the lock
  426.                 KeReleaseSpinLock(&pciada->AccessLock, oldIrql);
  427.                 ExchangePointer(&pciada->pbBusError, pbPrevBusError);
  428.                 if (file_obj->bBusError) Status = STATUS_ACCESS_VIOLATION;
  429.  
  430.             if (file_obj->bIncrement)  // only when increment to next is on
  431.                         *fileOffset =
  432.                                 RtlLargeIntegerAdd(*fileOffset, RtlConvertUlongToLargeInteger(storeLength));
  433.         }
  434.         // do here in between what has to be done end -------------
  435.  
  436.         Irp->IoStatus.Status      = Status;  
  437.         Irp->IoStatus.Information = storeLength;  
  438.         IoCompleteRequest(Irp,IO_NO_INCREMENT);  
  439.  
  440.     KdPrint(("PCIVMERead(), Status = 0x%08x\n", Status));
  441.  
  442.         return Status;
  443. }
  444.  
  445.  
  446. //------------------------------------------------------------------------
  447. // called at write()
  448. NTSTATUS PCIVMEWrite(PDEVICE_OBJECT device_Obj, PIRP Irp)
  449. {
  450.         NTSTATUS        Status        = STATUS_SUCCESS;
  451.         PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  452.         PVOID           pInputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
  453.         LARGE_INTEGER *fileOffset = (LARGE_INTEGER *)&Irp->Tail.Overlay.OriginalFileObject->CurrentByteOffset;
  454.         FILE_OBJ        *file_obj           = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  455.         DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
  456.   PCIADA      *pciada             = pDevExt->vmemm[file_obj->uwAssociatedVMEMM];
  457.         register ULONG Address  = IrpStack->Parameters.Write.ByteOffset.LowPart + file_obj->dwAccessBase;  
  458.         ULONG storeLength                   = 0;
  459.         PBOOLEAN pbPrevBusError;
  460.  
  461.         KdPrint(("PCIVMEWrite(%d)\n", file_obj->uwAssociatedVMEMM));
  462.  
  463.         // do here in between what has to be done -----------------
  464.   if (Address & file_obj->dwAddressMask)     // don't do unaligned transfers
  465.                 Status = STATUS_DATATYPE_MISALIGNMENT;
  466.         else
  467.         {
  468.                 register ULONG Length = IrpStack->Parameters.Write.Length;    
  469.                 register ULONG blockLength;
  470.                 register ULONG pageAddress;
  471.                 register ULONG toNextPage;
  472.                 KIRQL              oldIrql;
  473.  
  474.                 Length     &= ~file_obj->dwAddressMask; // align to integer increments
  475.                 storeLength = Length;
  476.                                                        // check for modifier
  477.                 // lock other users out
  478.                 KeAcquireSpinLock(&pciada->AccessLock, &oldIrql);
  479.  
  480.                 if (pciada->bModifier != file_obj->bAddressModifier)
  481.                 {
  482.                         WRITE_REGISTER_UCHAR(pciada->pbModifier, file_obj->bAddressModifier);
  483.                         pciada->bModifier = file_obj->bAddressModifier;
  484.                 }
  485.                
  486.                 // do the read ---
  487.                 file_obj->bBusError = FALSE;
  488.                 pbPrevBusError = ExchangePointer(&pciada->pbBusError, &file_obj->bBusError);
  489.                 while (Length)
  490.                 {
  491.                         pageAddress = Address & ~VME_ADR_MASK;
  492.                         if (pageAddress != pciada->dwVMEPage)
  493.                         {
  494.                                 WRITE_REGISTER_ULONG(pciada->pdwVMEAdr, pageAddress);
  495.                                 pciada->dwVMEPage = pageAddress;
  496.                         }
  497.  
  498.                         toNextPage  = (pageAddress + VME_ADR_MASK + 1) - Address;
  499.                         blockLength = (toNextPage < Length) ? toNextPage : Length;
  500.  
  501.                         KdPrint(("Address 0x%08x, blockLength %d, Length %d\n",
  502.                                                                                 Address, blockLength, Length));
  503.  
  504.                         file_obj->fWrite((PVOID)((PUCHAR)pciada->pvVME + (Address & VME_ADR_MASK)) , blockLength, pInputBuffer);
  505.  
  506.                         Length  -= blockLength;
  507.                         Address += blockLength;
  508.                         pInputBuffer = (PVOID)((PUCHAR)pInputBuffer + blockLength);
  509.                 }
  510.  
  511.                 // release the lock
  512.                 KeReleaseSpinLock(&pciada->AccessLock, oldIrql);
  513.                 ExchangePointer(&pciada->pbBusError, pbPrevBusError);
  514.                 if (file_obj->bBusError) Status = STATUS_ACCESS_VIOLATION;
  515.  
  516.                 if (file_obj->bIncrement)  // only when increment to next is on
  517.                         *fileOffset =   RtlLargeIntegerAdd(*fileOffset, RtlConvertUlongToLargeInteger(storeLength));
  518.         }
  519.         // do here in between what has to be done end -------------
  520.  
  521.         Irp->IoStatus.Status      = Status;  
  522.         Irp->IoStatus.Information = storeLength;  
  523.         IoCompleteRequest(Irp,IO_NO_INCREMENT);  
  524.  
  525.     KdPrint(("PCIVMEWrite(), Status = 0x%08x\n", Status));
  526.  
  527.         return Status;
  528. }
  529.  
  530. #ifdef DO_CLEANUP
  531. //------------------------------------------------------------------------
  532. // called at cancel of a path
  533. NTSTATUS PCIVMECancel(PDEVICE_OBJECT device_Obj, PIRP Irp)
  534. {
  535.         FILE_OBJ *file_obj = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
  536.         PIRP     pIrpCancel;
  537.  
  538.         KdPrint(("PCIVMECancel()\n"));
  539.  
  540.         // remove all queued IRPs of this file_obj
  541.         do
  542.         {
  543.                 pIrpCancel = RemoveIRPfromQueue(device_Obj, file_obj);
  544.  
  545.                 if (pIrpCancel == (PIRP)NULL)
  546.                 {
  547.                         IoReleaseCancelSpinLock(pIrpCancel->CancelIrql);
  548.                         break;
  549.                 }
  550.                 else
  551.                 {
  552.                         IoAcquireCancelSpinLock(pIrpCancel->CancelIrql);
  553.  
  554.                         // mark irp as not pending
  555.                         IoSetCancelRoutine(pIrpCancel, NULL);
  556.  
  557.                         IoReleaseCancelSpinLock(pIrpCancel->CancelIrql);
  558.  
  559.                         pIrpCancel->IoStatus.Status = STATUS_CANCELLED;
  560.                         pIrpCancel->IoStatus.Information = 0;
  561.                 }
  562.         } while (pIrpCancel != (PIRP)NULL);
  563.  
  564.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  565.  
  566.         KdPrint(("PCIVMECancel(OK)\n"));
  567.  
  568.         return STATUS_SUCCESS;
  569. }
  570. #endif
  571.  
  572. //------------------------------------------------------------------------
  573. // search for pciada's
  574. //
  575. NTSTATUS SearchDevices(PDEVICE_OBJECT device_Obj)
  576. {
  577.   PCI_SLOT_NUMBER   SlotNumber;
  578.   PCI_COMMON_CONFIG pci_config;
  579.   PCIADA            *pciada;
  580.   ULONG             length;
  581.   int               *found;
  582.   int               i,j,k;
  583.  
  584.   KdPrint(("SearchDevices()\n"));
  585.  
  586.   // prepare structures ----------------------------------------
  587.   found = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
  588.   *found = 0;
  589.   for (i = 0; i < PCIVME_MAX_PCIADA; i++)
  590.   {
  591.         pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  592.  
  593.         pciada->Bus                = -1;
  594.     pciada->Slot.u.AsULONG     = 0xFFFFFFFF;
  595.   }
  596.  
  597.   // search for pciada's ---------------------------------------
  598.   SlotNumber.u.bits.Reserved = 0;
  599.  
  600.   for (j = 0; j < PCI_MAX_BUSES; j++)
  601.   {
  602.     for (i = 0; i < PCI_MAX_DEVICES; i++)
  603.         {
  604.           SlotNumber.u.bits.DeviceNumber = i;
  605.           for (k = 0; k < PCI_MAX_FUNCTION; k++)
  606.           {
  607.                 SlotNumber.u.bits.FunctionNumber = k;
  608.             length = HalGetBusData( PCIConfiguration,         // Bustype
  609.                                                             j,                                    // PCI-Busnumber
  610.                                                             SlotNumber.u.AsULONG,     // Slotnumber
  611.                                                             (PVOID) &(pci_config),    // Pointer for the PCI-Information
  612.                                                             sizeof(PCI_COMMON_CONFIG) );
  613.  
  614.                 if ((pci_config.VendorID    == PCIVME_VENDOR_ID) &&
  615.                         (pci_config.DeviceID    == PCIVME_DEVICE_ID) &&
  616.                         (pci_config.u.type0.SubSystemID == PCIVME_SUBSYS_ID) &&
  617.                         (pci_config.u.type0.SubVendorID == PCIVME_SUBVEN_ID) &&
  618.                         (pci_config.u.type0.BaseAddresses[2]))
  619.                 {
  620.                pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[*found];
  621.  
  622.                memcpy(&pciada->PCIDevice, &pci_config, sizeof(pci_config));
  623.                    pciada->Slot = SlotNumber;
  624.                    pciada->Bus  = j;
  625.  
  626.                    KdPrint(("PCIADA found @ Bus/Slot %d/%d.\n", pciada->Bus, pciada->Slot.u.AsULONG));
  627.  
  628.                    (*found)++;
  629.                    if (*found >= PCIVME_MAX_PCIADA) return STATUS_SUCCESS;
  630.                 }
  631.           }
  632.         }              
  633.   }
  634.  
  635.   return STATUS_SUCCESS;
  636. }
  637.  
  638. //---------------------------------------------------------------
  639. // function to call for bug fix of PLX9050 build in bug
  640. //
  641. NTSTATUS PLX9050BugFix(PDEVICE_OBJECT device_Obj)
  642. {
  643.         DEVICE_EXT *DeviceExtension = (DEVICE_EXT*)device_Obj->DeviceExtension;
  644.         int i;
  645.         ULONG dwData;
  646.         PCIADA *pciada;
  647.  
  648.         KdPrint(("PLX9050BugFix()\n"));
  649.  
  650.         for (i = 0; i < DeviceExtension->nPCIADAs; i++)
  651.         {
  652.                 pciada = &DeviceExtension->pciada[i];
  653.  
  654.                 if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[0]) & 0x80)
  655.                 {      
  656.                         KdPrint(("Changing address 0:0x%p with 4:0x%p\n",
  657.                                 pciada->PCIDevice.u.type0.BaseAddresses[0],
  658.                                 pciada->PCIDevice.u.type0.BaseAddresses[4]));
  659.  
  660.                         pciada->PCIDevice.u.type0.BaseAddresses[0] =           // exchange
  661.                                 pciada->PCIDevice.u.type0.BaseAddresses[4];
  662.                         pciada->PCIDevice.u.type0.BaseAddresses[4] = dwData;
  663.  
  664.                         if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  665.                                   pciada->Slot.u.AsULONG,
  666.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[0],
  667.                                                 0x10, 4) != 4)
  668.                         return STATUS_UNSUCCESSFUL;
  669.  
  670.                         if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  671.                                   pciada->Slot.u.AsULONG,
  672.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[4],
  673.                                                 0x20, 4) != 4)
  674.                         return STATUS_UNSUCCESSFUL;
  675.                 }
  676.      
  677.                 if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[1]) & 0x80)
  678.                 {
  679.                         KdPrint(("Changing address 1:0x%p with 5:0x%p\n",
  680.                                 pciada->PCIDevice.u.type0.BaseAddresses[1],
  681.                                 pciada->PCIDevice.u.type0.BaseAddresses[5]));
  682.  
  683.                   pciada->PCIDevice.u.type0.BaseAddresses[1] =           // exchange
  684.                                 pciada->PCIDevice.u.type0.BaseAddresses[5];
  685.                   pciada->PCIDevice.u.type0.BaseAddresses[5] = dwData;
  686.  
  687.                   if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  688.                                   pciada->Slot.u.AsULONG,
  689.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[1],
  690.                                                 0x14, 4) != 4)
  691.                         return STATUS_UNSUCCESSFUL;
  692.  
  693.                   if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
  694.                                   pciada->Slot.u.AsULONG,
  695.                                         (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[5],
  696.                                                 0x24, 4) != 4)
  697.                         return STATUS_UNSUCCESSFUL;
  698.                 }
  699.         }
  700.  
  701.         return STATUS_SUCCESS;
  702. }
  703.  
  704.  
  705. //------------------------------------------------------------------------
  706. //  reserve resources for PCIADAs
  707. //
  708. NTSTATUS PCIVMEExtractResources(PCIADA *pciada, PCM_RESOURCE_LIST pList)
  709. {
  710.         PCM_RESOURCE_LIST pResourceList;
  711.         PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
  712.         PCM_PARTIAL_RESOURCE_LIST pPartialList;
  713.         PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialDescriptor;
  714.         int i;
  715.         int bug = 0;
  716.  
  717.         KdPrint(("PCIVMEExtractResources()\n"));
  718.  
  719.         pResourceList   = pList;
  720.         pFullDescriptor = pResourceList->List;
  721.         pPartialList    = &pFullDescriptor->PartialResourceList;
  722.  
  723.         for (i=0; i<(int)pPartialList->Count; i++)
  724.         {
  725.                 pPartialDescriptor = &pPartialList->PartialDescriptors[i];
  726.                 switch (pPartialDescriptor->Type)
  727.                 {
  728.                         case CmResourceTypeInterrupt:
  729.                                 pciada->Irql     = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
  730.                                 pciada->Vector   = pPartialDescriptor->u.Interrupt.Vector;
  731.                                 pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
  732.  
  733.                                 KdPrint(("Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
  734.                                         pciada->Irql, pciada->Vector, pciada->Affinity));
  735.                                 break;
  736.                         case CmResourceTypeDma:
  737.                                 KdPrint(("Dma    : \n"));
  738.                                 break;
  739.                         case CmResourceTypePort:
  740.  
  741.                                 KdPrint(("Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
  742.                                 break;
  743.                         case CmResourceTypeMemory:
  744.                                 // special handling of PLXBUG here because of WIN2000
  745.                                 // WIN2000 doesn't recognize late address changes
  746.                                 if (!bug)
  747.                                 {
  748.                                         if (i == 0)
  749.                                         {
  750.                                                 pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  751.  
  752.                                                 if (pciada->pvPhysLcr.LowPart & 0x80)
  753.                                                         bug = 1;
  754.                                         }
  755.                                 }
  756.                                 else
  757.                                 {
  758.                                         if (i == 3)
  759.                                                 pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
  760.                                 }
  761.  
  762.                                 if (i == 2)
  763.                                         pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
  764.  
  765.                                 KdPrint(("Memory : 0x%p\n", (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
  766.                                 break;
  767.                 }
  768.         }
  769.  
  770.         if (pciada->Irql == 0)
  771.                 return STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
  772.  
  773.         KdPrint(("PCIVMEExtractResources() OK.\n"));
  774.  
  775.         return STATUS_SUCCESS;
  776. }
  777.  
  778. NTSTATUS PCIVMEReserveResources(PDEVICE_OBJECT device_Obj)
  779. {
  780.         PCM_RESOURCE_LIST pList = NULL;
  781.         NTSTATUS result = STATUS_SUCCESS;
  782.         int i;
  783.         DEVICE_EXT *pDevExt = (DEVICE_EXT*)(device_Obj->DeviceExtension);
  784.         int nPCIADAs = pDevExt->nPCIADAs;
  785.         PCIADA *pciada;
  786.     UNICODE_STRING DriverClassName;
  787.    
  788.         KdPrint(("PCIVMEReserveResources()\n"));
  789.  
  790.         // prepare resource claiming
  791.         RtlInitUnicodeString(&DriverClassName, L"PCICC32");
  792.  
  793.         // cycle through all busses and slots assigned to PCIADAs
  794.         for (i = 0; i < nPCIADAs; i++)
  795.     {
  796.                 pciada = &pDevExt->pciada[i];
  797.  
  798.                 result = HalAssignSlotResources(NULL, &DriverClassName, device_Obj->DriverObject, device_Obj,
  799.                         PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, &pList);
  800.  
  801.                 if (result != STATUS_SUCCESS)
  802.                         break;
  803.  
  804.                 result = PCIVMEExtractResources(pciada, pList);
  805.  
  806.                 if (result != STATUS_SUCCESS)
  807.                         break;
  808.         }
  809.  
  810.         // its my part to free allocated resources
  811.         if (pList != NULL) ExFreePoolWithTag(pList,'nepo');
  812.  
  813.         KdPrint(("PCIVMEReserveResources(0x%08x)\n", result));
  814.  
  815.         return result;
  816. };
  817.  
  818.  
  819. //------------------------------------------------------------------------
  820. //  free resources from PCIADAs
  821. //
  822. NTSTATUS PCIVMEFreeResources(PDEVICE_OBJECT device_Obj)
  823. {
  824.         CM_RESOURCE_LIST ResList;
  825.         BOOLEAN          bConflict;
  826.     UNICODE_STRING   DriverClassName;
  827.  
  828.     KdPrint(("PCIVMEFreeResources()\n"));
  829.  
  830.         RtlInitUnicodeString(&DriverClassName, L"PCIVME");
  831.  
  832.         ResList.Count = 0;
  833.  
  834.         IoReportResourceUsage(&DriverClassName, device_Obj->DriverObject,
  835.                                          &ResList, sizeof(ResList), device_Obj,
  836.                                                                          NULL, 0, FALSE, &bConflict);
  837.         return STATUS_SUCCESS;
  838. };
  839.  
  840.  
  841. //------------------------------------------------------------------------
  842. //  translate memory resources to neutral for PCIADAs
  843. //
  844. NTSTATUS PCIVMETranslateBusAddresses(PDEVICE_OBJECT device_Obj)
  845. {
  846.         int              i;
  847.         NTSTATUS         result = STATUS_SUCCESS;
  848.         int nPCIADAs = ((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
  849.         ULONG            memType0, memType2;
  850.         PCIADA           *pciada;
  851.  
  852.     KdPrint(("TranslateBusAddresseses()\n"));
  853.         for (i = 0; i < nPCIADAs; i++)
  854.         {
  855.       pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  856.  
  857.           memType0 = memType2 = 0;
  858.  
  859.           if (!(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysLcr, &memType0,
  860.                                                                &pciada->pvPhysLcr)) ||
  861.               !(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysIfr, &memType2,
  862.                                                                &pciada->pvPhysIfr)))
  863.           {
  864.                   result = STATUS_UNSUCCESSFUL;
  865.                   break;
  866.           }
  867.  
  868.           if ((memType0) || (memType2))
  869.           {
  870.                   result = STATUS_UNSUCCESSFUL;
  871.                   break;
  872.           }
  873.         }
  874.         return result;
  875. }
  876.  
  877. //------------------------------------------------------------------------
  878. //  map address spaces to virtual addresses
  879. //
  880. NTSTATUS PCIVMEMapIOspace(PDEVICE_OBJECT device_Obj)
  881. {
  882.         int              i;
  883.         DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
  884.         int                              nPCIADAs = pDevExt->nPCIADAs;
  885.         PCIADA           *pciada;
  886.  
  887.         KdPrint(("PCIVMEMapIOspace()\n"));
  888.  
  889.         for (i = 0; i < nPCIADAs; i++)
  890.         {
  891.        pciada = &pDevExt->pciada[i];
  892.  
  893.        if ((pciada->pvVirtLcr = MmMapIoSpace(pciada->pvPhysLcr, LCR_SPACE, FALSE)) == NULL)
  894.           return STATUS_UNSUCCESSFUL;
  895.        if ((pciada->pvVirtIfr = MmMapIoSpace(pciada->pvPhysIfr, IFR_SPACE, FALSE)) == NULL)
  896.           return STATUS_UNSUCCESSFUL;
  897.  
  898.            KdPrint(("PCIADA %d: LCR 0x%08x IFR 0x%08x\n",
  899.                                          i, pciada->pvVirtLcr, pciada->pvVirtIfr));
  900.  
  901.            pciada->pwIntCSR = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x4C);
  902.            pciada->pwCntrl  = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x50);
  903.         }
  904.  
  905.         return STATUS_SUCCESS;
  906. }
  907.  
  908.  
  909. //------------------------------------------------------------------------
  910. //  initializes and registers a DPC routine for each pciada
  911. //
  912. NTSTATUS InitializeCustomDPCObjects(PDEVICE_OBJECT device_object)
  913. {
  914.         int              i;
  915.         int nPCIADAs = ((DEVICE_EXT*)(device_object->DeviceExtension))->nPCIADAs;
  916.         PCIADA           *pciada;
  917.  
  918.         KdPrint(("InitializeCustomDPCObject()\n"));
  919.  
  920.         for (i = 0; i < nPCIADAs; i++)
  921.         {
  922.                 pciada = &((DEVICE_EXT*)(device_object->DeviceExtension))->pciada[i];
  923.                 KeInitializeDpc(&pciada->kDPCobj, fMyDefferedRoutine, (PVOID)device_object);
  924.         }
  925.  
  926.         return STATUS_SUCCESS;
  927. }
  928.  
  929. //------------------------------------------------------------------------
  930. //  initializes the queue for storing IRPs waiting for vectors
  931. //
  932. NTSTATUS InitializeIRPQueue(PDEVICE_OBJECT device_Obj)
  933. {
  934.         DEVICE_EXT *pDevExt = ((DEVICE_EXT*)(device_Obj->DeviceExtension));
  935.  
  936.         KdPrint(("InitializeIRPQueue()\n"));
  937.  
  938.         KeInitializeSpinLock(&pDevExt->IRPLock);
  939.         InitializeListHead(&pDevExt->IRPList);
  940.  
  941.         return STATUS_SUCCESS;
  942. }
  943.  
  944. //------------------------------------------------------------------------
  945. // init structures a.s.o.
  946. //
  947. VOID PCIVMESoftInit(PDEVICE_OBJECT device_Obj)
  948. {
  949.         int i;
  950.         PCIADA *pciada;
  951.  
  952.         for (i = 0; i < PCIVME_MAX_PCIADA; i++)
  953.         {
  954.                 pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
  955.  
  956.                 pciada->pvPhysLcr.QuadPart = pciada->pvPhysIfr.QuadPart = 0;
  957.                 pciada->pvVirtLcr = pciada->pvVirtIfr = NULL;
  958.  
  959.                 pciada->bConnected     = FALSE;   // connection still not verified
  960.                 pciada->bWordMode      = TRUE;
  961.                 pciada->bSysControl    = FALSE;
  962.                 pciada->wModuleNumber  = 0xFFFF;
  963.                 pciada->wFPGAVersion   = 0xFFFF;
  964.                 pciada->wModuleType    = 1;       // always VMEMM
  965.  
  966.                 pciada->InterruptObject = NULL;
  967.                 pciada->Irql                    = 0;
  968.                 pciada->Vector          = 0;
  969.                 pciada->Affinity                = 0;
  970.  
  971.                 pciada->dwLinkCount     = 0;
  972.                                        
  973.                 KeInitializeSpinLock(&pciada->IrqListLock);
  974.                 KeInitializeSpinLock(&pciada->AccessLock);
  975.  
  976.                 InitializeListHead(&pciada->IrqListList);  // start of list of irq fifos
  977.  
  978.                 pciada->nInterruptHandlers = 0;
  979.         }
  980.  
  981.         // no vmemm associated to any PCIADA
  982.         for (i = 0; i < PCIVME_MAX_VMEMM; i++)
  983.           ((DEVICE_EXT*)(device_Obj->DeviceExtension))->vmemm[i] = NULL;
  984. }
  985.  
  986. //------------------------------------------------------------------------
  987. // the ultimate starting point of a driver
  988. NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath  )
  989. {
  990.         UNREFERENCED_PARAMETER(regPath);
  991.         PDEVICE_OBJECT device_object;                   // pointer to the device object
  992.         UNICODE_STRING device_name;
  993.         UNICODE_STRING symbol_name;
  994.         NTSTATUS result = STATUS_SUCCESS;
  995.         int            nPCIADAs;                                // count of PCIADAs
  996.         DEVICE_EXT     *DeviceExtension = NULL;
  997.  
  998.     KdPrint(("DriverEntry() ---%d.%d---------------------------------\n", (DRIVER_VERSION >> 16) & 0xff, DRIVER_VERSION & 0xff));
  999.  
  1000.         driverObj->DriverUnload = PCIVMEUnload;
  1001.         driverObj->MajorFunction[IRP_MJ_CREATE] = PCIVMEOpen;
  1002.         driverObj->MajorFunction[IRP_MJ_CLOSE]  = PCIVMEClose;
  1003.         driverObj->MajorFunction[IRP_MJ_READ]   = PCIVMERead;
  1004.     driverObj->MajorFunction[IRP_MJ_WRITE]  = PCIVMEWrite;
  1005.         driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]    = PCIVMEDeviceControl;
  1006. #ifdef DO_CLEANUP
  1007.         driverObj->MajorFunction[IRP_MJ_CLEANUP] = PCIVMECancel;
  1008. #endif
  1009.     driverObj->MajorFunction[IRP_MJ_SHUTDOWN]          = PCIVMEShutdown;
  1010.  
  1011.         RtlInitUnicodeString(&device_name, L"\\Device\\PCIVME");
  1012.  
  1013.         /* DeviceObject durch IO-Manager erzeugen */
  1014.         result = IoCreateDevice( driverObj,           // DriverObject received by the DriverEntry Call
  1015.                                                          sizeof(DEVICE_EXT),  // required Memory for the DeviceExtension
  1016.                                                          &device_name,        // Name of the device in the device-Directory
  1017.                                                          FILE_DEVICE_UNKNOWN, // Device-ID              
  1018.                                                          0,                   // Device-Characteristics normal 0
  1019.                                                          FALSE,               // TRUE : one Thread can open the driver
  1020.                                                          &device_object);     // DeviceObject returned from the IO-Manager
  1021.  
  1022.         // defines how the data are handled between user / kernel Adress-Space  
  1023.         device_object->Flags |= DO_DIRECT_IO;
  1024.  
  1025. #if 0
  1026.         // register the shutdown notification entry
  1027.     IoRegisterShutdownNotification(device_object);
  1028. #endif
  1029.  
  1030.         // anounce driver as symbolic device ---------------------------------
  1031.         if (result == STATUS_SUCCESS)
  1032.         {
  1033.                 /* now the symbolic Link is created. If there is no S.L. a program cannot connect to the driver */
  1034.                 RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
  1035.                 result = IoCreateSymbolicLink(&symbol_name,&device_name);
  1036.                 if (result != STATUS_SUCCESS)
  1037.                 {
  1038.                         IoDeleteDevice(device_object);
  1039.                         return result;
  1040.                 }
  1041.         }
  1042.         else
  1043.                 return result;
  1044.  
  1045.         DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
  1046.  
  1047.         DeviceExtension->actualIrp  = NULL;
  1048.         DeviceExtension->driverObj  = driverObj;
  1049.         DeviceExtension->nInitState = 0;
  1050.  
  1051.         // init pciada structures ------------------------------------
  1052.         PCIVMESoftInit(device_object);
  1053.  
  1054.         // search for PCIADAs ----------------------------------------
  1055.         result   = SearchDevices(device_object);
  1056.         nPCIADAs = DeviceExtension->nPCIADAs;
  1057.  
  1058.         if ((result != STATUS_SUCCESS) || !(nPCIADAs))
  1059.         {
  1060.                 PCIVMEUnload(driverObj);    
  1061.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1062.         }
  1063.  
  1064.         // request exclusive ownership of .. ---------------------------------
  1065.         if ((result = PCIVMEReserveResources(device_object)) != STATUS_SUCCESS)
  1066.         {
  1067.                 PCIVMEUnload(driverObj);    
  1068.                 return result;
  1069.         }
  1070.         else
  1071.                 DeviceExtension->nInitState++;
  1072.         // fix PLX9050 Bug -------------------------------------------
  1073.         if ((result = PLX9050BugFix(device_object)) != STATUS_SUCCESS)
  1074.         {
  1075.                 PCIVMEUnload(driverObj);    
  1076.                 return result;
  1077.         }
  1078.  
  1079.  
  1080.         // translate BUS relative addresses ----------------------------------
  1081.         if ((result = PCIVMETranslateBusAddresses(device_object)) != STATUS_SUCCESS)
  1082.         {
  1083.                 PCIVMEUnload(driverObj);    
  1084.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1085.         }
  1086.         else
  1087.                 DeviceExtension->nInitState++;
  1088.  
  1089.         // translate Interrupt Resources used --------------------------------
  1090.         if ((result = PCIVMETranslateInterrupts(device_object)) != STATUS_SUCCESS)
  1091.         {
  1092.                 PCIVMEUnload(driverObj);    
  1093.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1094.         }
  1095.         else
  1096.                 DeviceExtension->nInitState++;
  1097.        
  1098.         // map address spaces to virtual addresses ---------------------------
  1099.         if ((result = PCIVMEMapIOspace(device_object)) != STATUS_SUCCESS)
  1100.         {
  1101.                 PCIVMEUnload(driverObj);    
  1102.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1103.         }
  1104.         else
  1105.                 DeviceExtension->nInitState++;
  1106.  
  1107.         // initialze my custom DPC objects -----------------------------------
  1108.         if ((result = InitializeCustomDPCObjects(device_object)) != STATUS_SUCCESS)
  1109.         {
  1110.                 PCIVMEUnload(driverObj);    
  1111.                 return result;
  1112.         }
  1113.         else
  1114.                 DeviceExtension->nInitState++;
  1115.  
  1116.         // initialze the queue for IRPs waiting for vectors ------------------
  1117.         if ((result = InitializeIRPQueue(device_object)) != STATUS_SUCCESS)
  1118.         {
  1119.                 PCIVMEUnload(driverObj);    
  1120.                 return result;
  1121.         }
  1122.         else
  1123.                 DeviceExtension->nInitState++;
  1124.  
  1125.         // connect interrupts to service routines ----------------------------
  1126.         if ((result = PCIVMEConnectInterrupt(device_object)) != STATUS_SUCCESS)
  1127.         {
  1128.                 PCIVMEUnload(driverObj);    
  1129.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1130.         }
  1131.         else
  1132.                 DeviceExtension->nInitState++;
  1133.  
  1134.         // scan all connected VMEMM for info and later use -------------------
  1135.         if ((result = PCIVMEScanVMEMM(device_object)) != STATUS_SUCCESS)
  1136.         {
  1137.                 PCIVMEUnload(driverObj);    
  1138.                 return STATUS_DEVICE_DOES_NOT_EXIST;
  1139.         }
  1140.  
  1141.         device_object->Flags &= ~DO_DEVICE_INITIALIZING;
  1142.  
  1143.     KdPrint(("DriverEntry() OK.\n"));
  1144.  
  1145.         return result;
  1146. }
  1147.  
  1148.