Subversion Repositories shark

Rev

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

Rev Author Line No. Line
2 pj 1
/*****************************************************************************
2
* Filename:    pci6025e.c                                                    *
3
* Author:      Ziglioli Marco                                                *
4
* Date:        15/03/2001                                                    *
5
* Description: Collection of routines to find on PCI bus and configure Natio-*
6
*              nal Instruments PCI6025E multifunction board. This board has  *
7
*              - One ADC 12 bit flash with 16 input lines (multiplexed)      *
8
*              - Two DACs 12 bit                                             *
9
*              - Eight Digital lines drived through NI DAQ-STC IC            *
10
*              - Twentyfour Digital lines drived through OKI MSM82C55A       *
11
*              - Two General purpose 24-bit counters/timers                  *
12
*              - Timing module for analog input (AITM)                       *
13
*              - Timing module for analog output (AOTM)                      *
14
*              - 10 Programmable Function pins (PFI)                         *
15
*              - RTSI bus for connection with other National Board           *
16
*              - Timing module which can provide frequency from 20MHz to     *
17
*                6,25 KHz                                                    *
18
*              - Two shared interrupt groups to manage up than 20 different  *
19
*                interrupt events                                            *
20
* For more information please refer to National Web site: www.ni.com         *
21
*----------------------------------------------------------------------------*
22
* Notes:       Based on National C Routines                                  *
23
*****************************************************************************/
24
 
25
/* This file is part of the S.Ha.R.K. Project - http://shark.sssup.it
26
 *
27
 * Copyright (C) 2001 Marco Ziglioli
28
 *
29
 * This program is free software; you can redistribute it and/or modify
30
 * it under the terms of the GNU General Public License as published by
31
 * the Free Software Foundation; either version 2 of the License, or
32
 * (at your option) any later version.
33
 *
34
 * This program is distributed in the hope that it will be useful,
35
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
 * GNU General Public License for more details.
38
 *
39
 * You should have received a copy of the GNU General Public License
40
 * along with this program; if not, write to the Free Software
41
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
42
 *
43
 */
44
 
45
#include <drivers/pci6025e/pci6025e.h>
46
 
645 giacomo 47
extern int pci20to26_find_class(unsigned int class_code, int index, BYTE *bus, BYTE *dev);
48
extern int pci20to26_read_config_byte(unsigned int bus, unsigned int dev, int where, BYTE *val);
49
extern int pci20to26_read_config_word(unsigned int bus, unsigned int dev, int where, WORD *val);
50
extern int pci20to26_read_config_dword(unsigned int bus, unsigned int dev, int where, DWORD *val);
51
extern int pci20to26_write_config_byte(unsigned int bus, unsigned int dev, int where, BYTE val);
52
extern int pci20to26_write_config_word(unsigned int bus, unsigned int dev, int where, WORD val);
53
extern int pci20to26_write_config_dword(unsigned int bus, unsigned int dev, int where, DWORD val);
54
 
2 pj 55
//Software copy of importan register
56
static WORD interrupt_control;
57
 
58
// PJ: Global data
59
struct pci6025e_deviceinfo NIDevice_info[10];
60
DWORD *IntLinestructptr;
61
DWORD *BAR0structptr;
62
DWORD *RevID;
63
DWORD STC_Base_Address, MITE_Base_Address;
64
 
65
//Software copy of STC general registers
66
WORD joint_reset, interrupt_a_enable, interrupt_a_ack,
67
     interrupt_b_enable, interrupt_b_ack, clock_and_fout;
68
 
69
/*****************************************************************************
70
*                    Usefull(???) Functions                                  *
71
*****************************************************************************/
72
 
73
/*****************************************************************************
74
*  Print value of each bit contained in value                                *
75
*****************************************************************************/
76
void bitfield(BYTE dim, DWORD value)
77
{
78
   int   i;
79
 
80
   for(i=(dim*8)-1; i>=0; i--)
81
      cprintf("%ld",(value>>i)%2);
82
   cprintf("\n");
83
}
84
 
85
/*****************************************************************************
86
* Print custom string (str) before printing the bitfield                     *
87
*****************************************************************************/
88
void  TEST_bitfield(BYTE dim, DWORD value, char *str)
89
{
90
   cprintf("%s", str);
91
   bitfield(dim, value);
92
}
93
 
94
/*****************************************************************************
95
*  Low Level Functions to write in windowed mode into DAQ STC                *
96
*****************************************************************************/
97
void DAQ_STC_Windowed_Mode_Write(WORD addr, WORD Value)
98
{
645 giacomo 99
   SYS_FLAGS f;
100
 
101
   f = kern_fsave();
2 pj 102
   *((WORD *)(STC_Base_Address + WIN_ADDR_REG)) = addr;
103
   *((WORD *)(STC_Base_Address + WIN_DATA_WR_REG)) = Value;
645 giacomo 104
   kern_frestore(f);
2 pj 105
}
106
 
107
WORD DAQ_STC_Windowed_Mode_Read(WORD addr)
108
{
109
   WORD value = 0;
645 giacomo 110
   SYS_FLAGS f;
2 pj 111
 
645 giacomo 112
   f = kern_fsave();
2 pj 113
   *((WORD *)(STC_Base_Address + WIN_ADDR_REG)) = addr;
114
   value = *((WORD *)(STC_Base_Address + WIN_DATA_RD_REG));
645 giacomo 115
   kern_frestore(f);
2 pj 116
   return (value);
117
}
118
 
119
/*****************************************************************************
120
*  Detect all NI Devices on PCI bus                                          *
121
*****************************************************************************/
122
BYTE find_NI_Device(void)
123
{
124
   WORD     devNumFunNum = 0;
125
   WORD     busNum, i = 0;
645 giacomo 126
   DWORD    value, temp = 0, Device_ID;
2 pj 127
   BYTE     hdr, Device_Count;
128
   int      present;
129
 
130
   Device_Count = 0;
131
   BAR0structptr     = &NIDevice_info[0].BAR0Value;
132
   IntLinestructptr  = &NIDevice_info[0].IntLineRegValue;
133
   RevID             = &NIDevice_info[0].RevisionID;
134
 
135
   for(busNum = 0; busNum <= 0; busNum++){
136
      for(devNumFunNum = 0; devNumFunNum <= 0xFF; devNumFunNum += 0x08){
137
         present = 0;
138
         if((devNumFunNum & 0x07) == 0){
645 giacomo 139
            present = pci20to26_read_config_byte((BYTE)busNum,
2 pj 140
                                   (BYTE)devNumFunNum, 0x0E, &hdr);
141
            if(hdr & 0x80)
142
               present = 1;
143
            if(present){
645 giacomo 144
               if(pci20to26_read_config_dword((BYTE)busNum, (BYTE)devNumFunNum,
2 pj 145
                                  0x00, &value) && (value != 0xffffffff)){
146
                  if((value & 0xffffL) == NI_CODE){
147
                     Device_ID = value;
148
                     Device_ID &= 0xFFFF0000;
149
                     Device_ID = Device_ID >> 16;
150
 
151
                     NIDevice_info[i].DEVID = (WORD)temp;
152
                     NIDevice_info[i].DevFunction = (BYTE)devNumFunNum;
153
                     NIDevice_info[i].BusNumber = (BYTE)busNum;
645 giacomo 154
                     pci20to26_read_config_dword((BYTE)busNum, (BYTE)devNumFunNum, 0x10, (DWORD *)BAR0structptr);
155
                     pci20to26_read_config_dword((BYTE)busNum, (BYTE)devNumFunNum, 0x3C, (DWORD *)IntLinestructptr);
156
                     pci20to26_read_config_dword((BYTE)busNum, (BYTE)devNumFunNum, 0x08, (DWORD *)RevID);
2 pj 157
                     NIDevice_info[i].InterruptLevel = (BYTE)NIDevice_info[i].IntLineRegValue;
158
                     i++;
159
                     BAR0structptr++;
160
                     IntLinestructptr++;
161
                     RevID++;
162
                     Device_Count++;
163
                  }
164
               }
165
            }
166
         }
167
      }
168
   }
169
   return Device_Count;
170
}
171
 
172
/*****************************************************************************
173
*  Remap Base address of STC and MITE registers presents on NI boards        *
174
*  Note: If there's over than one NI Board on bus only the first device is   *
175
*        remapped                                                            *
176
*****************************************************************************/
177
BYTE reMap(void)
178
{
179
   //DWORD       Mite_Data;
180
   //DWORD       Value;
181
 
182
   if(!find_NI_Device()){
183
      return 0;
184
   }
185
 
186
 /*
187
   // ***************************************************************
188
   // This is usefull to remap board in another memory zone
189
   // Enable this and choose memory zone setting BAR0 and BAR1 values
190
   // on PCI6025E.H
191
   // ***************************************************************
192
   // Set Up MITE
193
   Value = BAR0;
194
   pcibios_write_config_dword((BYTE)NIDevice_info[0].BusNumber,
195
         NIDevice_info[0].DevFunction, 0x10, Value);
196
   Mite_Data = 0xAEAE;
197
   lmempoked(BAR0 + 0x0340, Mite_Data);
198
 
199
   // Set Up Board
200
   Value = BAR1;
201
   pcibios_write_config_dword((BYTE)NIDevice_info[0].BusNumber,
202
         NIDevice_info[0].DevFunction, 0x14, Value);
203
   Mite_Data = (BAR1 & 0xFFFFFF00) | 0x80;
204
   lmempoked(BAR0 + 0xC0, Mite_Data);
205
 */
206
 
207
 
208
   //Setting up Base Address
645 giacomo 209
   pci20to26_read_config_dword((BYTE)NIDevice_info[0].BusNumber,
2 pj 210
         (BYTE)NIDevice_info[0].DevFunction, 0x14, &STC_Base_Address);
211
   STC_Base_Address = (STC_Base_Address & 0xFFFFFF00) | 0x80;
645 giacomo 212
   pci20to26_read_config_dword((BYTE)NIDevice_info[0].BusNumber,
2 pj 213
         (BYTE)NIDevice_info[0].DevFunction, 0x10, &MITE_Base_Address);
214
   //MITE_Base_Address &= 0xFFFFFF00;
215
 
216
   *((DWORD *)MITE_Base_Address) = 0xAEAE;
217
   *((DWORD *)(MITE_Base_Address + 0xC0)) = STC_Base_Address;
218
 
219
   return 1;
220
}
221
 
222
/*****************************************************************************
223
*  Sets up the internal timebase clock and enable Frequency Out (FOUT).      *
224
*  Signal is available on pin 50                                             *
225
*----------------------------------------------------------------------------*
226
*  tbs      ->    if 0 then 20 Mhz freq; if 1 then 200 Khz freq              *
227
*  divBy2   ->    if 1 divides output frequency by two else if 0 doesn't     *
228
*                 divide it                                                  *
229
*  divider  ->    if 0 divides frequency by 16                               *
230
*                 if between 1 and 15 divides frequency by specified value   *
231
*****************************************************************************/
232
BYTE setIntClock(BYTE tbs, BYTE divBy2, BYTE divider)
233
{
234
   clr(clock_and_fout, 15);
235
   DAQ_STC_Windowed_Mode_Write(CLOCK_AND_FOUT, clock_and_fout);
236
 
237
   switch(tbs){
238
      case 0:
239
         clr(clock_and_fout, 14);   //IN_TIMEBASE
240
         break;
241
      case 1:
242
         set(clock_and_fout, 11);   //Enable IN_TIMEBASE2
243
         set(clock_and_fout, 14);   //Select IN_TIMEBASE2
244
         break;
245
      default:
246
         return 0;
247
         break;
248
   }
249
 
250
   switch(divBy2){
251
      case 0: clr(clock_and_fout, 12); break;   //Not divided by two
252
      case 1: set(clock_and_fout, 12); break;   //Divided by two
253
      default: return 0; break;
254
   }
255
 
256
   //if((divider < 0) || (divider > 15))
257
   if(divider > 15)  // PJ: byte has only positive values!!!
258
      return 0;      //Addictional frequency division wrong
259
 
260
   if(divider & 0x01)
261
      set(clock_and_fout, 0);
262
   else
263
      clr(clock_and_fout, 0);
264
 
265
   if(divider & 0x02)
266
      set(clock_and_fout, 1);
267
   else
268
      clr(clock_and_fout, 1);
269
 
270
   if(divider & 0x04)
271
      set(clock_and_fout, 2);
272
   else
273
      clr(clock_and_fout, 2);
274
 
275
   if(divider & 0x08)
276
      set(clock_and_fout, 3);
277
   else
278
      clr(clock_and_fout, 3);
279
 
280
   //Write in register
281
   DAQ_STC_Windowed_Mode_Write(CLOCK_AND_FOUT, clock_and_fout);
282
 
283
   //Enable internal clock
284
   set(clock_and_fout, 15);
285
   DAQ_STC_Windowed_Mode_Write(CLOCK_AND_FOUT, clock_and_fout);
286
 
287
   return 1;
288
}
289
 
290
/*****************************************************************************
291
*                 void PFIprogramming(WORD pfi)                              *
292
*----------------------------------------------------------------------------*
293
* Use this function to program the direction of the ten available PFI lines  *
294
* Parameter: pfi     bit 0 through 9: 0 releted PFI line configured as input *
295
*                                     1 releted PFI line configured as output*
296
*                    10..15   NOT USED                                       *
297
*****************************************************************************/
298
void PFIprogramming(WORD pfi)
299
{
300
   DAQ_STC_Windowed_Mode_Write(IO_BIDIRECTION_PIN, (pfi & 0x03FF));
301
}
302
 
303
/*****************************************************************************
304
*                 Interrupt manage module                                    *
305
*****************************************************************************/
306
/*****************************************************************************
307
*                 void INT_personalize(BYTE personal)                        *
308
*----------------------------------------------------------------------------*
309
* Use this function to select the logic level will indicate an interrupt     *
310
* condition on IRQ_OUT pins and to enable or disable the possibility of      *
311
* duplicate selected interrupt to IRQ_OUT<0..1> pins                         *
312
* Parameter:   personal:   bit 0: enable(1) or disable(0) signal duplication *
313
*                          bit 1: polarity: (0)active high (1)active low     *
314
*                          bit 2..7 NOT USED                                 *
315
*****************************************************************************/
316
void INT_personalize(BYTE personal)
317
{
318
   if( (personal & 0x02) )       set(interrupt_control, 0);
319
   else                          clr(interrupt_control, 0);
320
 
321
   if( (personal & 0x01) )       set(interrupt_control, 1);
322
   else                          clr(interrupt_control, 1);
323
 
324
   DAQ_STC_Windowed_Mode_Write(INTERRUPT_CONTROL, interrupt_control);
325
}
326
 
327
/*****************************************************************************
328
*                 void INT_setup(BYTE ga, BYTE gb)                           *
329
*----------------------------------------------------------------------------*
330
* Use this function to enable interrupt groups and to indicate which pin     *
331
* indicate interrupt condition.                                              *
332
* Parameter: ga: group A manages AITM, IRQ_IN0, Counter0                     *
333
*            gb: group B manages AOTM, IRQ_IN1, Counter1                     *
334
* Both parameters have first 3 bits (0..2) to indicate IRQ_OUT pin that will *
335
* indicate interrupt condition and the fourth bit (3) to enable the          *
336
* interrupts group.                                                          *
337
* Upper 4 bits of each BYTE are NOT USED                                     *
338
*****************************************************************************/
339
void INT_setup(BYTE ga, BYTE gb)
340
{
341
   if( (ga & 0x08) )
342
      interrupt_control = (interrupt_control & 0xF0FF) |
343
                          ((ga & 0x0F) << 8);
344
   else
345
      clr(interrupt_control, 11);
346
 
347
   if( (gb & 0x08) )
348
      interrupt_control = (interrupt_control & 0x0FFF) |
349
                          ((gb & 0x0F) << 12);
350
   else
351
      clr(interrupt_control, 15);
352
 
353
   DAQ_STC_Windowed_Mode_Write(INTERRUPT_CONTROL, interrupt_control);
354
}
355
/*End of file: pci6025e.c*/