Subversion Repositories f9daq

Rev

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