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  = 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
    KdPrint(("PCICC32Shutdown()\n"));
313
 
314
        // deinit interfaces and interrupts
315
        PCICC32DeInitPCIADAs(deviceObj);
316
 
317
    KdPrint(("PCICC32Shutdown() OK\n"));
318
 
319
        return STATUS_SUCCESS;
320
}
321
 
322
//------------------------------------------------------------------------
323
// called at ioctl()
324
NTSTATUS PCICC32DeviceControl(PDEVICE_OBJECT deviceObj, PIRP Irp)
325
{
326
        PIO_STACK_LOCATION IrpStack;
327
        int   nIndex;
328
 
329
        IrpStack  = IoGetCurrentIrpStackLocation(Irp);
330
        nIndex    = CTL_INDEX(IrpStack->Parameters.DeviceIoControl.IoControlCode);
331
 
332
    KdPrint(("PCICC32DeviceControl(%d / 0x%08x)\n", nIndex, Irp->Tail.Overlay.OriginalFileObject));
333
 
334
        if (nIndex > CTL_INDEX(PCICC32_LAST_CTL_CODE))
335
        {
336
                KdPrint(("LastIndex(%d)\n", CTL_INDEX(PCICC32_LAST_CTL_CODE)));
337
                Irp->IoStatus.Status      = STATUS_UNSUCCESSFUL;
338
                Irp->IoStatus.Information = 0;
339
                IoCompleteRequest(Irp,IO_NO_INCREMENT);
340
 
341
        KdPrint(("PCICC32DeviceControl() FAIL.\n"));
342
 
343
                return STATUS_UNSUCCESSFUL;
344
        }
345
 
346
        return ioctl[nIndex](deviceObj, Irp, IrpStack);
347
}
348
 
349
 
350
//------------------------------------------------------------------------
351
// called at read()
352
static BOOLEAN PCICC32Read_kernel(PVOID pvContext)
353
{
354
        register SYNC_CONTEXT *context = (SYNC_CONTEXT *)pvContext;
355
        register ULONG i = 0;
356
        USHORT   wCntrl;
357
 
358
        wCntrl = READ_REGISTER_USHORT(context->pciada->pwCntrl);
359
        if (context->file_obj->wBlockTransfer & AUTOREAD)
360
        {
361
                wCntrl &= ~0x0004;  // enable autoread - set bit to 0
362
                WRITE_REGISTER_USHORT(context->pciada->pwCntrl, wCntrl);                               
363
        }
364
 
365
        // do the read ---
366
        if (context->file_obj->wBlockTransfer & UNTIL_NOT_Q)
367
        {
368
                // read first time to get Q information
369
                register ULONG tempBuffer = READ_REGISTER_ULONG((ULONG *)context->Address);
370
 
371
                if (context->file_obj->wAccessType == WORD_ACCESS)
372
                {
373
                        PUSHORT pwBuffer = (PUSHORT)context->pOutputBuffer;
374
                        PUSHORT pwBufEnd = (PUSHORT)((PUCHAR)context->pOutputBuffer + context->Length);
375
 
376
                        while ((tempBuffer & 0x80000000) && (pwBuffer < pwBufEnd))
377
                        {
378
                                *pwBuffer++ = (USHORT)tempBuffer;
379
                                tempBuffer = READ_REGISTER_ULONG((ULONG *)context->Address);  // read the same address multiple times as long to get Q
380
                                i++;
381
                        }
382
                }
383
                else
384
                {
385
                        // LONG_ACCESS
386
                        PULONG pdwBuffer = (PULONG)context->pOutputBuffer;
387
                        PULONG pdwBufEnd = (PULONG)((PUCHAR)context->pOutputBuffer + context->Length);
388
 
389
                        while ((tempBuffer & 0x80000000) && (pdwBuffer < pdwBufEnd))
390
                        {
391
                                *pdwBuffer++ = tempBuffer;
392
                                tempBuffer   = READ_REGISTER_ULONG((ULONG *)context->Address);  // read the same address multiple times as long to get Q
393
                                i++;
394
                        }
395
                }
396
 
397
                i *= context->file_obj->wAccessType;
398
 
399
                KdPrint(("UNTIL_NOT_Q, 0x%08x bytes read\n", i));
400
        }
401
        else // no UNTIL_NOT_Q
402
        {
403
                while (i < context->Length)
404
                {
405
                        context->file_obj->fRead((void *)((PUCHAR)context->pOutputBuffer + i), (void *)context->Address);  // read the same address multiple times
406
                        i += context->file_obj->wAccessType;
407
                }
408
        }
409
 
410
        // disable autoread unconditionally - set bit to 1
411
        wCntrl |= 0x0004;  
412
        WRITE_REGISTER_USHORT(context->pciada->pwCntrl, wCntrl);
413
 
414
    context->Length = i;       
415
 
416
        return TRUE;
417
}
418
 
419
NTSTATUS PCICC32Read(PDEVICE_OBJECT device_Obj, PIRP Irp)
420
{
421
        NTSTATUS        Status        = STATUS_SUCCESS;
422
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
423
        DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
424
        SYNC_CONTEXT context;
425
 
426
        context.file_obj              = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
427
        context.pciada                = pDevExt->cc32[context.file_obj->uwAssociatedCC32];
428
        context.pOutputBuffer     = ((void *)(MmGetSystemAddressForMdl(Irp->MdlAddress)));
429
        context.Address           = IrpStack->Parameters.Read.ByteOffset.LowPart;  
430
        context.Length            = 0;
431
 
432
        KdPrint(("PCICC32Read(%d)\n", context.file_obj->uwAssociatedCC32));
433
 
434
        if (context.Address > IFR_SPACE)
435
                Status = STATUS_ACCESS_VIOLATION;
436
        else
437
        {
438
                // do here in between what has to be done -----------------
439
                context.Length = IrpStack->Parameters.Read.Length;
440
                KdPrint(("Address = 0x%08x, Length = 0x%08x\n", context.Address, context.Length));
441
                context.Address = (ULONG)context.pciada->pvVirtIfr + context.Address;
442
 
443
                KeSynchronizeExecution(context.pciada->InterruptObject, PCICC32Read_kernel, &context);
444
                // do here in between what has to be done end -------------
445
        }
446
 
447
        Irp->IoStatus.Status      = Status;  
448
        Irp->IoStatus.Information = context.Length;  
449
        IoCompleteRequest(Irp,IO_NO_INCREMENT);  
450
 
451
    KdPrint(("PCICC32Read(), Status = 0x%08x\n", Status));
452
 
453
        return Status;
454
}
455
 
456
 
457
//------------------------------------------------------------------------
458
// called at write()
459
static BOOLEAN PCICC32Write_kernel(PVOID pvContext)
460
{
461
        register SYNC_CONTEXT *context = (SYNC_CONTEXT *)pvContext;
462
        register ULONG i = 0;
463
 
464
        // do the write ---
465
        while (i < context->Length)
466
        {
467
                context->file_obj->fWrite((void *)context->Address, (void *)((PUCHAR)context->pInputBuffer + i));  // write the same address multiple times
468
                i += context->file_obj->wAccessType;
469
        }
470
 
471
        context->Length = i;
472
 
473
        return TRUE;
474
}
475
 
476
NTSTATUS PCICC32Write(PDEVICE_OBJECT device_Obj, PIRP Irp)
477
{
478
        NTSTATUS        Status        = STATUS_SUCCESS;
479
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
480
        DEVICE_EXT      *pDevExt          = (DEVICE_EXT *)(device_Obj->DeviceExtension);
481
        SYNC_CONTEXT context;
482
 
483
        context.file_obj              = (FILE_OBJ *)Irp->Tail.Overlay.OriginalFileObject->FsContext;
484
        context.pciada                = pDevExt->cc32[context.file_obj->uwAssociatedCC32];
485
        context.pInputBuffer      = ((void *)(MmGetSystemAddressForMdl(Irp->MdlAddress)));
486
        context.Address           = IrpStack->Parameters.Read.ByteOffset.LowPart;  
487
        context.Length            = 0;
488
 
489
        KdPrint(("PCICC32Write(%d)\n", context.file_obj->uwAssociatedCC32));
490
 
491
        if (context.Address > IFR_SPACE)
492
                Status = STATUS_ACCESS_VIOLATION;
493
        else
494
        {
495
                register ULONG i = 0;
496
 
497
                // do here in between what has to be done -----------------
498
                context.Length    = IrpStack->Parameters.Read.Length;
499
                KdPrint(("Address = 0x%08x, Length = 0x%08x\n", context.Address, context.Length));
500
                context.Address   = (ULONG)context.pciada->pvVirtIfr + context.Address;
501
 
502
                KeSynchronizeExecution(context.pciada->InterruptObject, PCICC32Write_kernel, &context);
503
                // do here in between what has to be done end -------------
504
        }
505
 
506
 
507
        Irp->IoStatus.Status      = Status;  
508
        Irp->IoStatus.Information = context.Length;  
509
        IoCompleteRequest(Irp,IO_NO_INCREMENT);  
510
 
511
    KdPrint(("PCICC32Write(), Status = 0x%08x\n", Status));
512
 
513
        return Status;
514
}
515
 
516
//------------------------------------------------------------------------
517
// search for pciada's
518
//
519
NTSTATUS SearchDevices(PDEVICE_OBJECT device_Obj)
520
{
521
  PCI_SLOT_NUMBER   SlotNumber;
522
  PCI_COMMON_CONFIG pci_config;
523
  PCIADA            *pciada;
524
  ULONG             length;
525
  int               *found;
526
  int               i,j,k;
527
 
528
  KdPrint(("SearchDevices()\n"));
529
 
530
  // prepare structures ----------------------------------------
531
  found  = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
532
  *found = 0;
533
  for (i = 0; i < PCICC32_MAX_PCIADA; i++)
534
  {
535
        pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
536
 
537
        pciada->Bus                = -1;
538
    pciada->Slot.u.AsULONG     = 0xFFFFFFFF;
539
  }
540
 
541
  // search for pciada's ---------------------------------------
542
  SlotNumber.u.bits.Reserved = 0;
543
 
544
  for (j = 0; j < PCI_MAX_BUSES; j++)
545
  {
546
    for (i = 0; i < PCI_MAX_DEVICES; i++)
547
        {
548
          SlotNumber.u.bits.DeviceNumber = i;
549
          for (k = 0; k < PCI_MAX_FUNCTION; k++)
550
          {
551
                SlotNumber.u.bits.FunctionNumber = k;
552
            length = HalGetBusData( PCIConfiguration,         // Bustype 
553
                                                            j,                                    // PCI-Busnumber
554
                                                            SlotNumber.u.AsULONG,     // Slotnumber
555
                                                            (PVOID) &(pci_config),    // Pointer for the PCI-Information
556
                                                            sizeof(PCI_COMMON_CONFIG) );
557
 
558
                if ((pci_config.VendorID    == PCICC32_VENDOR_ID) &&
559
                        (pci_config.DeviceID    == PCICC32_DEVICE_ID) &&
560
                        (pci_config.u.type0.SubSystemID == PCICC32_SUBSYS_ID) &&
561
                        (pci_config.u.type0.SubVendorID == PCICC32_SUBVEN_ID) &&
562
                        (pci_config.u.type0.BaseAddresses[3]))
563
                {
564
               pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[*found];
565
 
566
               memcpy(&pciada->PCIDevice, &pci_config, sizeof(pci_config));
567
                   pciada->Slot = SlotNumber;
568
                   pciada->Bus  = j;
569
 
570
                   KdPrint(("PCIADA found @ Bus/Slot %d/%d.\n", pciada->Bus, pciada->Slot.u.AsULONG));
571
 
572
                   (*found)++;
573
                   if (*found >= PCICC32_MAX_PCIADA) return STATUS_SUCCESS;
574
                }
575
          }
576
        }              
577
  }
578
 
579
  return STATUS_SUCCESS;
580
}
581
 
582
//---------------------------------------------------------------
583
// function to call for bug fix of PLX9050 build in bug
584
//
585
NTSTATUS PLX9050BugFix(PDEVICE_OBJECT device_Obj)
586
{
587
        DEVICE_EXT *DeviceExtension = (DEVICE_EXT*)device_Obj->DeviceExtension;
588
        int i;
589
        ULONG dwData;
590
        PCIADA *pciada;
591
 
592
        KdPrint(("PLX9050BugFix()\n"));
593
 
594
        for (i = 0; i < DeviceExtension->nPCIADAs; i++)
595
        {
596
                pciada = &DeviceExtension->pciada[i];
597
 
598
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[0]) & 0x80)
599
                {      
600
                        KdPrint(("Changing address 0:0x%p with 4:0x%p\n",
601
                                pciada->PCIDevice.u.type0.BaseAddresses[0],
602
                                pciada->PCIDevice.u.type0.BaseAddresses[4]));
603
 
604
                        pciada->PCIDevice.u.type0.BaseAddresses[0] =           // exchange
605
                                pciada->PCIDevice.u.type0.BaseAddresses[4];
606
                        pciada->PCIDevice.u.type0.BaseAddresses[4] = dwData;
607
 
608
                        if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
609
                                  pciada->Slot.u.AsULONG,
610
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[0],
611
                                                0x10, 4) != 4)
612
                        return STATUS_UNSUCCESSFUL;
613
 
614
                        if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
615
                                  pciada->Slot.u.AsULONG,
616
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[4],
617
                                                0x20, 4) != 4)
618
                        return STATUS_UNSUCCESSFUL;
619
                }
620
 
621
                if ((dwData = pciada->PCIDevice.u.type0.BaseAddresses[1]) & 0x80)
622
                {
623
                        KdPrint(("Changing address 1:0x%p with 5:0x%p\n",
624
                                pciada->PCIDevice.u.type0.BaseAddresses[1],
625
                                pciada->PCIDevice.u.type0.BaseAddresses[5]));
626
 
627
                  pciada->PCIDevice.u.type0.BaseAddresses[1] =           // exchange
628
                                pciada->PCIDevice.u.type0.BaseAddresses[5];
629
                  pciada->PCIDevice.u.type0.BaseAddresses[5] = dwData;
630
 
631
                  if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
632
                                  pciada->Slot.u.AsULONG,
633
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[1],
634
                                                0x14, 4) != 4)
635
                        return STATUS_UNSUCCESSFUL;
636
 
637
                  if (HalSetBusDataByOffset(PCIConfiguration, pciada->Bus,
638
                                  pciada->Slot.u.AsULONG,
639
                                        (PVOID)&pciada->PCIDevice.u.type0.BaseAddresses[5],
640
                                                0x24, 4) != 4)
641
                        return STATUS_UNSUCCESSFUL;
642
                }
643
        }
644
 
645
        return STATUS_SUCCESS;
646
}
647
 
648
 
649
//------------------------------------------------------------------------
650
//  reserve resources for PCIADAs 
651
//
652
NTSTATUS PCICC32ExtractResources(PCIADA *pciada, PCM_RESOURCE_LIST pList)
653
{
654
        PCM_RESOURCE_LIST pResourceList;
655
        PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
656
        PCM_PARTIAL_RESOURCE_LIST pPartialList;
657
        PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialDescriptor;
658
        int i;
659
        int bug = 0;
660
 
661
        KdPrint(("PCICC32ExtractResources()\n"));
662
 
663
        pResourceList   = pList;
664
        pFullDescriptor = pResourceList->List;
665
        pPartialList    = &pFullDescriptor->PartialResourceList;
666
 
667
        for (i=0; i<(int)pPartialList->Count; i++)
668
        {
669
                pPartialDescriptor = &pPartialList->PartialDescriptors[i];
670
                switch (pPartialDescriptor->Type)
671
                {
672
                        case CmResourceTypeInterrupt:
673
                                pciada->Irql     = (KIRQL)pPartialDescriptor->u.Interrupt.Level;
674
                                pciada->Vector   = pPartialDescriptor->u.Interrupt.Vector;
675
                                pciada->Affinity = pPartialDescriptor->u.Interrupt.Affinity;
676
 
677
                                KdPrint(("Irq    : Irql: %d, Vector: %d, Affinity: %d\n",
678
                                        pciada->Irql, pciada->Vector, pciada->Affinity));
679
                                break;
680
                        case CmResourceTypeDma:
681
                                KdPrint(("Dma    : \n"));
682
                                break;
683
                        case CmResourceTypePort:
684
 
685
                                KdPrint(("Port   : 0x%p\n", pPartialDescriptor->u.Port.Start));
686
                                break;
687
                        case CmResourceTypeMemory:
688
                                // special handling of PLXBUG here because of WIN2000
689
                                // WIN2000 doesn't recognize late address changes
690
                                if (!bug)
691
                                {
692
                                        if (i == 0)
693
                                        {
694
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
695
 
696
                                                if (pciada->pvPhysLcr.LowPart & 0x80)
697
                                                        bug = 1;
698
                                        }
699
                                }
700
                                else
701
                                {
702
                                        if (i == 3)
703
                                                pciada->pvPhysLcr = pPartialDescriptor->u.Memory.Start;
704
                                }
705
 
706
                                if (i == 2)
707
                                        pciada->pvPhysIfr = pPartialDescriptor->u.Memory.Start;
708
 
709
                                KdPrint(("Memory : 0x%p\n", (PUCHAR)pPartialDescriptor->u.Memory.Start.LowPart));
710
                                break;
711
                }
712
        }
713
 
714
        if (pciada->Irql == 0)
715
                return STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
716
 
717
        KdPrint(("PCICC32ExtractResources() OK.\n"));
718
 
719
        return STATUS_SUCCESS;
720
}
721
 
722
NTSTATUS PCICC32ReserveResources(PDEVICE_OBJECT device_Obj)
723
{
724
        PCM_RESOURCE_LIST pList = NULL;
725
        NTSTATUS result = STATUS_SUCCESS;
726
        int i;
727
        DEVICE_EXT *pDevExt = (DEVICE_EXT*)(device_Obj->DeviceExtension);
728
        int nPCIADAs = pDevExt->nPCIADAs;
729
        PCIADA *pciada;
730
    UNICODE_STRING DriverClassName;
731
 
732
        KdPrint(("PCICC32ReserveResources()\n"));
733
 
734
        // prepare resource claiming
735
        RtlInitUnicodeString(&DriverClassName, L"PCICC32");
736
 
737
        // cycle through all busses and slots assigned to PCIADAs
738
        for (i = 0; i < nPCIADAs; i++)
739
    {
740
                pciada = &pDevExt->pciada[i];
741
 
742
                result = HalAssignSlotResources(NULL, &DriverClassName, device_Obj->DriverObject, device_Obj,
743
                        PCIBus, pciada->Bus, pciada->Slot.u.AsULONG, &pList);
744
 
745
                if (result != STATUS_SUCCESS)
746
                        break;
747
 
748
                result = PCICC32ExtractResources(pciada, pList);
749
 
750
                if (result != STATUS_SUCCESS)
751
                        break;
752
        }
753
 
754
        // its my part to free allocated resources
755
        ExFreePool(pList);
756
 
757
        KdPrint(("PCICC32ReserveResources(0x%08x)\n", result));
758
 
759
        return result;
760
};
761
 
762
//------------------------------------------------------------------------
763
//  free resources from PCIADAs 
764
//
765
NTSTATUS PCICC32FreeResources(PDEVICE_OBJECT device_Obj)
766
{
767
        CM_RESOURCE_LIST ResList;
768
        BOOLEAN          bConflict;
769
    UNICODE_STRING   DriverClassName;
770
 
771
    KdPrint(("PCICC32FreeResources()\n"));
772
 
773
        RtlInitUnicodeString(&DriverClassName, L"PCICC32");
774
 
775
        ResList.Count = 0;
776
 
777
        IoReportResourceUsage(&DriverClassName, device_Obj->DriverObject,
778
                                         &ResList, sizeof(ResList), device_Obj,
779
                                                                         NULL, 0, FALSE, &bConflict);
780
        return STATUS_SUCCESS;
781
};
782
 
783
 
784
//------------------------------------------------------------------------
785
//  translate memory resources to neutral for PCIADAs 
786
//
787
NTSTATUS PCICC32TranslateBusAddresses(PDEVICE_OBJECT device_Obj)
788
{
789
        int              i;
790
        NTSTATUS         result = STATUS_SUCCESS;
791
        int nPCIADAs = ((DEVICE_EXT*)(device_Obj->DeviceExtension))->nPCIADAs;
792
        ULONG            memType0, memType2;
793
        PCIADA           *pciada;
794
 
795
    KdPrint(("TranslateBusAddresseses()\n"));
796
        for (i = 0; i < nPCIADAs; i++)
797
        {
798
      pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
799
 
800
          memType0 = memType2 = 0;
801
 
802
          if (!(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysLcr, &memType0,
803
                                                               &pciada->pvPhysLcr)) ||
804
              !(HalTranslateBusAddress(PCIBus, pciada->Bus, pciada->pvPhysIfr, &memType2,
805
                                                               &pciada->pvPhysIfr)))
806
          {
807
                  result = STATUS_UNSUCCESSFUL;
808
                  break;
809
          }
810
 
811
          if ((memType0) || (memType2))
812
          {
813
                  result = STATUS_UNSUCCESSFUL;
814
                  break;
815
          }
816
        }
817
        return result;
818
}
819
 
820
//------------------------------------------------------------------------
821
//  map address spaces to virtual addresses
822
//
823
NTSTATUS PCICC32MapIOspaces(PDEVICE_OBJECT device_Obj)
824
{
825
        int              i;
826
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
827
        int                              nPCIADAs = pDevExt->nPCIADAs;
828
        PCIADA           *pciada;
829
 
830
        KdPrint(("PCICC32MapIOspaces()\n"));
831
 
832
        for (i = 0; i < nPCIADAs; i++)
833
        {
834
       pciada = &pDevExt->pciada[i];
835
 
836
       if ((pciada->pvVirtLcr = MmMapIoSpace(pciada->pvPhysLcr, LCR_SPACE, FALSE)) == NULL)
837
          return STATUS_UNSUCCESSFUL;
838
       if ((pciada->pvVirtIfr = MmMapIoSpace(pciada->pvPhysIfr, IFR_SPACE, FALSE)) == NULL)
839
          return STATUS_UNSUCCESSFUL;
840
 
841
           KdPrint(("PCIADA %d: LCR 0x%08x IFR 0x%08x\n", i, pciada->pvVirtLcr, pciada->pvVirtIfr));
842
 
843
           pciada->pwIntCSR = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x4C);
844
           pciada->pwCntrl  = (PUSHORT)((PUCHAR)pciada->pvVirtLcr + 0x50);
845
        }
846
 
847
        return STATUS_SUCCESS;
848
}
849
 
850
 
851
//------------------------------------------------------------------------
852
//  initializes and registers a DPC routine for each pciada
853
//
854
NTSTATUS InitializeCustomDPCObjects(PDEVICE_OBJECT device_object)
855
{
856
        int              i;
857
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)(device_object->DeviceExtension);
858
        int              nPCIADAs = pDevExt->nPCIADAs;
859
        PCIADA           *pciada;
860
 
861
        KdPrint(("InitializeCustomDPCObject()\n"));
862
 
863
        for (i = 0; i < nPCIADAs; i++)
864
        {
865
                pciada = &pDevExt->pciada[i];
866
                KeInitializeDpc(&pciada->kDPCobj, fMyDefferedRoutine, (PVOID)device_object);
867
        }
868
 
869
        return STATUS_SUCCESS;
870
}
871
 
872
//------------------------------------------------------------------------
873
// init structures a.s.o.
874
//
875
VOID PCICC32SoftInit(PDEVICE_OBJECT device_Obj)
876
{
877
        int i;
878
        PCIADA *pciada;
879
 
880
        for (i = 0; i < PCICC32_MAX_PCIADA; i++)
881
        {
882
                pciada = &((DEVICE_EXT*)(device_Obj->DeviceExtension))->pciada[i];
883
 
884
                pciada->pvPhysLcr.QuadPart = pciada->pvPhysIfr.QuadPart = 0;
885
                pciada->pvVirtLcr = pciada->pvVirtIfr = NULL;
886
 
887
                pciada->bConnected     = FALSE;   // connection still not verified
888
                pciada->wModuleNumber  = 0xFFFF;
889
                pciada->wFPGAVersion   = 0xFFFF;
890
                pciada->wModuleType    = 1;       // always CC32
891
 
892
                pciada->InterruptObject = NULL;
893
                pciada->Irql                    = 0;
894
                pciada->Vector          = 0;
895
                pciada->Affinity                = 0;
896
 
897
                pciada->dwLinkCount     = 0;
898
 
899
                pciada->dwIrqStatus     = 0;
900
                pciada->pBlockingIrp    = (PIRP *)NULL;
901
 
902
                pciada->pIrqControlFile = (FILE_OBJ *)NULL;
903
        }
904
 
905
        // no CC32 associated to any PCIADA
906
        for (i = 0; i < PCICC32_MAX_CC32; i++)
907
          ((DEVICE_EXT*)(device_Obj->DeviceExtension))->cc32[i] = NULL;
908
}
909
 
910
//------------------------------------------------------------------------
911
// the ultimate starting point of a driver
912
NTSTATUS DriverEntry(PDRIVER_OBJECT driverObj, PUNICODE_STRING regPath)
913
{
914
        int            i;
915
        PDEVICE_OBJECT device_object;                   // pointer to the device object
916
        UNICODE_STRING device_name;
917
        UNICODE_STRING symbol_name;
918
        NTSTATUS result = STATUS_SUCCESS;
919
        PCIADA         *pciada;                                 // pointer to a PCIADA
920
        int            nPCIADAs;                                // count of PCIADAs
921
        DEVICE_EXT     *DeviceExtension = NULL;
922
 
923
    KdPrint(("DriverEntry() ----%d.%d-------------------------\n", (DRIVER_VERSION >> 16) & 0xFFFF, DRIVER_VERSION & 0xFFFF));
924
 
925
        driverObj->DriverUnload = PCICC32Unload;
926
        driverObj->MajorFunction[IRP_MJ_CREATE]            = PCICC32Open;
927
        driverObj->MajorFunction[IRP_MJ_CLOSE]             = PCICC32Close;
928
        driverObj->MajorFunction[IRP_MJ_READ]              = PCICC32Read;
929
    driverObj->MajorFunction[IRP_MJ_WRITE]             = PCICC32Write;
930
        driverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]    = PCICC32DeviceControl;
931
    driverObj->MajorFunction[IRP_MJ_SHUTDOWN]          = PCICC32Shutdown;
932
 
933
        RtlInitUnicodeString(&device_name, L"\\Device\\CC32");
934
 
935
        /* DeviceObject durch IO-Manager erzeugen */
936
        result = IoCreateDevice( driverObj,           // DriverObject received by the DriverEntry Call
937
                                                         sizeof(DEVICE_EXT),  // required Memory for the DeviceExtension
938
                                                         &device_name,        // Name of the device in the device-Directory
939
                                                         FILE_DEVICE_UNKNOWN, // Device-ID              
940
                                                         0,                   // Device-Characteristics normal 0
941
                                                         FALSE,               // TRUE : one Thread can open the driver
942
                                                         &device_object);     // DeviceObject returned from the IO-Manager
943
 
944
        // defines how the data are handled between user / kernel Adress-Space  
945
        device_object->Flags |= DO_DIRECT_IO;
946
 
947
        // anounce driver as symbolic device ---------------------------------
948
        if (result == STATUS_SUCCESS)
949
        {
950
                /* now the symbolic Link is created. If there is no S.L. a program cannot connect to the driver */
951
                RtlInitUnicodeString(&symbol_name, DOS_DEVICE_NAME);
952
                result = IoCreateSymbolicLink(&symbol_name,&device_name);
953
                if (result != STATUS_SUCCESS)
954
                {
955
                        IoDeleteDevice(device_object);
956
                        return result;
957
                }
958
        }
959
        else
960
                return result;
961
 
962
        DeviceExtension = (DEVICE_EXT*)device_object->DeviceExtension;
963
 
964
        DeviceExtension->actualIrp  = NULL;
965
        DeviceExtension->nInitState = 0;
966
 
967
        // init pciada structures ------------------------------------
968
        PCICC32SoftInit(device_object);
969
 
970
        // search for PCIADAs ----------------------------------------
971
        result   = SearchDevices(device_object);
972
        nPCIADAs = DeviceExtension->nPCIADAs;
973
 
974
        if ((result != STATUS_SUCCESS) || !(nPCIADAs))
975
        {
976
                PCICC32Unload(driverObj);    
977
                return STATUS_DEVICE_DOES_NOT_EXIST;
978
        }
979
 
980
        // request exclusive ownership of .. ---------------------------------
981
        if ((result = PCICC32ReserveResources(device_object)) != STATUS_SUCCESS)
982
        {
983
                PCICC32Unload(driverObj);    
984
                return result;
985
        }
986
        else
987
                DeviceExtension->nInitState++;
988
 
989
        // fix PLX9050 Bug -------------------------------------------
990
        if ((result = PLX9050BugFix(device_object)) != STATUS_SUCCESS)
991
        {
992
                PCICC32Unload(driverObj);    
993
                return result;
994
        }
995
 
996
        // translate BUS relative addresses ----------------------------------
997
        if ((result = PCICC32TranslateBusAddresses(device_object)) != STATUS_SUCCESS)
998
        {
999
                PCICC32Unload(driverObj);    
1000
                return STATUS_DEVICE_DOES_NOT_EXIST;
1001
        }
1002
        else
1003
                DeviceExtension->nInitState++;
1004
 
1005
        // translate Interrupt Resources used --------------------------------
1006
        if ((result = PCICC32TranslateInterrupt(device_object)) != STATUS_SUCCESS)
1007
        {
1008
                PCICC32Unload(driverObj);    
1009
                return STATUS_DEVICE_DOES_NOT_EXIST;
1010
        }
1011
        else
1012
                DeviceExtension->nInitState++;
1013
 
1014
        // map address spaces to virtual addresses ---------------------------
1015
        if ((result = PCICC32MapIOspaces(device_object)) != STATUS_SUCCESS)
1016
        {
1017
                PCICC32Unload(driverObj);    
1018
                return STATUS_DEVICE_DOES_NOT_EXIST;
1019
        }
1020
        else
1021
                DeviceExtension->nInitState++;
1022
 
1023
        // initialze my custom DPC objects -----------------------------------
1024
        if ((result = InitializeCustomDPCObjects(device_object)) != STATUS_SUCCESS)
1025
        {
1026
                PCICC32Unload(driverObj);    
1027
                return result;
1028
        }
1029
        else
1030
                DeviceExtension->nInitState++;
1031
 
1032
        // disable all interrupts --------------------------------------------
1033
        for (i = 0; i < nPCIADAs; i++)
1034
        {
1035
                pciada = &DeviceExtension->pciada[i];
1036
 
1037
                globalInterruptDisable(pciada);
1038
        }
1039
 
1040
        // connect interrupts to service routines ----------------------------
1041
        if ((result = PCICC32ConnectInterrupt(device_object)) != STATUS_SUCCESS)
1042
        {
1043
                PCICC32Unload(driverObj);    
1044
                return STATUS_DEVICE_DOES_NOT_EXIST;
1045
        }
1046
        else
1047
                DeviceExtension->nInitState++;
1048
 
1049
        // scan all connected CC32 for info and later use -------------------
1050
        if ((result = PCICC32ScanCC32(device_object)) != STATUS_SUCCESS)
1051
        {
1052
                PCICC32Unload(driverObj);    
1053
                return STATUS_DEVICE_DOES_NOT_EXIST;
1054
        }
1055
 
1056
        device_object->Flags &= ~DO_DEVICE_INITIALIZING;
1057
 
1058
    KdPrint(("DriverEntry() OK.\n"));
1059
 
1060
        return result;
1061
}
1062