Subversion Repositories f9daq

Rev

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

Rev Author Line No. Line
23 f9daq 1
//-------------------------------------------------------------------------
2
// WINNT driver for PCICC32 interface from ARW Elektronik, Germany --------
3
// all around irq handling
4
//
5
// (c) 1999-2002 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
// what                                            who          when
16
// started                                         AR           01.08.1999
17
// first release 1.0                                                       AR                   17.10.1999
18
// IoConnectInterrupt, share vector now true       AR           04.03.2000
19
// globalInterruptEnabledStatus() added            AR           24.02.2001
20
// added IRQ handling                              AR           24.02.2001
21
// added WITH_IRQS switch to switsch off irqs      AR           04.10.2001
22
// changed making procedure (only VCC > 6.0)       AR           30.05.2002
23
//
24
 
25
//-------------------------------------------------------------------------
26
// INCLUDES
27
//
28
#define WITH_IRQS     // comment out for interrupt handling excludes
29
// ACHTUNG TEST
30
 
31
//-------------------------------------------------------------------------
32
// INCLUDES
33
//
34
#include <ntddk.h>
35
#include <pcicc32_drv.h>
36
#include <pcicc32_i.h>
37
#include <pcicc32.h>
38
#include <pcicc32_local.h>
39
 
40
//------------------------------------------------------------------------
41
// DEFINES
42
//
43
#ifndef DWORD
44
#define DWORD ULONG
45
#endif
46
 
47
#ifndef WORD
48
#define WORD USHORT
49
#endif
50
 
51
//------------------------------------------------------------------------
52
// GLOBALS
53
//
54
 
55
//------------------------------------------------------------------------
56
// FUNCTIONS
57
//
58
 
59
//------------------------------------------------------------------------
60
// enable and disable of interrupts
61
//
62
void globalInterruptEnable(PCIADA *pciada)
63
{
64
#ifdef WITH_IRQS
65
   WRITE_REGISTER_USHORT(pciada->pwIntCSR, ENABLE_PCIADA_IRQS);
66
#endif
67
}
68
 
69
void globalInterruptDisable(PCIADA *pciada)
70
{
71
   WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
72
}
73
 
74
unsigned short globalInterruptEnabledStatus(PCIADA *pciada)
75
{
76
        unsigned short wStatus;
77
 
78
        wStatus = READ_REGISTER_USHORT(pciada->pwIntCSR);
79
 
80
        if ((wStatus & ENABLE_PCIADA_IRQS) == ENABLE_PCIADA_IRQS)
81
                return 1;
82
 
83
        return 0;
84
}
85
 
86
//------------------------------------------------------------------------
87
// determine which interrupt and evaluates status if appropriate
88
//
89
static int evaluateIrqStatus(PCIADA *pciada, ULONG *dwIrqStatus)
90
{
91
        volatile USHORT  wCntrl;
92
        int     result = 0;
93
 
94
        wCntrl = READ_REGISTER_USHORT(pciada->pwCntrl);
95
    if (wCntrl & 0x100)   // pciada switched on ?
96
        {
97
                volatile USHORT wIntCSR = READ_REGISTER_USHORT(pciada->pwIntCSR);
98
 
99
                if (wIntCSR & 0x0040) // are the interrupts enabled?
100
                {
101
                        if (wIntCSR & 0x20)
102
                        {
103
                                // it's the pci interrupt # 2
104
                                globalInterruptDisable(pciada); // disable following interrupts
105
 
106
                                // get current Cntrl - and clear interrupt
107
                                WRITE_REGISTER_USHORT(pciada->pwCntrl, (USHORT)(wCntrl & ~0x0100));     // disable
108
                                WRITE_REGISTER_USHORT(pciada->pwCntrl,  wCntrl);            // enable again
109
 
110
                                *dwIrqStatus = CONNECTION_TIMEOUT;
111
 
112
                                result = 1;
113
                        }
114
 
115
                        if (wIntCSR & 0x04)
116
                        {
117
                                globalInterruptDisable(pciada); // disable following interrupts
118
 
119
                                *dwIrqStatus =  READ_REGISTER_ULONG(_DWORD_NAF(pciada->pvVirtIfr, 28, 2, 0));
120
 
121
                                // clear pending interrupt - LAM-FF
122
                                WRITE_REGISTER_USHORT(_WORD_NAF(pciada->pvVirtIfr, 28, 0, 16), 0);
123
 
124
                                result = 1;
125
                        }
126
                }
127
        }
128
 
129
        return result;
130
}
131
 
132
//------------------------------------------------------------------------
133
// main interrupt handler function
134
//
135
static BOOLEAN irq_service(PKINTERRUPT Interrupt, PVOID ServiceContext)
136
{
137
        PCIADA *pciada = (PCIADA *)ServiceContext;
138
 
139
#ifndef WITH_IRQS
140
        return FALSE;
141
#endif
142
 
143
        if (!evaluateIrqStatus(pciada, &pciada->dwIrqStatus))
144
        {
145
                // KdPrint(("Not my irq.\n"));
146
                return FALSE;
147
        }
148
 
149
        // fire custom deffered procedure call
150
        KeInsertQueueDpc(&pciada->kDPCobj, (PVOID)pciada, (PVOID)&pciada->dwIrqStatus);
151
 
152
        KdPrint(("irq_service(0x%08x)\n", pciada->dwIrqStatus));
153
        return TRUE;
154
}
155
 
156
//------------------------------------------------------------------------
157
//  translate interrupt resources for PCIADAs to hardware independent ones
158
//
159
NTSTATUS PCICC32TranslateInterrupt(PDEVICE_OBJECT device_Obj)
160
{
161
        int              i;
162
        NTSTATUS         result = STATUS_SUCCESS;
163
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
164
        int                              nPCIADAs = pDevExt->nPCIADAs;
165
        PCIADA           *pciada;
166
 
167
    KdPrint(("PCICC32TranslateInterrupt()\n"));
168
 
169
        for (i = 0; i < nPCIADAs; i++)
170
        {
171
                pciada = &pDevExt->pciada[i];
172
 
173
                KdPrint(("In  - Bus:%d, IrqLine:%d\n", pciada->Bus, pciada->Irql));
174
 
175
                if (pciada->Irql)
176
                {
177
                        pciada->Vector = HalGetInterruptVector(PCIBus, pciada->Bus,
178
                                pciada->Irql, pciada->Vector,
179
                                                &pciada->Irql, &pciada->Affinity);
180
 
181
                        KdPrint(("Out - Irql:%d, Vector: %d, Affinity:%d\n", pciada->Irql, pciada->Vector, pciada->Affinity));
182
 
183
                }
184
                else
185
                        result = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
186
        }
187
 
188
        return result;
189
}
190
 
191
//------------------------------------------------------------------------
192
//  connect service routines to all PCIADA interrupts
193
//
194
NTSTATUS PCICC32ConnectInterrupt(PDEVICE_OBJECT device_Obj)
195
{
196
#ifdef WITH_IRQS
197
        int              i;
198
        NTSTATUS         result = STATUS_SUCCESS;
199
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
200
        int                              nPCIADAs = pDevExt->nPCIADAs;
201
        PCIADA           *pciada;
202
 
203
    KdPrint(("PCICC32ConnectInterrupt()\n"));
204
 
205
        // connect the interrupts to service routines
206
        for (i = 0; i < nPCIADAs; i++)
207
        {
208
                pciada = &pDevExt->pciada[i];
209
 
210
                pciada->InterruptObject = NULL;
211
 
212
                if (pciada->Vector)
213
                result = IoConnectInterrupt(&pciada->InterruptObject,
214
                        irq_service,
215
                                (PVOID)pciada,
216
                                        NULL,
217
                                                pciada->Vector,
218
                                                        pciada->Irql,
219
                                                                pciada->Irql,
220
                                                                        LevelSensitive,
221
                                                                                TRUE,
222
                                                                                        pciada->Affinity,
223
                                                                                                FALSE);
224
 
225
                KdPrint(("irq_service:%p, VirtVect:%d, Irql:%d, hIrql:%d, Aff:0x%08x, Status:0x%08x\n",
226
                                irq_service, pciada->Vector, pciada->Irql,
227
                                        pciada->Irql, pciada->Affinity, result));
228
 
229
                if (result != STATUS_SUCCESS)
230
                        break;
231
        }
232
 
233
        if (result == STATUS_SUCCESS)
234
        {
235
                KdPrint(("PCICC32ConnectInterrupt() OK.\n"));
236
        }
237
 
238
        return result;
239
#else
240
        return STATUS_SUCCESS;
241
#endif
242
}
243
 
244
//------------------------------------------------------------------------
245
//  dis-connect service routines to all PCIADA interrupts
246
//
247
NTSTATUS PCICC32DisConnectInterrupt(PDEVICE_OBJECT device_Obj)
248
{
249
#ifdef WITH_IRQS
250
        int              i;
251
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)device_Obj->DeviceExtension;
252
        int                              nPCIADAs = pDevExt->nPCIADAs;
253
        PCIADA           *pciada;
254
 
255
    KdPrint(("DisConnectInterrupt()\n"));
256
 
257
        // dis connect the interrupts to service routines
258
        for (i = 0; i < nPCIADAs; i++)
259
        {
260
                pciada = &pDevExt->pciada[i];
261
 
262
                KdPrint(("IrqObj:0x%08x\n", pciada->InterruptObject));
263
 
264
                if (pciada->InterruptObject)
265
                {
266
                  IoDisconnectInterrupt(pciada->InterruptObject);
267
                  pciada->InterruptObject = 0;
268
                }
269
        }
270
#endif
271
 
272
        return STATUS_SUCCESS;
273
}
274
 
275