Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
23 f9daq 1
//-------------------------------------------------------------------------
2
// WINNT driver for PCICC32 (CAMAC) interface of ARW Elektronik, Germany --
3
// the main body of the driver
4
//
5
// (c) 2000-2002 ARW Elektronik
6
//
7
// this source code is published under GPL (Open Source). You can use, redistribute and 
8
// modify it unless this header   is not modified or deleted. No warranty is given that 
9
// this software will work like expected.
10
// This product is not authorized for use as critical component in life support systems
11
// wihout the express written approval of ARW Elektronik Germany.
12
//
13
// Please announce changes and hints to ARW Elektronik
14
//
15
// what                                            who          when
16
// started out of pcivme sources                   AR           25.03.2000
17
// added IRQ handling                              AR           24.02.2001
18
// Added AUTOREAD functionality                    AR           17.03.2001
19
// Added LCR_READ                                  AR           31.03.2001
20
// resource allocation registers idle entries too  AR           25.11.2001
21
// changed making procedure (only VCC > 6.0)       AR           30.05.2002
22
// totally rearanged resource alloc for WIN2000    AR           01.06.2002
23
// version 2.14 eleminates PLXBUG in WIN2000       AR           05.06.2002
24
// added KeSynchronizeExecution for interrupt sync AR           16.06.2002
25
//
26
 
27
//------------------------------------------------------------------------
28
// DEFINES
29
//
30
#ifndef DWORD
31
#define DWORD ULONG
32
#endif
33
 
34
#ifndef WORD
35
#define WORD USHORT
36
#endif
37
 
38
#define CTL_INDEX(x) ((x >> 2) & 0xFF)  // get user control code as index
39
#define RESOURCE_ENTRY_COUNT 6          // WIN2000 forces to claim all entries
40
 
41
#define DOS_DEVICE_NAME L"\\DosDevices\\PCICC32:"
42
 
43
//-------------------------------------------------------------------------
44
// INCLUDES
45
//
46
 
47
#include <ntddk.h>
48
#include <devioctl.h>
49
// #include <wdm.h>
50
 
51
#include <pcicc32_drv.h>
52
#include <pcicc32.h>
53
#include <pcicc32_v.h>
54
#include <pcicc32_i.h>
55
#include <pcicc32_io.h>
56
 
57
 
58
//------------------------------------------------------------------------
59
// TYPEDEFS
60
//
61
typedef struct
62
{
63
        FILE_OBJ  *file_obj;
64
        PCIADA    *pciada;
65
        PVOID     pOutputBuffer;
66
        PVOID     pInputBuffer;
67
        ULONG     Address;
68
        DWORD     Length;
69
} SYNC_CONTEXT;
70
 
71
//------------------------------------------------------------------------
72
// GLOBALS
73
//
74
 
75
//------------------------------------------------------------------------
76
// FUNCTIONS
77
//
78
 
79
//------------------------------------------------------------------------
80
// for debug only - print interrupt line
81
//
82
#if DBG
83
void PrintInterruptLine(int Bus, int Slot)
84
{
85
  PCI_COMMON_CONFIG pci_config;
86
 
87
  HalGetBusData( PCIConfiguration,                      // Bustype 
88
                                 Bus,                                   // PCI-Busnumber
89
                         Slot,                                          // Slotnumber
90
                                 (PVOID) &(pci_config),     // Pointer for the PCI-Information
91
                                 sizeof(PCI_COMMON_CONFIG));
92
 
93
  KdPrint(("Irql: %d\n", pci_config.u.type0.InterruptLine));
94
}
95
#endif
96
 
97
//------------------------------------------------------------------------
98
// get the cc32 number out of the filename
99
//
100
NTSTATUS InterpreteFileName(PCHAR name, int *nCC32)
101
{
102
        char *ptr = name;
103
    char *n   = "cc32_";
104
        int  h = -1;  // high part
105
        int  l = -1;  // low part
106
 
107
        if (*ptr == '\\') ptr++; // jump over leading ...
108
 
109
    while (*n)                           // compare the basename
110
          if (*n == tolower(*ptr))     
111
          {
112
                  n++;
113
                  ptr++;
114
          }
115
          else
116
                  return STATUS_NO_SUCH_FILE;
117
 
118
        h = *ptr - '0';                  // get the number
119
        ptr++;
120
        l = *ptr - '0';
121
 
122
        if (*ptr == 0)                   // still over the end ??
123
        {
124
                l = h;
125
                h = 0;
126
        }
127
        else
128
          ptr++;
129
 
130
        if ((h < 0) || (l < 0) || (*ptr != 0))  // anything wrong ??
131
                  return STATUS_NO_SUCH_FILE;
132
 
133
        *nCC32 = (h * 10) + l;  // calculate number
134
 
135
        if (*nCC32 >= PCICC32_MAX_CC32) // out of range ??
136
                  return STATUS_NO_SUCH_FILE;
137
 
138
        return STATUS_SUCCESS;
139
}
140
 
141
//------------------------------------------------------------------------
142
// the ultimate driver unload
143
VOID PCICC32Unload(PDRIVER_OBJECT driverObj)
144
{
145
        int              i;
146
        UNICODE_STRING symbol_name;
147
        DEVICE_EXT *ext = (DEVICE_EXT*)(driverObj->DeviceObject->DeviceExtension);
148
        int         nPCIADAs = ext->nPCIADAs;
149
        PCIADA      *pciada;
150
 
151
    KdPrint(("PCICC32Unload()\n"));
152
 
153
        switch (ext->nInitState)
154
        {
155
                case 8:
156
                case 7:
157
                case 6:
158
                        // stop interrupts and shut off
159
                        PCICC32DeInitPCIADAs(driverObj->DeviceObject);
160
                        PCICC32DisConnectInterrupt(driverObj->DeviceObject);
161
                case 5:
162
                        // KeInitializeDpc has no counterpart
163
                case 4:
164
                        for (i = 0; i < nPCIADAs; i++)
165
                        {
166
                                pciada = &ext->pciada[i];
167
                                if (pciada->pvVirtLcr != NULL)
168
                                        MmUnmapIoSpace(pciada->pvVirtLcr, LCR_SPACE);
169
                                if (pciada->pvVirtIfr != NULL)
170
                                        MmUnmapIoSpace(pciada->pvVirtIfr, IFR_SPACE);
171
                        }
172
                case 3:
173
                        // HalGetInterruptVector has no counterpart
174
                case 2:
175
                        // HalTranslateBusAddress has no counterpart
176
                case 1:
177
                        PCICC32FreeResources(driverObj->DeviceObject);
178
                default:
179
                case 0:
180
                        RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
181
 
182
                        // delete the symbolicLink in the registry 
183
                        IoDeleteSymbolicLink( &symbol_name);
184
 
185
                        // delete the deviceObject 
186
                        IoDeleteDevice(driverObj->DeviceObject);
187
        }
188
 
189
        KdPrint(("PCICC32Unload() OK.\n"));
190
}
191
 
192
 
193
//------------------------------------------------------------------------
194
// called at CreateFile()
195
NTSTATUS PCICC32Open(PDEVICE_OBJECT deviceObj, PIRP Irp)
196
{
197
        NTSTATUS result = STATUS_SUCCESS;
198
    ANSI_STRING name;
199
    int nCC32;
200
        int i;
201
        DEVICE_EXT      *pDevExt = (DEVICE_EXT *)(deviceObj->DeviceExtension);
202
        PCIADA      *pciada;
203
        FILE_OBJ        *file_obj;
204
 
205
        name.Buffer = NULL;
206
    name.MaximumLength = 80;
207
 
208
        result = RtlUnicodeStringToAnsiString(&name, &(Irp->Tail.Overlay.OriginalFileObject->FileName), TRUE);
209
        if (result != STATUS_SUCCESS) goto fin;
210
 
211
        KdPrint(("PCICC32Open(%s)\n", name.Buffer));
212
 
213
        result = InterpreteFileName(name.Buffer, &nCC32);
214
    if (result != STATUS_SUCCESS) goto fin;
215
 
216
    KdPrint(("PCICC32Open(%d)\n", nCC32));
217
        RtlFreeAnsiString(&name);
218
 
219
    file_obj = (FILE_OBJ *)ExAllocatePool(NonPagedPool, sizeof(FILE_OBJ));
220
        if (file_obj == (FILE_OBJ *)NULL)
221
        {
222
                result = STATUS_NO_MEMORY;
223
                goto fin;
224
        }
225
 
226
        file_obj->uwAssociatedCC32  = (USHORT) nCC32;
227
 
228
    Irp->Tail.Overlay.OriginalFileObject->FsContext = (PVOID)file_obj;
229
 
230
        result = PCICC32ScanCC32(deviceObj);
231
        if (result != STATUS_SUCCESS) goto fin;
232
 
233
        for (i = 0; i < pDevExt->nPCIADAs; i++)
234
        {
235
          pciada = &pDevExt->pciada[i];
236
 
237
          if (pciada->wModuleNumber == nCC32)
238
          {
239
                  pDevExt->cc32[nCC32] = pciada; // create association
240
                  pciada->dwLinkCount++;
241
 
242
                  enableCC32(pciada);
243
                  break;
244
          }
245
        }
246
 
247
        if (i >= pDevExt->nPCIADAs)
248
        {
249
                result = STATUS_NO_SUCH_FILE;
250
                goto fin;
251
        }
252
 
253
        fin:
254
        Irp->IoStatus.Status = result;
255
        Irp->IoStatus.Information = 0;
256
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
257
 
258
        return result;
259
}
260
 
261
//------------------------------------------------------------------------
262
// called at close()
263
NTSTATUS PCICC32Close(PDEVICE_OBJECT deviceObj, PIRP Irp)
264
{
265
        DEVICE_EXT      *pDevExt  = (DEVICE_EXT *)(deviceObj->DeviceExtension);
266
        FILE_OBJ    *file_obj = (FILE_OBJ *)NULL;
267
        PCIADA      *pciada;                   
268
 
269
        file_obj = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
270
 
271
    KdPrint(("PCICC32Close(%d)\n", file_obj->uwAssociatedCC32));
272
 
273
        if (file_obj != (FILE_OBJ *)NULL)
274
        {
275
                pciada = pDevExt->cc32[file_obj->uwAssociatedCC32];
276
                pciada->dwLinkCount--;
277
 
278
                // disable interrupts when closing
279
                if (pciada->pIrqControlFile == file_obj)
280
                {
281
                        pciada->pIrqControlFile = (FILE_OBJ *)NULL;
282
                        globalInterruptDisable(pciada);
283
                }
284
 
285
                // cancel any blocking Irp origin from this file
286
                if (file_obj->blockingIrp != (PIRP)NULL)
287
                        file_obj->blockingIrp = (PIRP)NULL;
288
 
289
                if (pciada->pBlockingIrp == &file_obj->blockingIrp)
290
                        pciada->pBlockingIrp = (PIRP *)NULL;
291
 
292
                if (!pciada->dwLinkCount)
293
                          disableCC32(pciada);
294
 
295
                ExFreePool(file_obj);
296
                Irp->Tail.Overlay.OriginalFileObject->FsContext = (FILE_OBJ *)NULL;
297
        }
298
 
299
        KdPrint(("PCICC32Close OK\n"));
300
 
301
    Irp->IoStatus.Status = STATUS_SUCCESS;
302
        Irp->IoStatus.Information = 0;
303
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
304
 
305
        return STATUS_SUCCESS;
306
}
307
 
308
//------------------------------------------------------------------------
309
// called at 
310
NTSTATUS PCICC32Shutdown(PDEVICE_OBJECT deviceObj, PIRP irp)
311
{
312
        UNREFERENCED_PARAMETER(irp);
313
        KdPrint(("PCICC32Shutdown()\n"));
314
 
315
        // deinit interfaces and interrupts
316
        PCICC32DeInitPCIADAs(deviceObj);
317
 
318
    KdPrint(("PCICC32Shutdown() OK\n"));
319
 
320
        return STATUS_SUCCESS;
321
}
322
 
323
//------------------------------------------------------------------------
324
// called at ioctl()
325
NTSTATUS PCICC32DeviceControl(PDEVICE_OBJECT deviceObj, PIRP Irp)
326
{
327
        PIO_STACK_LOCATION IrpStack;
328
        int   nIndex;
329
 
330
        IrpStack  = IoGetCurrentIrpStackLocation(Irp);
331
        nIndex    = CTL_INDEX(IrpStack->Parameters.DeviceIoControl.IoControlCode);
332
 
333
    KdPrint(("PCICC32DeviceControl(%d / 0x%08x)\n", nIndex, Irp->Tail.Overlay.OriginalFileObject));
334
 
335
        if (nIndex > CTL_INDEX(PCICC32_LAST_CTL_CODE))
336
        {
337
                KdPrint(("LastIndex(%d)\n", CTL_INDEX(PCICC32_LAST_CTL_CODE)));
338
                Irp->IoStatus.Status      = STATUS_UNSUCCESSFUL;
339
                Irp->IoStatus.Information = 0;
340
                IoCompleteRequest(Irp,IO_NO_INCREMENT);
341
 
342
        KdPrint(("PCICC32DeviceControl() FAIL.\n"));
343
 
344
                return STATUS_UNSUCCESSFUL;
345
        }
346
 
347
        return ioctl[nIndex](deviceObj, Irp, IrpStack);
348
}
349
 
350
 
351
//------------------------------------------------------------------------
352
// called at read()
353
static BOOLEAN PCICC32Read_kernel(PVOID pvContext)
354
{
355
        register SYNC_CONTEXT *context = (SYNC_CONTEXT *)pvContext;
356
        register ULONG i = 0;
357
        USHORT   wCntrl;
358
 
359
        wCntrl = READ_REGISTER_USHORT(context->pciada->pwCntrl);
360
        if (context->file_obj->wBlockTransfer & AUTOREAD)
361
        {
362
                wCntrl &= ~0x0004;  // enable autoread - set bit to 0
363
                WRITE_REGISTER_USHORT(context->pciada->pwCntrl, wCntrl);                               
364
        }
365
 
366
        // do the read ---
367
        if (context->file_obj->wBlockTransfer & UNTIL_NOT_Q)
368
        {
369
                // read first time to get Q information
370
                register ULONG tempBuffer = READ_REGISTER_ULONG((ULONG *)context->Address);
371
 
372
                if (context->file_obj->wAccessType == WORD_ACCESS)
373
                {
374
                        PUSHORT pwBuffer = (PUSHORT)context->pOutputBuffer;
375
                        PUSHORT pwBufEnd = (PUSHORT)((PUCHAR)context->pOutputBuffer + context->Length);
376
 
377
                        while ((tempBuffer & 0x80000000) && (pwBuffer < pwBufEnd))
378
                        {
379
                                *pwBuffer++ = (USHORT)tempBuffer;
380
                                tempBuffer = READ_REGISTER_ULONG((ULONG *)context->Address);  // read the same address multiple times as long to get Q
381
                                i++;
382
                        }
383
                }
384
                else
385
                {
386
                        // LONG_ACCESS
387
                        PULONG pdwBuffer = (PULONG)context->pOutputBuffer;
388
                        PULONG pdwBufEnd = (PULONG)((PUCHAR)context->pOutputBuffer + context->Length);
389
 
390
                        while ((tempBuffer & 0x80000000) && (pdwBuffer < pdwBufEnd))
391
                        {
392
                                *pdwBuffer++ = tempBuffer;
393
                                tempBuffer   = READ_REGISTER_ULONG((ULONG *)context->Address);  // read the same address multiple times as long to get Q
394
                                i++;
395
                        }
396
                }
397
 
398
                i *= context->file_obj->wAccessType;
399
 
400
                KdPrint(("UNTIL_NOT_Q, 0x%08x bytes read\n", i));
401
        }
402
        else // no UNTIL_NOT_Q
403
        {
404
                while (i < context->Length)
405
                {
406
                        context->file_obj->fRead((void *)((PUCHAR)context->pOutputBuffer + i), (void *)context->Address);  // read the same address multiple times
407
                        i += context->file_obj->wAccessType;
408
                }
409
        }
410
 
411
        // disable autoread unconditionally - set bit to 1
412
        wCntrl |= 0x0004;  
413
        WRITE_REGISTER_USHORT(context->pciada->pwCntrl, wCntrl);
414
 
415
    context->Length = i;       
416
 
417
        return TRUE;
418
}
419
 
420
NTSTATUS PCICC32Read(PDEVICE_OBJECT device_Obj, PIRP Irp)
421
{
422
        NTSTATUS        Status        = STATUS_SUCCESS;
423
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
424
        DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
425
        SYNC_CONTEXT context;
426
 
427
        context.file_obj              = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
428
        context.pciada                = pDevExt->cc32[context.file_obj->uwAssociatedCC32];
429
        context.pOutputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
430
        context.Address           = IrpStack->Parameters.Read.ByteOffset.LowPart;  
431
        context.Length            = 0;
432
 
433
        KdPrint(("PCICC32Read(%d)\n", context.file_obj->uwAssociatedCC32));
434
 
435
        if (context.Address > IFR_SPACE)
436
                Status = STATUS_ACCESS_VIOLATION;
437
        else
438
        {
439
                // do here in between what has to be done -----------------
440
                context.Length = IrpStack->Parameters.Read.Length;
441
                KdPrint(("Address = 0x%08x, Length = 0x%08x\n", context.Address, context.Length));
442
                context.Address = (ULONG)context.pciada->pvVirtIfr + context.Address;
443
 
444
                KeSynchronizeExecution(context.pciada->InterruptObject, PCICC32Read_kernel, &context);
445
                // do here in between what has to be done end -------------
446
        }
447
 
448
        Irp->IoStatus.Status      = Status;  
449
        Irp->IoStatus.Information = context.Length;  
450
        IoCompleteRequest(Irp,IO_NO_INCREMENT);  
451
 
452
    KdPrint(("PCICC32Read(), Status = 0x%08x\n", Status));
453
 
454
        return Status;
455
}
456
 
457
 
458
//------------------------------------------------------------------------
459
// called at write()
460
static BOOLEAN PCICC32Write_kernel(PVOID pvContext)
461
{
462
        register SYNC_CONTEXT *context = (SYNC_CONTEXT *)pvContext;
463
        register ULONG i = 0;
464
 
465
        // do the write ---
466
        while (i < context->Length)
467
        {
468
                context->file_obj->fWrite((void *)context->Address, (void *)((PUCHAR)context->pInputBuffer + i));  // write the same address multiple times
469
                i += context->file_obj->wAccessType;
470
        }
471
 
472
        context->Length = i;
473
 
474
        return TRUE;
475
}
476
 
477
NTSTATUS PCICC32Write(PDEVICE_OBJECT device_Obj, PIRP Irp)
478
{
479
        NTSTATUS        Status        = STATUS_SUCCESS;
480
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
481
        DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
482
        SYNC_CONTEXT context;
483
 
484
        context.file_obj              = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
485
        context.pciada                = pDevExt->cc32[context.file_obj->uwAssociatedCC32];
486
        context.pInputBuffer = ((void *)(MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)));
487
        context.Address           = IrpStack->Parameters.Read.ByteOffset.LowPart;  
488
        context.Length            = 0;
489
 
490
        KdPrint(("PCICC32Write(%d)\n", context.file_obj->uwAssociatedCC32));
491
 
492
        if (context.Address > IFR_SPACE)
493
                Status = STATUS_ACCESS_VIOLATION;
494
        else
495
        {
496
//              register ULONG i = 0;
497
 
498
                // do here in between what has to be done -----------------
499
                context.Length    = IrpStack->Parameters.Read.Length;
500
                KdPrint(("Address = 0x%08x, Length = 0x%08x\n", context.Address, context.Length));
501
                context.Address   = (ULONG)context.pciada->pvVirtIfr + context.Address;
502
 
503
                KeSynchronizeExecution(context.pciada->InterruptObject, PCICC32Write_kernel, &context);
504
                // do here in between what has to be done end -------------
505
        }
506
 
507
 
508
        Irp->IoStatus.Status      = Status;  
509
        Irp->IoStatus.Information = context.Length;  
510
        IoCompleteRequest(Irp,IO_NO_INCREMENT);  
511
 
512
    KdPrint(("PCICC32Write(), Status = 0x%08x\n", Status));
513
 
514
        return Status;
515
}
516
 
517
//------------------------------------------------------------------------
518
// search for pciada's
519
//
520
NTSTATUS SearchDevices(PDEVICE_OBJECT device_Obj)
521
{
522
  PCI_SLOT_NUMBER   SlotNumber;
523
  PCI_COMMON_CONFIG pci_config;
524
  PCIADA            *pciada;
525
  ULONG             length;
526
  int               *found;
527
  int               i,j,k;
528
 
529
  KdPrint(("SearchDevices()\n"));
530
 
531
  // prepare structures ----------------------------------------
532
  found  = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
533
  *found = 0;
534
  for (i = 0; i < PCICC32_MAX_PCIADA; i++)
535
  {
536
        pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
537
 
538
        pciada->Bus                = -1;
539
    pciada->Slot.u.AsULONG     = 0xFFFFFFFF;
540
  }
541
 
542
  // search for pciada's ---------------------------------------
543
  SlotNumber.u.bits.Reserved = 0;
544
 
545
  for (j = 0; j < PCI_MAX_BUSES; j++)
546
  {
547
    for (i = 0; i < PCI_MAX_DEVICES; i++)
548
        {
549
          SlotNumber.u.bits.DeviceNumber = i;
550
          for (k = 0; k < PCI_MAX_FUNCTION; k++)
551
          {
552
                SlotNumber.u.bits.FunctionNumber = k;
553
            length = HalGetBusData( PCIConfiguration,         // Bustype 
554
                                                            j,                                    // PCI-Busnumber
555
                                                            SlotNumber.u.AsULONG,     // Slotnumber
556
                                                            (PVOID) &(pci_config),    // Pointer for the PCI-Information
557
                                                            sizeof(PCI_COMMON_CONFIG) );
558
 
559
                if ((pci_config.VendorID    == PCICC32_VENDOR_ID) &&
560
                        (pci_config.DeviceID    == PCICC32_DEVICE_ID) &&
561
                        (pci_config.u.type0.SubSystemID == PCICC32_SUBSYS_ID) &&
562
                        (pci_config.u.type0.SubVendorID == PCICC32_SUBVEN_ID) &&
563
                        (pci_config.u.type0.BaseAddresses[3]))
564
                {
565
               pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[*found];
566
 
567
               memcpy(&pciada->PCIDevice, &pci_config, sizeof(pci_config));
568
                   pciada->Slot = SlotNumber;
569
                   pciada->Bus  = j;
570
 
571
                   KdPrint(("PCIADA found @ Bus/Slot %d/%d.\n", pciada->Bus, pciada->Slot.u.AsULONG));
572
 
573
                   (*found)++;
574
                   if (*found >= PCICC32_MAX_PCIADA) return STATUS_SUCCESS;
575
                }
576
          }
577
        }              
578
  }
579
 
580
  return STATUS_SUCCESS;
581
}
582
 
583
//---------------------------------------------------------------
584
// function to call for bug fix of PLX9050 build in bug
585
//
586
NTSTATUS PLX9050BugFix(PDEVICE_OBJECT device_Obj)
587
{
588
        DEVICE_EXT *DeviceExtension = (DEVICE_EXT*)device_Obj->DeviceExtension;
589
        int i;
590
        ULONG dwData;
591
        PCIADA *pciada;
592
 
593
        KdPrint(("PLX9050BugFix()\n"));
594
 
595
        for (i = 0; i < DeviceExtension->nPCIADAs; i++)
596
        {
597
                pciada = &DeviceExtension->pciada[i];
598
 
599
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[0]) & 0x80)
600
                {      
601
                        KdPrint(("Changing address 0:0x%p with 4:0x%p\n",
602
                                pciada->PCIDevice.u.type0.BaseAddresses[0],
603
                                pciada->PCIDevice.u.type0.BaseAddresses[4]));
604
 
605
                        pciada->PCIDevice.u.type0.BaseAddresses[0] =           // exchange
606
                                pciada->PCIDevice.u.type0.BaseAddresses[4];
607
                        pciada->PCIDevice.u.type0.BaseAddresses[4] = dwData;
608
 
609
                        if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
610
                                  pciada->Slot.u.AsULONG,
611
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[0],
612
                                                0x10, 4) != 4)
613
                        return STATUS_UNSUCCESSFUL;
614
 
615
                        if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
616
                                  pciada->Slot.u.AsULONG,
617
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[4],
618
                                                0x20, 4) != 4)
619
                        return STATUS_UNSUCCESSFUL;
620
                }
621
 
622
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[1]) & 0x80)
623
                {
624
                        KdPrint(("Changing address 1:0x%p with 5:0x%p\n",
625
                                pciada->PCIDevice.u.type0.BaseAddresses[1],
626
                                pciada->PCIDevice.u.type0.BaseAddresses[5]));
627
 
628
                  pciada->PCIDevice.u.type0.BaseAddresses[1] =           // exchange
629
                                pciada->PCIDevice.u.type0.BaseAddresses[5];
630
                  pciada->PCIDevice.u.type0.BaseAddresses[5] = dwData;
631
 
632
                  if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
633
                                  pciada->Slot.u.AsULONG,
634
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[1],
635
                                                0x14, 4) != 4)
636
                        return STATUS_UNSUCCESSFUL;
637
 
638
                  if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
639
                                  pciada->Slot.u.AsULONG,
640
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[5],
641
                                                0x24, 4) != 4)
642
                        return STATUS_UNSUCCESSFUL;
643
                }
644
        }
645
 
646
        return STATUS_SUCCESS;
647
}
648
 
649
 
650
//------------------------------------------------------------------------
651
//  reserve resources for PCIADAs 
652
//
653
NTSTATUS PCICC32ExtractResources(PCIADA *pciada, PCM_RESOURCE_LIST pList)
654
{
655
        PCM_RESOURCE_LIST pResourceList;
656
        PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
657
        PCM_PARTIAL_RESOURCE_LIST pPartialList;
658
        PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialDescriptor;
659
        int i;
660
        int bug = 0;
661
 
662
        KdPrint(("PCICC32ExtractResources()\n"));
663
 
664
        pResourceList   = pList;
665
        pFullDescriptor = pResourceList->List;
666
        pPartialList    = &pFullDescriptor->PartialResourceList;
667
 
668
        for (i=0; i<(int)pPartialList->Count; i++)
669
        {
670
                pPartialDescriptor = &pPartialList->PartialDescriptors[i];
671
                switch (pPartialDescriptor->Type)
672
                {
673
                        case CmResourceTypeInterrupt:
674
                                pciada->Irql     = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
675
                                pciada->Vector   = pPartialDescriptor->u.Interrupt.Vector;
676
                                pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
677
 
678
                                KdPrint(("Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
679
                                        pciada->Irql, pciada->Vector, pciada->Affinity));
680
                                break;
681
                        case CmResourceTypeDma:
682
                                KdPrint(("Dma    : \n"));
683
                                break;
684
                        case CmResourceTypePort:
685
 
686
                                KdPrint(("Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
687
                                break;
688
                        case CmResourceTypeMemory:
689
                                // special handling of PLXBUG here because of WIN2000
690
                                // WIN2000 doesn't recognize late address changes
691
                                if (!bug)
692
                                {
693
                                        if (i == 0)
694
                                        {
695
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
696
 
697
                                                if (pciada->pvPhysLcr.LowPart & 0x80)
698
                                                        bug = 1;
699
                                        }
700
                                }
701
                                else
702
                                {
703
                                        if (i == 3)
704
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
705
                                }
706
 
707
                                if (i == 2)
708
                                        pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
709
 
710
                                KdPrint(("Memory : 0x%p\n", (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
711
                                break;
712
                }
713
        }
714
 
715
        if (pciada->Irql == 0)
716
                return STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
717
 
718
        KdPrint(("PCICC32ExtractResources() OK.\n"));
719
 
720
        return STATUS_SUCCESS;
721
}
722
 
723
NTSTATUS PCICC32ReserveResources(PDEVICE_OBJECT device_Obj)
724
{
725
        PCM_RESOURCE_LIST pList = NULL;
726
        NTSTATUS result = STATUS_SUCCESS;
727
        int i;
728
        DEVICE_EXT *pDevExt = (DEVICE_EXT*)(device_Obj->DeviceExtension);
729
        int nPCIADAs = pDevExt->nPCIADAs;
730
        PCIADA *pciada;
731
    UNICODE_STRING DriverClassName;
732
 
733
        KdPrint(("PCICC32ReserveResources()\n"));
734
 
735
        // prepare resource claiming
736
        RtlInitUnicodeString(&DriverClassName, L"PCICC32");
737
 
738
        // cycle through all busses and slots assigned to PCIADAs
739
        for (i = 0; i < nPCIADAs; i++)
740
    {
741
                pciada = &pDevExt->pciada[i];
742
 
743
                result = HalAssignSlotResources(NULL, &DriverClassName, device_Obj->DriverObject, device_Obj,
744
                        PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, &pList);
745
 
746
                if (result != STATUS_SUCCESS)
747
                        break;
748
 
749
                result = PCICC32ExtractResources(pciada, pList);
750
 
751
                if (result != STATUS_SUCCESS)
752
                        break;
753
        }
754
 
755
        // its my part to free allocated resources
756
        ExFreePool(pList);
757
 
758
        KdPrint(("PCICC32ReserveResources(0x%08x)\n", result));
759
 
760
        return result;
761
};
762
 
763
//------------------------------------------------------------------------
764
//  free resources from PCIADAs 
765
//
766
NTSTATUS PCICC32FreeResources(PDEVICE_OBJECT device_Obj)
767
{
768
        CM_RESOURCE_LIST ResList;
769
        BOOLEAN          bConflict;
770
    UNICODE_STRING   DriverClassName;
771
 
772
    KdPrint(("PCICC32FreeResources()\n"));
773
 
774
        RtlInitUnicodeString(&DriverClassName, L"PCICC32");
775
 
776
        ResList.Count = 0;
777
 
778
        IoReportResourceUsage(&DriverClassName, device_Obj->DriverObject,
779
                                         &ResList, sizeof(ResList), device_Obj,
780
                                                                         NULL, 0, FALSE, &bConflict);
781
        return STATUS_SUCCESS;
782
};
783
 
784
 
785
//------------------------------------------------------------------------
786
//  translate memory resources to neutral for PCIADAs 
787
//
788
NTSTATUS PCICC32TranslateBusAddresses(PDEVICE_OBJECT device_Obj)
789
{
790
        int              i;
791
        NTSTATUS         result = STATUS_SUCCESS;
792
        int nPCIADAs = ((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
793
        ULONG            memType0, memType2;
794
        PCIADA           *pciada;
795
 
796
    KdPrint(("TranslateBusAddresseses()\n"));
797
        for (i = 0; i < nPCIADAs; i++)
798
        {
799
      pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
800
 
801
          memType0 = memType2 = 0;
802
 
803
          if (!(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysLcr, &memType0,
804
                                                               &pciada->pvPhysLcr)) ||
805
              !(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysIfr, &memType2,
806
                                                               &pciada->pvPhysIfr)))
807
          {
808
                  result = STATUS_UNSUCCESSFUL;
809
                  break;
810
          }
811
 
812
          if ((memType0) || (memType2))
813
          {
814
                  result = STATUS_UNSUCCESSFUL;
815
                  break;
816
          }
817
        }
818
        return result;
819
}
820
 
821
//------------------------------------------------------------------------
822
//  map address spaces to virtual addresses
823
//
824
NTSTATUS PCICC32MapIOspaces(PDEVICE_OBJECT device_Obj)
825
{
826
        int              i;
827
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
828
        int                              nPCIADAs = pDevExt->nPCIADAs;
829
        PCIADA           *pciada;
830
 
831
        KdPrint(("PCICC32MapIOspaces()\n"));
832
 
833
        for (i = 0; i < nPCIADAs; i++)
834
        {
835
       pciada = &pDevExt->pciada[i];
836
 
837
       if ((pciada->pvVirtLcr = MmMapIoSpace(pciada->pvPhysLcr, LCR_SPACE, FALSE)) == NULL)
838
          return STATUS_UNSUCCESSFUL;
839
       if ((pciada->pvVirtIfr = MmMapIoSpace(pciada->pvPhysIfr, IFR_SPACE, FALSE)) == NULL)
840
          return STATUS_UNSUCCESSFUL;
841
 
842
           KdPrint(("PCIADA %d: LCR 0x%08x IFR 0x%08x\n", i, pciada->pvVirtLcr, pciada->pvVirtIfr));
843
 
844
           pciada->pwIntCSR = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x4C);
845
           pciada->pwCntrl  = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x50);
846
        }
847
 
848
        return STATUS_SUCCESS;
849
}
850
 
851
 
852
//------------------------------------------------------------------------
853
//  initializes and registers a DPC routine for each pciada
854
//
855
NTSTATUS InitializeCustomDPCObjects(PDEVICE_OBJECT device_object)
856
{
857
        int              i;
858
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)(device_object->DeviceExtension);
859
        int              nPCIADAs = pDevExt->nPCIADAs;
860
        PCIADA           *pciada;
861
 
862
        KdPrint(("InitializeCustomDPCObject()\n"));
863
 
864
        for (i = 0; i < nPCIADAs; i++)
865
        {
866
                pciada = &pDevExt->pciada[i];
867
                KeInitializeDpc(&pciada->kDPCobj, fMyDefferedRoutine, (PVOID)device_object);
868
        }
869
 
870
        return STATUS_SUCCESS;
871
}
872
 
873
//------------------------------------------------------------------------
874
// init structures a.s.o.
875
//
876
VOID PCICC32SoftInit(PDEVICE_OBJECT device_Obj)
877
{
878
        int i;
879
        PCIADA *pciada;
880
 
881
        for (i = 0; i < PCICC32_MAX_PCIADA; i++)
882
        {
883
                pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
884
 
885
                pciada->pvPhysLcr.QuadPart = pciada->pvPhysIfr.QuadPart = 0;
886
                pciada->pvVirtLcr = pciada->pvVirtIfr = NULL;
887
 
888
                pciada->bConnected     = FALSE;   // connection still not verified
889
                pciada->wModuleNumber  = 0xFFFF;
890
                pciada->wFPGAVersion   = 0xFFFF;
891
                pciada->wModuleType    = 1;       // always CC32
892
 
893
                pciada->InterruptObject = NULL;
894
                pciada->Irql                    = 0;
895
                pciada->Vector          = 0;
896
                pciada->Affinity                = 0;
897
 
898
                pciada->dwLinkCount     = 0;
899
 
900
                pciada->dwIrqStatus     = 0;
901
                pciada->pBlockingIrp    = (PIRP *)NULL;
902
 
903
                pciada->pIrqControlFile = (FILE_OBJ *)NULL;
904
        }
905
 
906
        // no CC32 associated to any PCIADA
907
        for (i = 0; i < PCICC32_MAX_CC32; i++)
908
          ((DEVICE_EXT*)(device_Obj->DeviceExtension))->cc32[i] = NULL;
909
}
910
 
911
//------------------------------------------------------------------------
912
// the ultimate starting point of a driver
913
NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath)
914
{
915
        int            i;
916
        PDEVICE_OBJECT device_object;                   // pointer to the device object
917
        UNICODE_STRING device_name;
918
        UNICODE_STRING symbol_name;
919
        NTSTATUS result = STATUS_SUCCESS;
920
        PCIADA         *pciada;                                 // pointer to a PCIADA
921
        int            nPCIADAs;                                // count of PCIADAs
922
        DEVICE_EXT     *DeviceExtension = NULL;
923
        UNREFERENCED_PARAMETER(regPath);
924
    KdPrint(("DriverEntry() ----%d.%d-------------------------\n", (DRIVER_VERSION >> 16) & 0xFFFF, DRIVER_VERSION & 0xFFFF));
925
 
926
        driverObj->DriverUnload = PCICC32Unload;
927
        driverObj->MajorFunction[IRP_MJ_CREATE]            = PCICC32Open;
928
        driverObj->MajorFunction[IRP_MJ_CLOSE]             = PCICC32Close;
929
        driverObj->MajorFunction[IRP_MJ_READ]              = PCICC32Read;
930
    driverObj->MajorFunction[IRP_MJ_WRITE]             = PCICC32Write;
931
        driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]    = PCICC32DeviceControl;
932
    driverObj->MajorFunction[IRP_MJ_SHUTDOWN]          = PCICC32Shutdown;
933
 
934
        RtlInitUnicodeString(&device_name, L"\\Device\\CC32");
935
 
936
        /* DeviceObject durch IO-Manager erzeugen */
937
        result = IoCreateDevice( driverObj,           // DriverObject received by the DriverEntry Call
938
                                                         sizeof(DEVICE_EXT),  // required Memory for the DeviceExtension
939
                                                         &device_name,        // Name of the device in the device-Directory
940
                                                         FILE_DEVICE_UNKNOWN, // Device-ID              
941
                                                         0,                   // Device-Characteristics normal 0
942
                                                         FALSE,               // TRUE : one Thread can open the driver
943
                                                         &device_object);     // DeviceObject returned from the IO-Manager
944
 
945
        // defines how the data are handled between user / kernel Adress-Space  
946
        device_object->Flags |= DO_DIRECT_IO;
947
 
948
        // anounce driver as symbolic device ---------------------------------
949
        if (result == STATUS_SUCCESS)
950
        {
951
                /* now the symbolic Link is created. If there is no S.L. a program cannot connect to the driver */
952
                RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
953
                result = IoCreateSymbolicLink(&symbol_name,&device_name);
954
                if (result != STATUS_SUCCESS)
955
                {
956
                        IoDeleteDevice(device_object);
957
                        return result;
958
                }
959
        }
960
        else
961
                return result;
962
 
963
        DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
964
 
965
        DeviceExtension->actualIrp  = NULL;
966
        DeviceExtension->nInitState = 0;
967
 
968
        // init pciada structures ------------------------------------
969
        PCICC32SoftInit(device_object);
970
 
971
        // search for PCIADAs ----------------------------------------
972
        result   = SearchDevices(device_object);
973
        nPCIADAs = DeviceExtension->nPCIADAs;
974
 
975
        if ((result != STATUS_SUCCESS) || !(nPCIADAs))
976
        {
977
                PCICC32Unload(driverObj);    
978
                return STATUS_DEVICE_DOES_NOT_EXIST;
979
        }
980
 
981
        // request exclusive ownership of .. ---------------------------------
982
        if ((result = PCICC32ReserveResources(device_object)) != STATUS_SUCCESS)
983
        {
984
                PCICC32Unload(driverObj);    
985
                return result;
986
        }
987
        else
988
                DeviceExtension->nInitState++;
989
 
990
        // fix PLX9050 Bug -------------------------------------------
991
        if ((result = PLX9050BugFix(device_object)) != STATUS_SUCCESS)
992
        {
993
                PCICC32Unload(driverObj);    
994
                return result;
995
        }
996
 
997
        // translate BUS relative addresses ----------------------------------
998
        if ((result = PCICC32TranslateBusAddresses(device_object)) != STATUS_SUCCESS)
999
        {
1000
                PCICC32Unload(driverObj);    
1001
                return STATUS_DEVICE_DOES_NOT_EXIST;
1002
        }
1003
        else
1004
                DeviceExtension->nInitState++;
1005
 
1006
        // translate Interrupt Resources used --------------------------------
1007
        if ((result = PCICC32TranslateInterrupt(device_object)) != STATUS_SUCCESS)
1008
        {
1009
                PCICC32Unload(driverObj);    
1010
                return STATUS_DEVICE_DOES_NOT_EXIST;
1011
        }
1012
        else
1013
                DeviceExtension->nInitState++;
1014
 
1015
        // map address spaces to virtual addresses ---------------------------
1016
        if ((result = PCICC32MapIOspaces(device_object)) != STATUS_SUCCESS)
1017
        {
1018
                PCICC32Unload(driverObj);    
1019
                return STATUS_DEVICE_DOES_NOT_EXIST;
1020
        }
1021
        else
1022
                DeviceExtension->nInitState++;
1023
 
1024
        // initialze my custom DPC objects -----------------------------------
1025
        if ((result = InitializeCustomDPCObjects(device_object)) != STATUS_SUCCESS)
1026
        {
1027
                PCICC32Unload(driverObj);    
1028
                return result;
1029
        }
1030
        else
1031
                DeviceExtension->nInitState++;
1032
 
1033
        // disable all interrupts --------------------------------------------
1034
        for (i = 0; i < nPCIADAs; i++)
1035
        {
1036
                pciada = &DeviceExtension->pciada[i];
1037
 
1038
                globalInterruptDisable(pciada);
1039
        }
1040
 
1041
        // connect interrupts to service routines ----------------------------
1042
        if ((result = PCICC32ConnectInterrupt(device_object)) != STATUS_SUCCESS)
1043
        {
1044
                PCICC32Unload(driverObj);    
1045
                return STATUS_DEVICE_DOES_NOT_EXIST;
1046
        }
1047
        else
1048
                DeviceExtension->nInitState++;
1049
 
1050
        // scan all connected CC32 for info and later use -------------------
1051
        if ((result = PCICC32ScanCC32(device_object)) != STATUS_SUCCESS)
1052
        {
1053
                PCICC32Unload(driverObj);    
1054
                return STATUS_DEVICE_DOES_NOT_EXIST;
1055
        }
1056
 
1057
        device_object->Flags &= ~DO_DEVICE_INITIALIZING;
1058
 
1059
    KdPrint(("DriverEntry() OK.\n"));
1060
 
1061
        return result;
1062
}
1063