Subversion Repositories f9daq

Rev

Rev 46 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
19 f9daq 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
//
46 f9daq 34
#include <initguid.h>
35
#include <wdmguid.h>
19 f9daq 36
#include <ntddk.h>
37
#include <devioctl.h>
38
#include <pcivme_drv.h>
39
#include <pcivme_v.h>
40
#include <pcivme_io.h>
41
#include <pcivme_i.h>
42
#include <pcivme.h>
43
#include <pciif.h>
44
#include <pcivme_fifo.h>
45
//------------------------------------------------------------------------
46
// DEFINES
47
//
41 f9daq 48
#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
49
 
19 f9daq 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;
41 f9daq 136
        if (!driverObj->DeviceObject) {
137
                KdPrint(("PCIVMEUnload() DeviceObject does not exist \n"));
138
                return;
139
        }
19 f9daq 140
        DEVICE_EXT *ext = (DEVICE_EXT*)(driverObj->DeviceObject->DeviceExtension);
141
        int         nPCIADAs = ext->nPCIADAs;
142
        PCIADA      *pciada;
143
 
41 f9daq 144
        KdPrint(("PCIVMEUnload() InitState %d \n", ext->nInitState ));
19 f9daq 145
 
46 f9daq 146
 
41 f9daq 147
        if (ext->nInitState!=100) return;
148
 
19 f9daq 149
        switch (ext->nInitState)
150
        {
151
                case 8:
152
                case 7:
153
                        // stop interrupts and shut off
154
                        PCIVMEDeInitPCIADAs(driverObj->DeviceObject);
155
                        PCIVMEDisConnectInterrupt(driverObj->DeviceObject);
156
 
157
                        // remove interrupt lists
158
                        for (i = 0; i < nPCIADAs; i++)
159
                        {
160
                                pciada = &ext->pciada[i];
161
 
162
                                // removeQueueFromList(...)
163
                                while (IsListEmpty(&pciada->IrqListList) == FALSE)
164
                                {
165
                                        PLIST_ENTRY pList;
166
                                        FIFO_LIST   *next;
167
 
168
                                        KdPrint(("RemoveHeadList(0x%08x)\n", &pciada->IrqListList));
169
                                        pList = RemoveHeadList(&pciada->IrqListList);
170
                                        next  = CONTAINING_RECORD(pList, FIFO_LIST, entry);
171
 
172
                                        ExFreePool((PVOID)next);
173
                                }
174
                        }
175
                case 6:
176
                        // InitializeIRPQueue has no counterpart
177
                case 5:
178
                        // KeInitializeDpc has no counterpart
179
                case 4:
180
                        // release io spaces
181
                        for (i = 0; i < nPCIADAs; i++)
182
                        {
183
                                pciada = &ext->pciada[i];
184
 
185
                                if (pciada->pvVirtLcr != NULL)
186
                                        MmUnmapIoSpace(pciada->pvVirtLcr, LCR_SPACE);
187
                                if (pciada->pvVirtIfr != NULL)
188
                                        MmUnmapIoSpace(pciada->pvVirtIfr, IFR_SPACE);
189
                        }
190
                case 3:
191
                        // HalGetInterruptVector has no counterpart
192
                case 2:
193
                        // HalTranslateBusAddress has no counterpart
194
                case 1:
41 f9daq 195
                        // PCIVMEFreeResources(driverObj->DeviceObject); // not used in pnp
19 f9daq 196
                default:
197
                case 0:
198
                        RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
199
 
200
                        // delete the symbolicLink in the registry 
201
                        IoDeleteSymbolicLink( &symbol_name);
202
 
203
                        // delete the deviceObject 
46 f9daq 204
 
41 f9daq 205
                        if (ext->LowerDeviceObject) IoDetachDevice(ext->LowerDeviceObject);
19 f9daq 206
                        IoDeleteDevice(driverObj->DeviceObject);
207
        }
41 f9daq 208
 
19 f9daq 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
 
46 f9daq 583
 
584
// http://read.pudn.com/downloads148/sourcecode/windows/vxd/640413/agp/agplib/init.c__.htm
585
NTSTATUS  
586
QueryBusInterface(  
587
    IN PDEVICE_OBJECT DeviceObject,  
588
    OUT PBUS_INTERFACE_STANDARD BusInterface  
589
    )  
590
/*++  
591
 
592
Routine Description:  
593
 
594
    Sends a query-interface IRP to the specified device object  
595
    to obtain the BUS_INTERFACE_STANDARD interface.  
596
 
597
Arguments:  
598
 
599
    DeviceObject - Supplies the device object to send the BUS_INTERFACE_STANDARD to  
600
 
601
    BusInterface - Returns the bus interface  
602
 
603
Return Value:  
604
 
605
    STATUS_SUCCESS if successful  
606
    NTSTATUS if unsuccessful  
607
 
608
--*/  
609
 
610
{  
611
    PIRP Irp;  
612
    KEVENT Event;  
613
    PIO_STACK_LOCATION IrpSp;  
614
    IO_STATUS_BLOCK IoStatusBlock;  
615
    NTSTATUS Status;  
616
//    ULONG ReturnLength;   
617
 
618
    KeInitializeEvent( &Event, NotificationEvent, FALSE );  
619
    Irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,  
620
                                        DeviceObject,  
621
                                        NULL,  
622
                                        0,  
623
                                        NULL,  
624
                                        &Event,  
625
                                        &IoStatusBlock );  
626
    if (Irp == NULL) {  
627
        return(STATUS_INSUFFICIENT_RESOURCES);  
628
    }  
629
 
630
    IrpSp = IoGetNextIrpStackLocation( Irp );  
631
    ASSERT(IrpSp != NULL);  
632
    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;  
633
    IrpSp->MajorFunction = IRP_MJ_PNP;  
634
    IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;  
635
    IrpSp->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;  
636
    IrpSp->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);  
637
    IrpSp->Parameters.QueryInterface.Version = 1;  
638
    IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;  
639
    IrpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;  
640
 
641
    Status = IoCallDriver(DeviceObject, Irp);  
642
    if (Status == STATUS_PENDING) {  
643
        KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );  
644
        Status = Irp->IoStatus.Status;  
645
    }  
646
 
647
    return(Status);  
648
}  
649
 
19 f9daq 650
//------------------------------------------------------------------------
651
// search for pciada's
652
//
46 f9daq 653
 
19 f9daq 654
NTSTATUS SearchDevices(PDEVICE_OBJECT device_Obj)
655
{
656
  PCI_SLOT_NUMBER   SlotNumber;
657
  PCI_COMMON_CONFIG pci_config;
46 f9daq 658
  PBUS_INTERFACE_STANDARD busInterface;
19 f9daq 659
  PCIADA            *pciada;
46 f9daq 660
 
661
  ULONG   propertyAddress, length;
662
  USHORT  FunctionNumber, DeviceNumber;
19 f9daq 663
  int               *found;
46 f9daq 664
  int               i;
665
  NTSTATUS          status;
666
  int  BytesRead;
19 f9daq 667
  KdPrint(("SearchDevices()\n"));
668
 
669
  // prepare structures ----------------------------------------
670
  found = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
671
  *found = 0;
672
  for (i = 0; i < PCIVME_MAX_PCIADA; i++)
673
  {
674
        pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
675
 
676
        pciada->Bus                = -1;
677
    pciada->Slot.u.AsULONG     = 0xFFFFFFFF;
678
  }
679
 
680
  // search for pciada's ---------------------------------------
681
  SlotNumber.u.bits.Reserved = 0;
46 f9daq 682
  busInterface = (PBUS_INTERFACE_STANDARD)ExAllocatePool(NonPagedPool,
683
          sizeof(BUS_INTERFACE_STANDARD));
684
  if (busInterface == NULL)
19 f9daq 685
  {
46 f9daq 686
          return STATUS_INSUFFICIENT_RESOURCES;
687
  }
688
  ((DEVICE_EXT*)(device_Obj->DeviceExtension))->busInterface = busInterface;
689
  status = QueryBusInterface(device_Obj, busInterface);
690
  BytesRead = busInterface->GetBusData(busInterface->Context, PCI_WHICHSPACE_CONFIG, &pci_config, 0, PCI_COMMON_HDR_LENGTH);
19 f9daq 691
 
46 f9daq 692
  pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[0];
693
 
694
                //http://www.hollistech.com/Resources/Misc%20articles/getbusdata.htm
695
                //IoGetDeviceProperty
696
                //There are other differnt methods to send a request to lower layer. One method is 
697
        //by sending IRP_MN_READ_CONFIG to lower driver. You will recieve 
698
        //PCI_COMMON_CONFIG structure.
699
                // http://msdn.microsoft.com/en-us/library/windows/hardware/ff536890(v=vs.85).aspx
700
                // http://www.rdos.net/svn/tags/V9.2.5/watcom/bld/src/win32/miniwdm/dev/wdmdev.c
701
 
19 f9daq 702
                if ((pci_config.VendorID    == PCIVME_VENDOR_ID) &&
703
                        (pci_config.DeviceID    == PCIVME_DEVICE_ID) &&
704
                        (pci_config.u.type0.SubSystemID == PCIVME_SUBSYS_ID) &&
705
                        (pci_config.u.type0.SubVendorID == PCIVME_SUBVEN_ID) &&
706
                        (pci_config.u.type0.BaseAddresses[2]))
707
                {
708
               pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[*found];
709
 
710
               memcpy(&pciada->PCIDevice, &pci_config, sizeof(pci_config));
46 f9daq 711
 
712
                   IoGetDeviceProperty(device_Obj,
713
                           DevicePropertyBusNumber,
714
                           sizeof(ULONG),
715
                           (PVOID)&(pciada->Bus),
716
                           &length);
19 f9daq 717
 
46 f9daq 718
                   IoGetDeviceProperty(device_Obj,
719
                           DevicePropertyAddress,
720
                           sizeof(ULONG),
721
                           (PVOID)&propertyAddress,
722
                           &length);
723
                   // 
724
                   // For PCI, the DevicePropertyAddress has device number 
725
                   // in the high word and the function number in the low word. 
726
                   // 
727
                   FunctionNumber = (USHORT)((propertyAddress)& 0x0000FFFF);
728
                   DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
729
                   pciada->Slot.u.AsULONG = DeviceNumber;
19 f9daq 730
                   KdPrint(("PCIADA found @ Bus/Slot %d/%d.\n", pciada->Bus, pciada->Slot.u.AsULONG));
731
 
732
                   (*found)++;
733
                   if (*found >= PCIVME_MAX_PCIADA) return STATUS_SUCCESS;
46 f9daq 734
 
735
        }
41 f9daq 736
  KdPrint(("SearchDevices() found %d devices\n", (*found)));
19 f9daq 737
  return STATUS_SUCCESS;
738
}
739
 
740
//---------------------------------------------------------------
741
// function to call for bug fix of PLX9050 build in bug
742
//
743
NTSTATUS PLX9050BugFix(PDEVICE_OBJECT device_Obj)
744
{
41 f9daq 745
        // http://permalink.gmane.org/gmane.linux.kernel.pci/18419
19 f9daq 746
        DEVICE_EXT *DeviceExtension = (DEVICE_EXT*)device_Obj->DeviceExtension;
747
        int i;
748
        ULONG dwData;
749
        PCIADA *pciada;
46 f9daq 750
        PBUS_INTERFACE_STANDARD busInterface;
19 f9daq 751
 
752
        KdPrint(("PLX9050BugFix()\n"));
46 f9daq 753
        busInterface = DeviceExtension->busInterface;
19 f9daq 754
        for (i = 0; i < DeviceExtension->nPCIADAs; i++)
755
        {
756
                pciada = &DeviceExtension->pciada[i];
757
 
758
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[0]) & 0x80)
759
                {      
760
                        KdPrint(("Changing address 0:0x%p with 4:0x%p\n",
761
                                pciada->PCIDevice.u.type0.BaseAddresses[0],
762
                                pciada->PCIDevice.u.type0.BaseAddresses[4]));
763
 
764
                        pciada->PCIDevice.u.type0.BaseAddresses[0] =           // exchange
765
                                pciada->PCIDevice.u.type0.BaseAddresses[4];
766
                        pciada->PCIDevice.u.type0.BaseAddresses[4] = dwData;
767
 
46 f9daq 768
                        if (busInterface->SetBusData(busInterface->Context, PCI_WHICHSPACE_CONFIG, (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[0], 0x10, 4) != 4)
769
                                return STATUS_UNSUCCESSFUL;
770
 
771
                        if (busInterface->SetBusData(busInterface->Context, PCI_WHICHSPACE_CONFIG, (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[4], 0x20, 4) != 4)
772
                                return STATUS_UNSUCCESSFUL;
773
 
19 f9daq 774
                }
775
 
776
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[1]) & 0x80)
777
                {
778
                        KdPrint(("Changing address 1:0x%p with 5:0x%p\n",
779
                                pciada->PCIDevice.u.type0.BaseAddresses[1],
780
                                pciada->PCIDevice.u.type0.BaseAddresses[5]));
781
 
782
                  pciada->PCIDevice.u.type0.BaseAddresses[1] =           // exchange
783
                                pciada->PCIDevice.u.type0.BaseAddresses[5];
784
                  pciada->PCIDevice.u.type0.BaseAddresses[5] = dwData;
785
 
46 f9daq 786
                  if (busInterface->SetBusData(busInterface->Context, PCI_WHICHSPACE_CONFIG, (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[1], 0x14, 4) != 4)
787
                          return STATUS_UNSUCCESSFUL;
788
 
789
                  if (busInterface->SetBusData(busInterface->Context, PCI_WHICHSPACE_CONFIG, (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[5], 0x24, 4) != 4)
790
                          return STATUS_UNSUCCESSFUL;
791
 
19 f9daq 792
                }
793
        }
794
 
795
        return STATUS_SUCCESS;
796
}
797
 
41 f9daq 798
static VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list)
799
{                                                       // ShowResources
800
        PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = list->PartialDescriptors;
801
        ULONG nres = list->Count;
802
        ULONG i;
19 f9daq 803
 
41 f9daq 804
        for (i = 0; i < nres; ++i, ++resource)
805
        {                                               // for each resource
806
                ULONG type = resource->Type;
807
 
808
                static char* namelow[] = {
809
                        "CmResourceTypeNull",//                0   // ResType_All or ResType_None (0x0000)
810
                        "CmResourceTypePort",//               1   // ResType_IO (0x0002)
811
                        "CmResourceTypeInterrupt",//          2   // ResType_IRQ (0x0004)
812
                        "CmResourceTypeMemory",//             3   // ResType_Mem (0x0001)
813
                        "CmResourceTypeDma",//                4   // ResType_DMA (0x0003)
814
                        "CmResourceTypeDeviceSpecific",//      5   // ResType_ClassSpecific (0xFFFF)
815
                        "CmResourceTypeBusNumber",//          6   // ResType_BusNumber (0x0006)
816
                        "CmResourceTypeMemoryLarge" //        7   // ResType_MemLarge (0x0007)
817
                };
818
                static char* namehigh[] = {
819
                        //"CmResourceTypeNonArbitrated" ,//    128   // Not arbitrated if 0x80 bit set
820
                        "CmResourceTypeConfigData",//       128   // ResType_Reserved (0x8000)
821
                        "CmResourceTypeDevicePrivate",//    129   // ResType_DevicePrivate (0x8001)
822
                        "CmResourceTypePcCardConfig",//     130   // ResType_PcCardConfig (0x8002)
823
                        "CmResourceTypeMfCardConfig",//     131   // ResType_MfCardConfig (0x8003)
824
                        "CmResourceTypeConnection" //       132   // ResType_Connection (0x8004)
825
                };
826
 
827
                if (type<8) KdPrint((" [%d] type %s", type, type < arraysize(namelow) ? namelow[type] : "unknown"));
828
                if (type>127) KdPrint((" [%d] type %s", type, type-128 < arraysize(namehigh) ? namehigh[type-128] : "unknown"));
829
                switch (type)
830
                {                                       // select on resource type
831
                case CmResourceTypePort:
832
                                KdPrint((" start ADDR=0x%p  0x%8X%8.8lX length %X\n",
833
                                resource->u.Port.Start, resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,
834
                                resource->u.Port.Length));
835
                        break;
836
                case CmResourceTypeMemory:
837
                        KdPrint((" %d start ADDR=0x%p \n", i,  resource->u.Memory.Start ));
838
                        break;
839
 
840
                case CmResourceTypeInterrupt:
841
                        KdPrint(("  IRQL %d, vector %d, affinity %d\n",
842
                                resource->u.Interrupt.Level, resource->u.Interrupt.Vector,
843
                                resource->u.Interrupt.Affinity));
844
                        break;
845
 
846
                case CmResourceTypeDma:
847
                        KdPrint(("  channel %d, port %X\n",
848
                                resource->u.Dma.Channel, resource->u.Dma.Port));
849
 
850
 
851
 
852
                }                                       // select on resource type
853
        }                                               // for each resource
854
}                                                       // ShowResources
855
 
856
 
19 f9daq 857
//------------------------------------------------------------------------
858
//  reserve resources for PCIADAs 
859
//
41 f9daq 860
NTSTATUS PCIVMEExtractResources(PCIADA *pciada, PIRP irp)
19 f9daq 861
{
41 f9daq 862
        //PCM_RESOURCE_LIST pResourceList;
863
        ///PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
864
        PCM_PARTIAL_RESOURCE_LIST pPartialList = NULL;
865
        PCM_PARTIAL_RESOURCE_LIST pListTranslated = NULL;
19 f9daq 866
        PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialDescriptor;
867
        int i;
868
        int bug = 0;
869
 
870
        KdPrint(("PCIVMEExtractResources()\n"));
871
 
41 f9daq 872
        ///pResourceList   = pList;
873
        ///pFullDescriptor = pResourceList->List;
874
        ///pPartialList    = &pFullDescriptor->PartialResourceList;
875
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);
876
        if (stack->Parameters.StartDevice.AllocatedResources)
877
        pPartialList = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
878
        KdPrint(("Allocated Resources:------------------\n"));
879
        ShowResources(pPartialList);
880
 
881
        int plcount = 0;
19 f9daq 882
        for (i=0; i<(int)pPartialList->Count; i++)
883
        {
884
                pPartialDescriptor = &pPartialList->PartialDescriptors[i];
41 f9daq 885
 
19 f9daq 886
                switch (pPartialDescriptor->Type)
887
                {
888
                        case CmResourceTypeInterrupt:
889
                                pciada->Irql     = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
890
                                pciada->Vector   = pPartialDescriptor->u.Interrupt.Vector;
891
                                pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
892
 
41 f9daq 893
                                KdPrint(("AllocatedResources Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
19 f9daq 894
                                        pciada->Irql, pciada->Vector, pciada->Affinity));
895
                                break;
896
                        case CmResourceTypeDma:
41 f9daq 897
                                KdPrint(("AllocatedResources Dma    : \n"));
19 f9daq 898
                                break;
899
                        case CmResourceTypePort:
900
 
41 f9daq 901
                                KdPrint(("AllocatedResources Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
19 f9daq 902
                                break;
903
                        case CmResourceTypeMemory:
904
                                // special handling of PLXBUG here because of WIN2000
905
                                // WIN2000 doesn't recognize late address changes
906
                                if (!bug)
907
                                {
41 f9daq 908
                                        if (plcount == 0)
19 f9daq 909
                                        {
910
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
911
 
41 f9daq 912
                                                if (pciada->pvPhysLcr.LowPart & 0x80) {
19 f9daq 913
                                                        bug = 1;
41 f9daq 914
                                                        KdPrint(("AllocatedResources PLXBug\n"));
915
                                                }
19 f9daq 916
                                        }
917
                                }
918
                                else
919
                                {
41 f9daq 920
                                        if (plcount == 3)
19 f9daq 921
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
922
                                }
923
 
41 f9daq 924
                                if (plcount == 2){
19 f9daq 925
                                        pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
41 f9daq 926
                                        KdPrint(("PCIVMEExtractResources() IFR=0x%p \n", pciada->pvPhysIfr));
927
                                }
928
                                KdPrint(("[%d] AllocatedResources Memory : 0x%p\n", plcount, (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
19 f9daq 929
                                break;
930
                }
41 f9daq 931
                if (pPartialDescriptor->Type < 8) plcount++;
19 f9daq 932
        }
933
 
41 f9daq 934
        KdPrint(("PCIVMEExtractResources() LCR=0x%p IFR=0x%p \n", pciada->pvPhysLcr, pciada->pvPhysIfr));
935
 
936
        if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
937
                pListTranslated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
938
        KdPrint(("Translated Resources:------------------\n"));
939
        ShowResources(pListTranslated);
940
        plcount = 0;
941
        bug     = 0;
942
        for (i = 0; i<(int)pPartialList->Count; i++)
943
        {
944
                pPartialDescriptor = &pListTranslated->PartialDescriptors[i];
945
 
946
                switch (pPartialDescriptor->Type)
947
                {
948
                case CmResourceTypeInterrupt:
949
                        pciada->Irql = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
950
                        pciada->Vector = pPartialDescriptor->u.Interrupt.Vector;
951
                        pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
952
 
953
                        KdPrint(("AllocatedResourcesTranslated Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
954
                                pciada->Irql, pciada->Vector, pciada->Affinity));
955
                        break;
956
                case CmResourceTypeDma:
957
                        KdPrint(("AllocatedResourcesTranslated Dma    : \n"));
958
                        break;
959
                case CmResourceTypePort:
960
 
961
                        KdPrint(("AllocatedResourcesTranslated Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
962
                        break;
963
                case CmResourceTypeMemory:
964
                        // special handling of PLXBUG here because of WIN2000
965
                        // WIN2000 doesn't recognize late address changes
966
                        if (!bug)
967
                        {
968
                                if (plcount == 0)
969
                                {
970
                                        pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
971
                                        KdPrint(("0 PCIVMEExtractResources() LCR=0x%p \n", pciada->pvPhysLcr));
972
                                        if (pciada->pvPhysLcr.LowPart & 0x80) {
973
                                                bug = 1;
974
                                                KdPrint(("AllocatedResourcesTranslated PLXBug\n"));
975
                                        }
976
                                }
977
                        }
978
                        else
979
                        {
980
                                if (plcount == 3){
981
                                        pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
982
                                        KdPrint(("3 PCIVMEExtractResources() LCR=0x%p \n", pciada->pvPhysLcr));
983
                                }
984
                        }
985
 
986
                        if (plcount == 2){
987
                                pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
988
                                KdPrint(("2 PCIVMEExtractResources() IFR=0x%p \n", pciada->pvPhysIfr));
989
                        }
990
 
991
                        KdPrint(("[%d] AllocatedResourcesTranslated Memory : 0x%p\n", plcount, (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
992
                        break;
993
                }
994
                if (pPartialDescriptor->Type < 8) plcount++;
995
        }
996
 
997
 
998
 
19 f9daq 999
        if (pciada->Irql == 0)
1000
                return STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
1001
 
41 f9daq 1002
        KdPrint(("PCIVMEExtractResources() Translated LCR=0x%p IFR=0x%p \n", pciada->pvPhysLcr, pciada->pvPhysIfr));
19 f9daq 1003
 
1004
        return STATUS_SUCCESS;
1005
}
1006
 
41 f9daq 1007
NTSTATUS PCIVMEReserveResources(PDEVICE_OBJECT device_Obj, PIRP irp)
19 f9daq 1008
{
41 f9daq 1009
        //PCM_RESOURCE_LIST pList = NULL;
19 f9daq 1010
        NTSTATUS result = STATUS_SUCCESS;
1011
        int i;
1012
        DEVICE_EXT *pDevExt = (DEVICE_EXT*)(device_Obj->DeviceExtension);
1013
        int nPCIADAs = pDevExt->nPCIADAs;
1014
        PCIADA *pciada;
1015
    UNICODE_STRING DriverClassName;
1016
 
1017
        KdPrint(("PCIVMEReserveResources()\n"));
1018
 
1019
        // prepare resource claiming
41 f9daq 1020
        //RtlInitUnicodeString(&DriverClassName, L"PCICC32");
1021
        RtlInitUnicodeString(&DriverClassName, L"PCIVME");
19 f9daq 1022
        // cycle through all busses and slots assigned to PCIADAs
1023
        for (i = 0; i < nPCIADAs; i++)
1024
    {
1025
                pciada = &pDevExt->pciada[i];
1026
 
41 f9daq 1027
                //result = HalAssignSlotResources(NULL, &DriverClassName, device_Obj->DriverObject, device_Obj, 
1028
                //      PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, &pList);
1029
                /*
1030
                result = IoReportDetectedDevice(device_Obj->DriverObject, PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, pList, NULL, FALSE, &device_Obj);
1031
                if (result != STATUS_SUCCESS){
1032
                        KdPrint(("PCIVMEReserveResources(0x%08x) HalAssignSlotResources  ***ERROR*** faliure to get slot information\n", result));
19 f9daq 1033
                        break;
41 f9daq 1034
                }
1035
                */
1036
                result = PCIVMEExtractResources(pciada, irp);
19 f9daq 1037
 
41 f9daq 1038
                if (result != STATUS_SUCCESS){
1039
                        KdPrint(("PCIVMEReserveResources(0x%08x) PCIVMEExtractResources\n", result));
19 f9daq 1040
                        break;
41 f9daq 1041
                }
19 f9daq 1042
        }
1043
 
1044
        // its my part to free allocated resources
41 f9daq 1045
        //if (pList != NULL) ExFreePoolWithTag(pList,'nepo');
19 f9daq 1046
 
1047
        KdPrint(("PCIVMEReserveResources(0x%08x)\n", result));
1048
 
1049
        return result;
1050
};
1051
 
1052
 
1053
//------------------------------------------------------------------------
1054
//  translate memory resources to neutral for PCIADAs 
1055
//
41 f9daq 1056
NTSTATUS PCIVMETranslateBusAddresses(PDEVICE_OBJECT device_Obj,  PIRP irp)
19 f9daq 1057
{
1058
        int              i;
1059
        NTSTATUS         result = STATUS_SUCCESS;
1060
        int nPCIADAs = ((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
1061
        ULONG            memType0, memType2;
1062
        PCIADA           *pciada;
41 f9daq 1063
        PCM_PARTIAL_RESOURCE_LIST pPartialList = NULL;
1064
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);
1065
        if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
1066
       pPartialList = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
19 f9daq 1067
 
41 f9daq 1068
 
19 f9daq 1069
        for (i = 0; i < nPCIADAs; i++)
1070
        {
1071
      pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
1072
 
1073
          memType0 = memType2 = 0;
41 f9daq 1074
          /*
19 f9daq 1075
          if (!(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysLcr, &memType0,
1076
                                                               &pciada->pvPhysLcr)) ||
1077
              !(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysIfr, &memType2,
1078
                                                               &pciada->pvPhysIfr)))
1079
          {
1080
                  result = STATUS_UNSUCCESSFUL;
1081
                  break;
1082
          }
41 f9daq 1083
          */
1084
          KdPrint(("PCIADA %d TranslateBusAddresseses() -- no translation is made\n", i));
19 f9daq 1085
 
1086
          if ((memType0) || (memType2))
1087
          {
1088
                  result = STATUS_UNSUCCESSFUL;
1089
                  break;
1090
          }
1091
        }
41 f9daq 1092
 
19 f9daq 1093
        return result;
1094
}
1095
 
1096
//------------------------------------------------------------------------
1097
//  map address spaces to virtual addresses
1098
//
1099
NTSTATUS PCIVMEMapIOspace(PDEVICE_OBJECT device_Obj)
1100
{
1101
        int              i;
1102
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
1103
        int                              nPCIADAs = pDevExt->nPCIADAs;
1104
        PCIADA           *pciada;
1105
 
1106
        KdPrint(("PCIVMEMapIOspace()\n"));
1107
 
1108
        for (i = 0; i < nPCIADAs; i++)
1109
        {
1110
       pciada = &pDevExt->pciada[i];
1111
 
1112
       if ((pciada->pvVirtLcr = MmMapIoSpace(pciada->pvPhysLcr, LCR_SPACE, FALSE)) == NULL)
1113
          return STATUS_UNSUCCESSFUL;
1114
       if ((pciada->pvVirtIfr = MmMapIoSpace(pciada->pvPhysIfr, IFR_SPACE, FALSE)) == NULL)
1115
          return STATUS_UNSUCCESSFUL;
1116
 
1117
           KdPrint(("PCIADA %d: LCR 0x%08x IFR 0x%08x\n",
1118
                                         i, pciada->pvVirtLcr, pciada->pvVirtIfr));
1119
 
1120
           pciada->pwIntCSR = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x4C);
1121
           pciada->pwCntrl  = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x50);
1122
        }
1123
 
1124
        return STATUS_SUCCESS;
1125
}
1126
 
1127
 
1128
//------------------------------------------------------------------------
1129
//  initializes and registers a DPC routine for each pciada
1130
//
1131
NTSTATUS InitializeCustomDPCObjects(PDEVICE_OBJECT device_object)
1132
{
1133
        int              i;
1134
        int nPCIADAs = ((DEVICE_EXT*)(device_object->DeviceExtension))->nPCIADAs;
1135
        PCIADA           *pciada;
1136
 
1137
        KdPrint(("InitializeCustomDPCObject()\n"));
1138
 
1139
        for (i = 0; i < nPCIADAs; i++)
1140
        {
1141
                pciada = &((DEVICE_EXT*)(device_object->DeviceExtension))->pciada[i];
1142
                KeInitializeDpc(&pciada->kDPCobj, fMyDefferedRoutine, (PVOID)device_object);
1143
        }
1144
 
1145
        return STATUS_SUCCESS;
1146
}
1147
 
1148
//------------------------------------------------------------------------
1149
//  initializes the queue for storing IRPs waiting for vectors
1150
// 
1151
NTSTATUS InitializeIRPQueue(PDEVICE_OBJECT device_Obj)
1152
{
1153
        DEVICE_EXT *pDevExt = ((DEVICE_EXT*)(device_Obj->DeviceExtension));
1154
 
1155
        KdPrint(("InitializeIRPQueue()\n"));
1156
 
1157
        KeInitializeSpinLock(&pDevExt->IRPLock);
1158
        InitializeListHead(&pDevExt->IRPList);
1159
 
1160
        return STATUS_SUCCESS;
1161
}
1162
 
1163
//------------------------------------------------------------------------
1164
// init structures a.s.o.
1165
//
1166
VOID PCIVMESoftInit(PDEVICE_OBJECT device_Obj)
1167
{
1168
        int i;
1169
        PCIADA *pciada;
1170
 
1171
        for (i = 0; i < PCIVME_MAX_PCIADA; i++)
1172
        {
1173
                pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
1174
 
1175
                pciada->pvPhysLcr.QuadPart = pciada->pvPhysIfr.QuadPart = 0;
1176
                pciada->pvVirtLcr = pciada->pvVirtIfr = NULL;
1177
 
1178
                pciada->bConnected     = FALSE;   // connection still not verified
1179
                pciada->bWordMode      = TRUE;
1180
                pciada->bSysControl    = FALSE;
1181
                pciada->wModuleNumber  = 0xFFFF;
1182
                pciada->wFPGAVersion   = 0xFFFF;
1183
                pciada->wModuleType    = 1;       // always VMEMM
1184
 
1185
                pciada->InterruptObject = NULL;
1186
                pciada->Irql                    = 0;
1187
                pciada->Vector          = 0;
1188
                pciada->Affinity                = 0;
1189
 
1190
                pciada->dwLinkCount     = 0;
1191
 
1192
                KeInitializeSpinLock(&pciada->IrqListLock);
1193
                KeInitializeSpinLock(&pciada->AccessLock);
1194
 
1195
                InitializeListHead(&pciada->IrqListList);  // start of list of irq fifos
1196
 
1197
                pciada->nInterruptHandlers = 0;
1198
        }
1199
 
1200
        // no vmemm associated to any PCIADA
1201
        for (i = 0; i < PCIVME_MAX_VMEMM; i++)
1202
          ((DEVICE_EXT*)(device_Obj->DeviceExtension))->vmemm[i] = NULL;
1203
}
1204
 
41 f9daq 1205
NTSTATUS OnRequestComplete(PDEVICE_OBJECT fdo, PIRP Irp, PKEVENT pev)
19 f9daq 1206
{
41 f9daq 1207
        UNREFERENCED_PARAMETER(fdo);
1208
        UNREFERENCED_PARAMETER(Irp);
1209
        KeSetEvent(pev, 0, FALSE);
1210
        return STATUS_MORE_PROCESSING_REQUIRED;
1211
}
19 f9daq 1212
 
41 f9daq 1213
NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR Information)
1214
{
1215
        Irp->IoStatus.Status = status;
1216
        Irp->IoStatus.Information = Information;
1217
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
1218
        return status;
1219
}
1220
NTSTATUS ForwardAndWait(PDEVICE_OBJECT fdo, PIRP Irp)
1221
{
1222
        KEVENT event;
1223
        KeInitializeEvent(&event, NotificationEvent, FALSE);
1224
        IoCopyCurrentIrpStackLocationToNext(Irp);
1225
        IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete, (PVOID)&event, TRUE, TRUE, TRUE);
1226
        PDEVICE_EXT pdx = (PDEVICE_EXT ) fdo->DeviceExtension;
1227
        IoCallDriver(pdx->LowerDeviceObject, Irp);
1228
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
1229
        return Irp->IoStatus.Status;
1230
}
19 f9daq 1231
 
41 f9daq 1232
NTSTATUS HandleStartDevice(PDEVICE_OBJECT fdo, PIRP Irp)
1233
{
1234
        PIO_STACK_LOCATION stack;
1235
        Irp->IoStatus.Status = STATUS_SUCCESS;
1236
        NTSTATUS status = ForwardAndWait(fdo, Irp);
1237
        if (!NT_SUCCESS(status))
1238
                return CompleteRequest(Irp, status, Irp->IoStatus.Information);
1239
 
1240
        stack = IoGetCurrentIrpStackLocation(Irp);
1241
        status = PCIVMEStartDevice(fdo, Irp);
1242
        return CompleteRequest(Irp, status, Irp->IoStatus.Information);
1243
}
19 f9daq 1244
 
1245
 
41 f9daq 1246
NTSTATUS DefaultPnpHandler(PDEVICE_OBJECT fdo, PIRP Irp)
1247
{
1248
        IoSkipCurrentIrpStackLocation(Irp);
1249
        PDEVICE_EXT pdx = (PDEVICE_EXT )fdo->DeviceExtension;
1250
        return IoCallDriver(pdx->LowerDeviceObject, Irp);
1251
}
19 f9daq 1252
 
41 f9daq 1253
NTSTATUS HandleStopDevice(PDEVICE_OBJECT fdo, PIRP Irp)
1254
{
1255
        IoSkipCurrentIrpStackLocation(Irp);
1256
        UNICODE_STRING symbol_name;
1257
        RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
1258
    // delete the symbolicLink in the registry 
1259
        IoDeleteSymbolicLink(&symbol_name);
1260
        DEVICE_EXT *ext = (DEVICE_EXT*)(fdo->DeviceExtension);
46 f9daq 1261
        // delete the busInterface and deviceObject 
1262
        if (ext->busInterface) {
1263
                (*ext->busInterface->InterfaceDereference)(ext->busInterface->Context);
1264
                ext->busInterface = NULL;
1265
        }
41 f9daq 1266
        if (ext->LowerDeviceObject) IoDetachDevice(ext->LowerDeviceObject);
1267
        IoDeleteDevice(fdo);
1268
        KdPrint(("HandleStopDevice (OK)\n"));
1269
        return STATUS_SUCCESS;
1270
}
19 f9daq 1271
 
1272
 
41 f9daq 1273
NTSTATUS PCIVMEDispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
1274
{
1275
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
1276
        ULONG fcn = stack->MinorFunction;
1277
        static char* pnpname[] = {
1278
                "IRP_MN_START_DEVICE",
1279
                "IRP_MN_QUERY_REMOVE_DEVICE",
1280
                "IRP_MN_REMOVE_DEVICE",
1281
                "IRP_MN_CANCEL_REMOVE_DEVICE",
1282
                "IRP_MN_STOP_DEVICE",
1283
                "IRP_MN_QUERY_STOP_DEVICE",
1284
                "IRP_MN_CANCEL_STOP_DEVICE",
1285
                "IRP_MN_QUERY_DEVICE_RELATIONS",
1286
                "IRP_MN_QUERY_INTERFACE",
1287
                "IRP_MN_QUERY_CAPABILITIES",
1288
                "IRP_MN_QUERY_RESOURCES",
1289
                "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
1290
                "IRP_MN_QUERY_DEVICE_TEXT",
1291
                "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
1292
                "",
1293
                "IRP_MN_READ_CONFIG",
1294
                "IRP_MN_WRITE_CONFIG",
1295
                "IRP_MN_EJECT",
1296
                "IRP_MN_SET_LOCK",
1297
                "IRP_MN_QUERY_ID",
1298
                "IRP_MN_QUERY_PNP_DEVICE_STATE",
1299
                "IRP_MN_QUERY_BUS_INFORMATION",
1300
                "IRP_MN_DEVICE_USAGE_NOTIFICATION",
1301
                "IRP_MN_SURPRISE_REMOVAL",
1302
                "IRP_MN_QUERY_LEGACY_BUS_INFORMATION",
1303
        };
1304
 
1305
        if (fcn < arraysize(pnpname))
1306
                KdPrint(("PCIVMEDispatchPnp  - IRP_MJ_PNP (%s)\n", pnpname[fcn]));
19 f9daq 1307
        else
41 f9daq 1308
                KdPrint(( "PCIVMEDispatchPnp - IRP_MJ_PNP (%2.2X)\n", fcn));
19 f9daq 1309
 
41 f9daq 1310
        static NTSTATUS(*fcntab[])(PDEVICE_OBJECT, PIRP) = {
46 f9daq 1311
                HandleStartDevice,        // IRP_MN_START_DEVICE
1312
        //      DefaultPnpHandler,        // IRP_MN_QUERY_REMOVE_DEVICE
1313
                HandleStopDevice          // IRP_MN_REMOVE_DEVICE
41 f9daq 1314
        };
19 f9daq 1315
 
41 f9daq 1316
        if (fcn >= arraysize(fcntab))
1317
                return DefaultPnpHandler(fdo, Irp);
1318
        return (*fcntab[fcn])(fdo, Irp);
1319
}
19 f9daq 1320
 
41 f9daq 1321
 
1322
NTSTATUS PCIVMEStartDevice(PDEVICE_OBJECT device_object, PIRP irp){
1323
        NTSTATUS result = STATUS_SUCCESS;
1324
        int            nPCIADAs;                                // count of PCIADAs
1325
        DEVICE_EXT     *DeviceExtension = NULL;
1326
        DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
19 f9daq 1327
        // init pciada structures ------------------------------------
1328
        PCIVMESoftInit(device_object);
1329
 
1330
        // search for PCIADAs ----------------------------------------
41 f9daq 1331
        result = SearchDevices(device_object);
19 f9daq 1332
        nPCIADAs = DeviceExtension->nPCIADAs;
1333
 
1334
        if ((result != STATUS_SUCCESS) || !(nPCIADAs))
1335
        {
41 f9daq 1336
                KdPrint(("PCIVMEStartDevice Device not found\n"));
1337
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1338
                return STATUS_DEVICE_DOES_NOT_EXIST;
41 f9daq 1339
        }
19 f9daq 1340
 
1341
        // request exclusive ownership of .. ---------------------------------
41 f9daq 1342
        if ((result = PCIVMEReserveResources(device_object, irp)) != STATUS_SUCCESS)
19 f9daq 1343
        {
41 f9daq 1344
                KdPrint(("PCIVMEStartDevice Resource not reserved PCIVMEReserveResources \n"));
1345
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1346
                return result;
41 f9daq 1347
        }
19 f9daq 1348
        else
1349
                DeviceExtension->nInitState++;
1350
        // fix PLX9050 Bug -------------------------------------------
1351
        if ((result = PLX9050BugFix(device_object)) != STATUS_SUCCESS)
1352
        {
41 f9daq 1353
                KdPrint(("PCIVMEStartDevice PLX9050BugFix\n"));
1354
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1355
                return result;
1356
        }
1357
 
41 f9daq 1358
        DeviceExtension->nInitState += 2;
1359
        /*
19 f9daq 1360
        // translate BUS relative addresses ----------------------------------
41 f9daq 1361
        if ((result = PCIVMETranslateBusAddresses(device_object,irp)) != STATUS_SUCCESS)
19 f9daq 1362
        {
41 f9daq 1363
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1364
                return STATUS_DEVICE_DOES_NOT_EXIST;
41 f9daq 1365
        }
19 f9daq 1366
        else
1367
                DeviceExtension->nInitState++;
1368
 
41 f9daq 1369
 
19 f9daq 1370
        // translate Interrupt Resources used --------------------------------
1371
        if ((result = PCIVMETranslateInterrupts(device_object)) != STATUS_SUCCESS)
1372
        {
41 f9daq 1373
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1374
                return STATUS_DEVICE_DOES_NOT_EXIST;
1375
        }
1376
        else
1377
                DeviceExtension->nInitState++;
41 f9daq 1378
        */
1379
 
19 f9daq 1380
        // map address spaces to virtual addresses ---------------------------
1381
        if ((result = PCIVMEMapIOspace(device_object)) != STATUS_SUCCESS)
1382
        {
41 f9daq 1383
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1384
                return STATUS_DEVICE_DOES_NOT_EXIST;
41 f9daq 1385
        }
19 f9daq 1386
        else
1387
                DeviceExtension->nInitState++;
1388
 
1389
        // initialze my custom DPC objects -----------------------------------
1390
        if ((result = InitializeCustomDPCObjects(device_object)) != STATUS_SUCCESS)
1391
        {
41 f9daq 1392
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1393
                return result;
41 f9daq 1394
        }
19 f9daq 1395
        else
1396
                DeviceExtension->nInitState++;
41 f9daq 1397
 
19 f9daq 1398
        // initialze the queue for IRPs waiting for vectors ------------------
1399
        if ((result = InitializeIRPQueue(device_object)) != STATUS_SUCCESS)
1400
        {
41 f9daq 1401
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1402
                return result;
41 f9daq 1403
        }
19 f9daq 1404
        else
1405
                DeviceExtension->nInitState++;
1406
 
1407
        // connect interrupts to service routines ----------------------------
1408
        if ((result = PCIVMEConnectInterrupt(device_object)) != STATUS_SUCCESS)
1409
        {
41 f9daq 1410
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1411
                return STATUS_DEVICE_DOES_NOT_EXIST;
1412
        }
1413
        else
1414
                DeviceExtension->nInitState++;
1415
 
1416
        // scan all connected VMEMM for info and later use -------------------
1417
        if ((result = PCIVMEScanVMEMM(device_object)) != STATUS_SUCCESS)
1418
        {
41 f9daq 1419
                PCIVMEUnload(DeviceExtension->driverObj);
19 f9daq 1420
                return STATUS_DEVICE_DOES_NOT_EXIST;
41 f9daq 1421
        }
19 f9daq 1422
 
1423
        device_object->Flags &= ~DO_DEVICE_INITIALIZING;
41 f9daq 1424
        return result;
1425
}
19 f9daq 1426
 
41 f9daq 1427
NTSTATUS PCIVMEAddDevice(PDRIVER_OBJECT driverObj,  PDEVICE_OBJECT  pdo)
1428
        {                                                       // AddDevice
1429
 
1430
        UNICODE_STRING device_name;
1431
        UNICODE_STRING symbol_name;
1432
        NTSTATUS result = STATUS_SUCCESS;
1433
        //int            nPCIADAs;                              // count of PCIADAs
1434
        DEVICE_EXT     *DeviceExtension = NULL;
1435
        PDEVICE_OBJECT device_object;
1436
        RtlInitUnicodeString(&device_name, L"\\Device\\PCIVME");
1437
        KdPrint(("PCIVME AddDevice() v%d.%d\n", (DRIVER_VERSION >> 16) & 0xff, DRIVER_VERSION & 0xff));
1438
        /* DeviceObject durch IO-Manager erzeugen */
1439
        result = IoCreateDevice( driverObj,           // DriverObject received by the DriverEntry Call
1440
                                                         sizeof(DEVICE_EXT),  // required Memory for the DeviceExtension
1441
                                                         &device_name,        // Name of the device in the device-Directory
1442
                                                         FILE_DEVICE_UNKNOWN, // Device-ID              
1443
                                                         0,                   // Device-Characteristics normal 0
1444
                                                         FALSE,               // TRUE : one Thread can open the driver
1445
                                                         &device_object);     // DeviceObject returned from the IO-Manager
19 f9daq 1446
 
41 f9daq 1447
        // defines how the data are handled between user / kernel Adress-Space  
1448
        device_object->Flags |= DO_DIRECT_IO;
1449
 
1450
#if 0
1451
        // register the shutdown notification entry
1452
    IoRegisterShutdownNotification(device_object);
1453
#endif
1454
 
1455
        // anounce driver as symbolic device ---------------------------------
1456
        if (result == STATUS_SUCCESS)
1457
        {
1458
                /* now the symbolic Link is created. If there is no S.L. a program cannot connect to the driver */
1459
                RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
1460
                result = IoCreateSymbolicLink(&symbol_name,&device_name);
1461
                if (result != STATUS_SUCCESS)
1462
                {
1463
 
1464
                        IoDeleteDevice(device_object);
1465
                        return result;
1466
                }
1467
        }
1468
        else
1469
                return result;
1470
 
1471
 
1472
        DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
1473
 
1474
        DeviceExtension->actualIrp  = NULL;
1475
        DeviceExtension->driverObj  = driverObj;
1476
        DeviceExtension->nInitState = 0;
1477
 
1478
 
1479
        DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(device_object, pdo);
1480
    KdPrint(("AddDevice() OK.\n"));
1481
 
19 f9daq 1482
        return result;
1483
}
1484
 
41 f9daq 1485
//------------------------------------------------------------------------
1486
// the ultimate starting point of a driver
1487
NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath)
1488
{
1489
        UNREFERENCED_PARAMETER(regPath);
1490
 
1491
        KdPrint(("PCIVME DriverEntry() v%d.%d\n", (DRIVER_VERSION >> 16) & 0xff, DRIVER_VERSION & 0xff));
1492
 
1493
        driverObj->DriverUnload = PCIVMEUnload;
1494
        driverObj->DriverExtension->AddDevice = PCIVMEAddDevice;
1495
        driverObj->MajorFunction[IRP_MJ_CREATE] = PCIVMEOpen;
1496
        driverObj->MajorFunction[IRP_MJ_CLOSE] = PCIVMEClose;
1497
        driverObj->MajorFunction[IRP_MJ_READ] = PCIVMERead;
1498
        driverObj->MajorFunction[IRP_MJ_WRITE] = PCIVMEWrite;
1499
        driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PCIVMEDeviceControl;
1500
#ifdef DO_CLEANUP
1501
        driverObj->MajorFunction[IRP_MJ_CLEANUP] = PCIVMECancel;
1502
#endif
1503
        driverObj->MajorFunction[IRP_MJ_SHUTDOWN] = PCIVMEShutdown;
1504
        driverObj->MajorFunction[IRP_MJ_PNP] = PCIVMEDispatchPnp;
1505
        return  STATUS_SUCCESS;;
1506
}