Subversion Repositories f9daq

Rev

Rev 11 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 11 Rev 362
1
//****************************************************************************
1
//****************************************************************************
2
// Copyright (C) 2000-2004  ARW Elektronik Germany
2
// Copyright (C) 2000-2004  ARW Elektronik Germany
3
//
3
//
4
//
4
//
5
// This program is free software; you can redistribute it and/or modify
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 2 of the License, or
7
// the Free Software Foundation; either version 2 of the License, or
8
// (at your option) any later version.
8
// (at your option) any later version.
9
//
9
//
10
// This program is distributed in the hope that it will be useful,
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
13
// GNU General Public License for more details.
14
//
14
//
15
// You should have received a copy of the GNU General Public License
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
//
18
//
19
// This product is not authorized for use as critical component in 
19
// This product is not authorized for use as critical component in 
20
// life support systems without the express written approval of 
20
// life support systems without the express written approval of 
21
// ARW Elektronik Germany.
21
// ARW Elektronik Germany.
22
//  
22
//  
23
// Please announce changes and hints to ARW Elektronik
23
// Please announce changes and hints to ARW Elektronik
24
//
24
//
25
// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
25
// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
26
//
26
//
27
//****************************************************************************
27
//****************************************************************************
28
 
28
 
29
//****************************************************************************
29
//****************************************************************************
30
//
30
//
31
// fops.c -- the file operations module for the PCIVME PCI to VME Interface
31
// fops.c -- the file operations module for the PCIVME PCI to VME Interface
32
//
32
//
33
// $Log: fops.c,v $
33
// $Log: fops.c,v $
34
// Revision 1.11  2005/03/01 10:56:12  klaus
34
// Revision 1.11  2005/03/01 10:56:12  klaus
35
// removed warnings with gcc 3.3.3
35
// removed warnings with gcc 3.3.3
36
//
36
//
37
// Revision 1.10  2004/08/13 19:23:26  klaus
37
// Revision 1.10  2004/08/13 19:23:26  klaus
38
// conversion to kernel-version 2.6, released version 3.0
38
// conversion to kernel-version 2.6, released version 3.0
39
//
39
//
40
// Revision 1.9  2003/06/27 17:25:52  klaus
40
// Revision 1.9  2003/06/27 17:25:52  klaus
41
// incomplete try to get mmap() with nopage() running for automatic page switch
41
// incomplete try to get mmap() with nopage() running for automatic page switch
42
//
42
//
43
// Revision 1.8  2002/10/20 18:06:51  klaus
43
// Revision 1.8  2002/10/20 18:06:51  klaus
44
// changed error handling
44
// changed error handling
45
//
45
//
46
// Revision 1.7  2002/10/18 21:56:28  klaus
46
// Revision 1.7  2002/10/18 21:56:28  klaus
47
// completed functional features, untested
47
// completed functional features, untested
48
//
48
//
49
// Revision 1.6  2002/10/18 21:56:28  klaus
49
// Revision 1.6  2002/10/18 21:56:28  klaus
50
// completed functional features, untested
50
// completed functional features, untested
51
//
51
//
52
// Revision 1.5  2002/10/17 19:05:03  klaus
52
// Revision 1.5  2002/10/17 19:05:03  klaus
53
// VME access is working through test to lib to driver
53
// VME access is working through test to lib to driver
54
//
54
//
55
//****************************************************************************
55
//****************************************************************************
56
 
56
 
57
/*--- INCLUDES -----------------------------------------------------------------------------------*/
57
/*--- INCLUDES -----------------------------------------------------------------------------------*/
58
#include "common.h"  /* must be the first include */
58
#include "common.h"  /* must be the first include */
59
 
59
 
60
#include <linux/kernel.h> /* printk() */
60
#include <linux/kernel.h> /* printk() */
61
#include <linux/module.h> /* only here ?cause of MAJOR ... */
61
#include <linux/module.h> /* only here ?cause of MAJOR ... */
62
#include <linux/pci.h>
62
#include <linux/pci.h>
63
#include <linux/list.h>
63
#include <linux/list.h>
64
#include <asm/errno.h>
64
#include <asm/errno.h>
65
#include <asm/types.h>
65
#include <asm/types.h>
66
#include <asm/uaccess.h>
66
#include <asm/uaccess.h>
67
 
67
 
68
#include <linux/sched.h>
68
#include <linux/sched.h>
69
#include <linux/fs.h>
69
#include <linux/fs.h>
70
#if HAVE_UNLOCKED_IOCTL
-
 
71
    #include <linux/mutex.h>
70
#include <linux/mutex.h>
72
#else
-
 
73
    #include <linux/smp_lock.h>
-
 
74
#endif
-
 
75
 
71
 
76
 
72
 
77
#include "fops.h"
73
#include "fops.h"
78
#include "plx9050.h"
74
#include "plx9050.h"
79
#include "pcivme.h"      /* the common ioctl commands and structures between driver and application */
75
#include "pcivme.h"      /* the common ioctl commands and structures between driver and application */
80
#include "main.h"
76
#include "main.h"
81
#include "askpci.h"
77
#include "askpci.h"
82
#include "pciif.h"
78
#include "pciif.h"
83
#include "vic.h"
79
#include "vic.h"
84
#include "vme.h"
80
#include "vme.h"
85
 
81
 
86
/*--- DEFINES ------------------------------------------------------------------------------------*/
82
/*--- DEFINES ------------------------------------------------------------------------------------*/
87
 
83
 
88
#ifndef MINOR
84
#ifndef MINOR
89
#define MINOR(x) minor(x)            // since 2.5.?
85
#define MINOR(x) minor(x)            // since 2.5.?
90
#endif
86
#endif
91
 
87
 
92
static PCIVME_INIT_ELEMENT init_element[] =
88
static PCIVME_INIT_ELEMENT init_element[] =
93
{{LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS}, // disable interrupts
89
{{LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS}, // disable interrupts
94
    {LCR,  WORD_ACCESS, PLX9050_CNTRL,  RELEASE_VMEMM},       // enable interface
90
    {LCR,  WORD_ACCESS, PLX9050_CNTRL,  RELEASE_VMEMM},       // enable interface
95
 
91
 
96
    {VIC,  BYTE_ACCESS, VIICR, 0xf8+1},      // VIICR
92
    {VIC,  BYTE_ACCESS, VIICR, 0xf8+1},      // VIICR
97
 
93
 
98
    {VIC,  BYTE_ACCESS, VICR1, 0x78+1},      // VICR1
94
    {VIC,  BYTE_ACCESS, VICR1, 0x78+1},      // VICR1
99
    {VIC,  BYTE_ACCESS, VICR2, 0x78+2},
95
    {VIC,  BYTE_ACCESS, VICR2, 0x78+2},
100
    {VIC,  BYTE_ACCESS, VICR3, 0x78+3},
96
    {VIC,  BYTE_ACCESS, VICR3, 0x78+3},
101
    {VIC,  BYTE_ACCESS, VICR4, 0x78+4},
97
    {VIC,  BYTE_ACCESS, VICR4, 0x78+4},
102
    {VIC,  BYTE_ACCESS, VICR5, 0x78+5},
98
    {VIC,  BYTE_ACCESS, VICR5, 0x78+5},
103
    {VIC,  BYTE_ACCESS, VICR6, 0x78+6},
99
    {VIC,  BYTE_ACCESS, VICR6, 0x78+6},
104
    {VIC,  BYTE_ACCESS, VICR7, 0x78+7},      // VICR7
100
    {VIC,  BYTE_ACCESS, VICR7, 0x78+7},      // VICR7
105
 
101
 
106
    {VIC,  BYTE_ACCESS, DSICR, 0xf8+0},      // DSICR
102
    {VIC,  BYTE_ACCESS, DSICR, 0xf8+0},      // DSICR
107
 
103
 
108
    {VIC,  BYTE_ACCESS, LICR1, 0xf8+1},      // LICR1
104
    {VIC,  BYTE_ACCESS, LICR1, 0xf8+1},      // LICR1
109
    {VIC,  BYTE_ACCESS, LICR2, 0xf8+2},
105
    {VIC,  BYTE_ACCESS, LICR2, 0xf8+2},
110
    {VIC,  BYTE_ACCESS, LICR3, 0xf8+3},
106
    {VIC,  BYTE_ACCESS, LICR3, 0xf8+3},
111
    {VIC,  BYTE_ACCESS, LICR4, 0xf8+4},
107
    {VIC,  BYTE_ACCESS, LICR4, 0xf8+4},
112
    {VIC,  BYTE_ACCESS, LICR5, 0xf8+5},
108
    {VIC,  BYTE_ACCESS, LICR5, 0xf8+5},
113
    {VIC,  BYTE_ACCESS, LICR6, 0x38+6},
109
    {VIC,  BYTE_ACCESS, LICR6, 0x38+6},
114
    {VIC,  BYTE_ACCESS, LICR7, 0x38+7},      // LICR7
110
    {VIC,  BYTE_ACCESS, LICR7, 0x38+7},      // LICR7
115
 
111
 
116
    {VIC,  BYTE_ACCESS, ICGSICR, 0xf8+2},    // ICGS
112
    {VIC,  BYTE_ACCESS, ICGSICR, 0xf8+2},    // ICGS
117
    {VIC,  BYTE_ACCESS, ICMSICR, 0xf8+3},    // ICMS
113
    {VIC,  BYTE_ACCESS, ICMSICR, 0xf8+3},    // ICMS
118
 
114
 
119
    {VIC,  BYTE_ACCESS, EGICR, 0xf8+6},      // EGICR
115
    {VIC,  BYTE_ACCESS, EGICR, 0xf8+6},      // EGICR
120
 
116
 
121
    {VIC,  BYTE_ACCESS, ICGSVBR, 0x08},      // ICGS-IVBR (!)
117
    {VIC,  BYTE_ACCESS, ICGSVBR, 0x08},      // ICGS-IVBR (!)
122
    {VIC,  BYTE_ACCESS, ICMSVBR, 0x0c},      // ICMS-IVBR (!)
118
    {VIC,  BYTE_ACCESS, ICMSVBR, 0x0c},      // ICMS-IVBR (!)
123
 
119
 
124
    {VIC,  BYTE_ACCESS, LIVBR, 0x00},        // LIVBR (!)
120
    {VIC,  BYTE_ACCESS, LIVBR, 0x00},        // LIVBR (!)
125
 
121
 
126
    {VIC,  BYTE_ACCESS, EGIVBR, 0x10},       // EGIVBR (!)
122
    {VIC,  BYTE_ACCESS, EGIVBR, 0x10},       // EGIVBR (!)
127
 
123
 
128
    {VIC,  BYTE_ACCESS, ICSR, 0x00},         // ICSR
124
    {VIC,  BYTE_ACCESS, ICSR, 0x00},         // ICSR
129
 
125
 
130
    {VIC,  BYTE_ACCESS, ICR0, 0x00},         // ICR0
126
    {VIC,  BYTE_ACCESS, ICR0, 0x00},         // ICR0
131
    {VIC,  BYTE_ACCESS, ICR1, 0x00},
127
    {VIC,  BYTE_ACCESS, ICR1, 0x00},
132
    {VIC,  BYTE_ACCESS, ICR2, 0x00},
128
    {VIC,  BYTE_ACCESS, ICR2, 0x00},
133
    {VIC,  BYTE_ACCESS, ICR3, 0x00},
129
    {VIC,  BYTE_ACCESS, ICR3, 0x00},
134
    {VIC,  BYTE_ACCESS, ICR4, 0x00},         // ICR4
130
    {VIC,  BYTE_ACCESS, ICR4, 0x00},         // ICR4
135
 
131
 
136
    {VIC,  BYTE_ACCESS, VIRSR, 0xfe},        // VIRSR
132
    {VIC,  BYTE_ACCESS, VIRSR, 0xfe},        // VIRSR
137
 
133
 
138
    {VIC,  BYTE_ACCESS, VIVR1, 0x0f},        // VIVR1
134
    {VIC,  BYTE_ACCESS, VIVR1, 0x0f},        // VIVR1
139
    {VIC,  BYTE_ACCESS, VIVR2, 0x0f},
135
    {VIC,  BYTE_ACCESS, VIVR2, 0x0f},
140
    {VIC,  BYTE_ACCESS, VIVR3, 0x0f},
136
    {VIC,  BYTE_ACCESS, VIVR3, 0x0f},
141
    {VIC,  BYTE_ACCESS, VIVR4, 0x0f},
137
    {VIC,  BYTE_ACCESS, VIVR4, 0x0f},
142
    {VIC,  BYTE_ACCESS, VIVR5, 0x0f},
138
    {VIC,  BYTE_ACCESS, VIVR5, 0x0f},
143
    {VIC,  BYTE_ACCESS, VIVR6, 0x0f},
139
    {VIC,  BYTE_ACCESS, VIVR6, 0x0f},
144
    {VIC,  BYTE_ACCESS, VIVR7, 0x0f},        // VIVR7
140
    {VIC,  BYTE_ACCESS, VIVR7, 0x0f},        // VIVR7
145
 
141
 
146
    {VIC,  BYTE_ACCESS, TTR, 0x3c},          // TTR
142
    {VIC,  BYTE_ACCESS, TTR, 0x3c},          // TTR
147
 
143
 
148
    {VIC,  BYTE_ACCESS, ARCR, 0x40},         // ARCR
144
    {VIC,  BYTE_ACCESS, ARCR, 0x40},         // ARCR
149
    {VIC,  BYTE_ACCESS, AMSR, 0x29},         // AMSR
145
    {VIC,  BYTE_ACCESS, AMSR, 0x29},         // AMSR
150
    {VIC,  BYTE_ACCESS, RCR, 0x00},          // RCR
146
    {VIC,  BYTE_ACCESS, RCR, 0x00},          // RCR
151
 
147
 
152
    {IFR,  LONG_ACCESS, (u16)ADRHL, 0xF0F0F0F0},  // ADR-H, ADR-L
148
    {IFR,  LONG_ACCESS, (u16)ADRHL, 0xF0F0F0F0},  // ADR-H, ADR-L
153
    {IFR,  WORD_ACCESS, (u16)CSR  , 0x0000},      // Contr-Reg
149
    {IFR,  WORD_ACCESS, (u16)CSR  , 0x0000},      // Contr-Reg
154
 
150
 
155
    {VIC,  BYTE_ACCESS, ICR7, 0x80},         // ICR7
151
    {VIC,  BYTE_ACCESS, ICR7, 0x80},         // ICR7
156
 
152
 
157
    {LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS},  // disable interrupts
153
    {LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS},  // disable interrupts
158
 
154
 
159
    {STOP, WORD_ACCESS, 0,     0}};
155
    {STOP, WORD_ACCESS, 0,     0}};
160
 
156
 
161
static PCIVME_INIT_ELEMENT deinit_element_pre[] =
157
static PCIVME_INIT_ELEMENT deinit_element_pre[] =
162
{{VIC,  BYTE_ACCESS, ICR7, 0x00},         // ICR7 - sysfail
158
{{VIC,  BYTE_ACCESS, ICR7, 0x00},         // ICR7 - sysfail
163
    {LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS},  // disable interrupts
159
    {LCR,  WORD_ACCESS, PLX9050_INTCSR, DISABLE_PCIADA_IRQS},  // disable interrupts
164
    {STOP, WORD_ACCESS, 0,    0}};
160
    {STOP, WORD_ACCESS, 0,    0}};
165
 
161
 
166
static PCIVME_INIT_ELEMENT deinit_element_post[] =
162
static PCIVME_INIT_ELEMENT deinit_element_post[] =
167
{{LCR,  WORD_ACCESS, PLX9050_CNTRL, INHIBIT_VMEMM},     // disable interface
163
{{LCR,  WORD_ACCESS, PLX9050_CNTRL, INHIBIT_VMEMM},     // disable interface
168
    {STOP, WORD_ACCESS, 0,    0}};
164
    {STOP, WORD_ACCESS, 0,    0}};
169
 
165
 
170
 
166
 
171
/*--- EXTERNALS ----------------------------------------------------------------------------------*/
167
/*--- EXTERNALS ----------------------------------------------------------------------------------*/
172
 
168
 
173
/*--- TYPEDEFS -----------------------------------------------------------------------------------*/
169
/*--- TYPEDEFS -----------------------------------------------------------------------------------*/
174
 
170
 
175
/*--- FUNCTIONS ----------------------------------------------------------------------------------*/
171
/*--- FUNCTIONS ----------------------------------------------------------------------------------*/
176
static inline void switch_VMEMM_on(DEVICE_OBJ *pd)
172
static inline void switch_VMEMM_on(DEVICE_OBJ *pd)
177
{
173
{
178
    writew(RELEASE_VMEMM, (volatile void *) (pd->pLCR + PLX9050_CNTRL)); /* enable access */
174
    writew(RELEASE_VMEMM, (volatile void *) (pd->pLCR + PLX9050_CNTRL)); /* enable access */
179
}
175
}
180
 
176
 
181
static inline void switch_VMEMM_off(DEVICE_OBJ *pd)
177
static inline void switch_VMEMM_off(DEVICE_OBJ *pd)
182
{
178
{
183
    writew(INHIBIT_VMEMM, (volatile void *) (pd->pLCR + PLX9050_CNTRL)); /* enable access */
179
    writew(INHIBIT_VMEMM, (volatile void *) (pd->pLCR + PLX9050_CNTRL)); /* enable access */
184
}
180
}
185
 
181
 
186
static inline void setPageAddress(DEVICE_OBJ *pd, u32 newPageAddress)
182
static inline void setPageAddress(DEVICE_OBJ *pd, u32 newPageAddress)
187
{
183
{
188
    PRINTK(KERN_DEBUG "%s : setPageAddress(0x%08x)\n", DEVICE_NAME, newPageAddress);
184
    PRINTK(KERN_DEBUG "%s : setPageAddress(0x%08x)\n", DEVICE_NAME, newPageAddress);
189
 
185
 
190
    writel(newPageAddress, (volatile void *) pd->pAdrReg);
186
    writel(newPageAddress, (volatile void *) pd->pAdrReg);
191
    pd->dwCurrentPageAddress = newPageAddress;
187
    pd->dwCurrentPageAddress = newPageAddress;
192
}
188
}
193
 
189
 
194
static inline void setModifier(DEVICE_OBJ *pd, u8 newModifier)
190
static inline void setModifier(DEVICE_OBJ *pd, u8 newModifier)
195
{
191
{
196
    PRINTK(KERN_DEBUG "%s : setModifier(0x%02x)\n", DEVICE_NAME, newModifier);
192
    PRINTK(KERN_DEBUG "%s : setModifier(0x%02x)\n", DEVICE_NAME, newModifier);
197
 
193
 
198
    writeb(newModifier, (volatile void *) pd->pAdrMod);
194
    writeb(newModifier, (volatile void *) pd->pAdrMod);
199
    pd->bCurrentModifier = newModifier;
195
    pd->bCurrentModifier = newModifier;
200
}
196
}
201
 
197
 
202
/* read and write functions -----------------------------------------------------------------------*/
198
/* read and write functions -----------------------------------------------------------------------*/
203
static inline u8 *increment8(void **pvBuffer)
199
static inline u8 *increment8(void **pvBuffer)
204
{
200
{
205
  u8 *tmp = (u8*)*pvBuffer;
201
  u8 *tmp = (u8*)*pvBuffer;
206
 
202
 
207
  *pvBuffer += sizeof(u8);
203
  *pvBuffer += sizeof(u8);
208
 
204
 
209
  return tmp;
205
  return tmp;
210
}
206
}
211
 
207
 
212
static inline u16 *increment16(void **pvBuffer)
208
static inline u16 *increment16(void **pvBuffer)
213
{
209
{
214
  u16 *tmp = (u16*)*pvBuffer;
210
  u16 *tmp = (u16*)*pvBuffer;
215
 
211
 
216
  *pvBuffer += sizeof(u16);
212
  *pvBuffer += sizeof(u16);
217
 
213
 
218
  return tmp;
214
  return tmp;
219
}
215
}
220
 
216
 
221
static inline u32 *increment32(void **pvBuffer)
217
static inline u32 *increment32(void **pvBuffer)
222
{
218
{
223
  u32 *tmp = (u32*)*pvBuffer;
219
  u32 *tmp = (u32*)*pvBuffer;
224
 
220
 
225
  *pvBuffer += sizeof(u32);
221
  *pvBuffer += sizeof(u32);
226
 
222
 
227
  return tmp;
223
  return tmp;
228
}
224
}
229
 
225
 
230
static void readByte(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
226
static void readByte(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
231
{
227
{
232
    u8 tmp;
228
    u8 tmp;
233
 
229
 
234
    tmp = readb((const volatile void *) (pd->pVME + dwLocalAddressInPage));
230
    tmp = readb((const volatile void *) (pd->pVME + dwLocalAddressInPage));
235
    __put_user(tmp, increment8(pvBuffer));
231
    __put_user(tmp, increment8(pvBuffer));
236
}
232
}
237
 
233
 
238
static void writeByte(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
234
static void writeByte(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
239
{
235
{
240
    u8 tmp;
236
    u8 tmp;
241
 
237
 
242
    __get_user(tmp, increment8(pvBuffer));
238
    __get_user(tmp, increment8(pvBuffer));
243
    writeb(tmp, (volatile void *) (pd->pVME + dwLocalAddressInPage ));
239
    writeb(tmp, (volatile void *) (pd->pVME + dwLocalAddressInPage ));
244
}
240
}
245
 
241
 
246
static void readWord(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
242
static void readWord(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
247
{
243
{
248
    u16 tmp;
244
    u16 tmp;
249
 
245
 
250
    tmp = readw((const volatile void *) (pd->pVME + dwLocalAddressInPage));
246
    tmp = readw((const volatile void *) (pd->pVME + dwLocalAddressInPage));
251
    __put_user(tmp, increment16(pvBuffer));
247
    __put_user(tmp, increment16(pvBuffer));
252
}
248
}
253
 
249
 
254
static void writeWord(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
250
static void writeWord(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
255
{
251
{
256
    u16 tmp;
252
    u16 tmp;
257
 
253
 
258
    __get_user(tmp, increment16(pvBuffer));
254
    __get_user(tmp, increment16(pvBuffer));
259
    writew(tmp, (volatile void *) ( pd->pVME + dwLocalAddressInPage ));
255
    writew(tmp, (volatile void *) ( pd->pVME + dwLocalAddressInPage ));
260
}
256
}
261
 
257
 
262
static void readLong(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
258
static void readLong(DEVICE_OBJ *pd, void **pvBuffer, u32 dwLocalAddressInPage)
263
{
259
{
264
    u32 tmp;
260
    u32 tmp;
265
 
261
 
266
    tmp = readl((const volatile void *) (pd->pVME + dwLocalAddressInPage));
262
    tmp = readl((const volatile void *) (pd->pVME + dwLocalAddressInPage));
267
    __put_user(tmp, increment32(pvBuffer));
263
    __put_user(tmp, increment32(pvBuffer));
268
}
264
}
269
 
265
 
270
static void writeLong(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
266
static void writeLong(DEVICE_OBJ *pd, u32 dwLocalAddressInPage, void **pvBuffer)
271
{
267
{
272
    u32 tmp;
268
    u32 tmp;
273
 
269
 
274
    __get_user(tmp, increment32(pvBuffer));
270
    __get_user(tmp, increment32(pvBuffer));
275
    writel(tmp, (volatile void *) (pd->pVME + dwLocalAddressInPage));
271
    writel(tmp, (volatile void *) (pd->pVME + dwLocalAddressInPage));
276
}
272
}
277
 
273
 
278
/* test alignment functions -----------------------------------------------------------------------*/
274
/* test alignment functions -----------------------------------------------------------------------*/
279
static int MisalignmentForByteAccess(loff_t offset)
275
static int MisalignmentForByteAccess(loff_t offset)
280
{
276
{
281
    return 0;
277
    return 0;
282
}
278
}
283
 
279
 
284
static int MisalignmentForWordAccess(loff_t offset)
280
static int MisalignmentForWordAccess(loff_t offset)
285
{
281
{
286
    return(offset & 1);
282
    return(offset & 1);
287
}
283
}
288
 
284
 
289
static int MisalignmentForLongAccess(loff_t offset)
285
static int MisalignmentForLongAccess(loff_t offset)
290
{
286
{
291
    return(offset & 3);
287
    return(offset & 3);
292
}
288
}
293
 
289
 
294
// helper functions --------------------------------------------------------------------------------
290
// helper functions --------------------------------------------------------------------------------
295
int check_command(const PCIVME_INIT_ELEMENT *psInitElement)
291
int check_command(const PCIVME_INIT_ELEMENT *psInitElement)
296
{
292
{
297
    u16 range;
293
    u16 range;
298
    u16 access_size;
294
    u16 access_size;
299
 
295
 
300
    // PRINTK(KERN_DEBUG "%s : check_command()\n", DEVICE_NAME);
296
    // PRINTK(KERN_DEBUG "%s : check_command()\n", DEVICE_NAME);
301
 
297
 
302
    switch (psInitElement->bDestination)
298
    switch (psInitElement->bDestination)
303
    {
299
    {
304
        case LCR:
300
        case LCR:
305
            range = 0x54;    
301
            range = 0x54;    
306
            break;
302
            break;
307
        case IFR:
303
        case IFR:
308
            range = 0x0c;    
304
            range = 0x0c;    
309
            break;
305
            break;
310
        case VIC:
306
        case VIC:
311
            range = 0xe4;
307
            range = 0xe4;
312
            if ((psInitElement->wOffset & 3) != 3)
308
            if ((psInitElement->wOffset & 3) != 3)
313
                return -EINVAL;
309
                return -EINVAL;
314
            break;
310
            break;
315
        default:  
311
        default:  
316
            return -EINVAL;        
312
            return -EINVAL;        
317
            break;
313
            break;
318
    }
314
    }
319
 
315
 
320
    // check alignment and allowed address range
316
    // check alignment and allowed address range
321
    switch (psInitElement->bAccessType)
317
    switch (psInitElement->bAccessType)
322
    {
318
    {
323
        case LONG_ACCESS:
319
        case LONG_ACCESS:
324
            if (psInitElement->wOffset & 3)
320
            if (psInitElement->wOffset & 3)
325
                return -EINVAL;
321
                return -EINVAL;
326
            access_size = sizeof(u32);
322
            access_size = sizeof(u32);
327
            break;
323
            break;
328
        case WORD_ACCESS:
324
        case WORD_ACCESS:
329
            if (psInitElement->wOffset & 1)
325
            if (psInitElement->wOffset & 1)
330
                return -EINVAL;
326
                return -EINVAL;
331
            access_size = sizeof(u16);
327
            access_size = sizeof(u16);
332
            break;
328
            break;
333
        case BYTE_ACCESS:
329
        case BYTE_ACCESS:
334
            access_size = sizeof(u8);
330
            access_size = sizeof(u8);
335
            break;
331
            break;
336
        default         :
332
        default         :
337
            return -EINVAL;        
333
            return -EINVAL;        
338
            break;
334
            break;
339
    }
335
    }
340
 
336
 
341
    if ((psInitElement->wOffset + access_size) > range)
337
    if ((psInitElement->wOffset + access_size) > range)
342
        return -EINVAL;       // ignore it
338
        return -EINVAL;       // ignore it
343
 
339
 
344
    return 0;
340
    return 0;
345
}
341
}
346
 
342
 
347
static int CmdMachine(DEVICE_OBJ *pd, const PCIVME_INIT_ELEMENT *psInitElement)
343
static int CmdMachine(DEVICE_OBJ *pd, const PCIVME_INIT_ELEMENT *psInitElement)
348
{
344
{
349
    u32 adr;
345
    u32 adr;
350
    int err;
346
    int err;
351
 
347
 
352
    //PRINTK(KERN_DEBUG "%s : CmdMachine()\n", DEVICE_NAME);
348
    //PRINTK(KERN_DEBUG "%s : CmdMachine()\n", DEVICE_NAME);
353
 
349
 
354
    // loop through the init (or deinit) list
350
    // loop through the init (or deinit) list
355
    while (psInitElement->bDestination != STOP)
351
    while (psInitElement->bDestination != STOP)
356
    {
352
    {
357
        err = check_command(psInitElement);
353
        err = check_command(psInitElement);
358
        if (!err)
354
        if (!err)
359
        {
355
        {
360
            switch (psInitElement->bDestination)
356
            switch (psInitElement->bDestination)
361
            {
357
            {
362
                case LCR:
358
                case LCR:
363
                    adr = pd->pLCR;
359
                    adr = pd->pLCR;
364
                    break;
360
                    break;
365
                case VIC:
361
                case VIC:
366
                    adr = pd->pCtl + VICBASE;
362
                    adr = pd->pCtl + VICBASE;
367
                    break;
363
                    break;
368
                case IFR:
364
                case IFR:
369
                    adr = pd->pCtl + CSR;
365
                    adr = pd->pCtl + CSR;
370
                    break;  
366
                    break;  
371
                default:
367
                default:
372
                    return -EINVAL;
368
                    return -EINVAL;
373
            }
369
            }
374
 
370
 
375
            switch (psInitElement->bAccessType)
371
            switch (psInitElement->bAccessType)
376
            {
372
            {
377
                case LONG_ACCESS:
373
                case LONG_ACCESS:
378
                    writel(psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
374
                    writel(psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
379
                    break;
375
                    break;
380
                case WORD_ACCESS:
376
                case WORD_ACCESS:
381
                    writew((u16)psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
377
                    writew((u16)psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
382
                    break;
378
                    break;
383
                case BYTE_ACCESS:
379
                case BYTE_ACCESS:
384
                    writeb((u8)psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
380
                    writeb((u8)psInitElement->dwValue, (volatile void *) (adr + psInitElement->wOffset));
385
                    break;
381
                    break;
386
                default:
382
                default:
387
                    return -EINVAL;
383
                    return -EINVAL;
388
            }
384
            }
389
        }
385
        }
390
        else
386
        else
391
            return err;
387
            return err;
392
 
388
 
393
        psInitElement++;
389
        psInitElement++;
394
    }
390
    }
395
 
391
 
396
    return 0;
392
    return 0;
397
}
393
}
398
 
394
 
399
// all ioctls --------------------------------------------------------------------------------------
395
// all ioctls --------------------------------------------------------------------------------------
400
static int init_hardware(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_INIT_COMMAND *init)
396
static int init_hardware(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_INIT_COMMAND *init)
401
{
397
{
402
    int err;
398
    int err;
403
    PCIVME_INIT_ELEMENT *element = init->sVie;
399
    PCIVME_INIT_ELEMENT *element = init->sVie;
404
 
400
 
405
    PRINTK(KERN_INFO "%s : init_hardware()\n", DEVICE_NAME);
401
    PRINTK(KERN_INFO "%s : init_hardware()\n", DEVICE_NAME);
406
 
402
 
407
    err = CmdMachine(pd, element);
403
    err = CmdMachine(pd, element);
408
    if (err)
404
    if (err)
409
    {
405
    {
410
        PRINTK(KERN_DEBUG "%s : init failed with err = %d!\n", DEVICE_NAME, err);
406
        PRINTK(KERN_DEBUG "%s : init failed with err = %d!\n", DEVICE_NAME, err);
411
        return err;
407
        return err;
412
    }
408
    }
413
 
409
 
414
    // sync storage with hardware
410
    // sync storage with hardware
415
    pd->bCurrentModifier     = readb((const volatile void *) pd->pAdrMod) & 0x3f;
411
    pd->bCurrentModifier     = readb((const volatile void *) pd->pAdrMod) & 0x3f;
416
    pd->dwCurrentPageAddress = readl((const volatile void *) pd->pAdrReg) & HI_ADDRESS_MASK;
412
    pd->dwCurrentPageAddress = readl((const volatile void *) pd->pAdrReg) & HI_ADDRESS_MASK;
417
 
413
 
418
    return 0;
414
    return 0;
419
}
415
}
420
 
416
 
421
static int deinit_hardware(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_INIT_COMMAND *deinit)
417
static int deinit_hardware(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_INIT_COMMAND *deinit)
422
{
418
{
423
    int err;
419
    int err;
424
    PCIVME_INIT_ELEMENT *element = deinit->sVie;
420
    PCIVME_INIT_ELEMENT *element = deinit->sVie;
425
 
421
 
426
    PRINTK(KERN_DEBUG "%s : deinit_hardware()\n", DEVICE_NAME);
422
    PRINTK(KERN_DEBUG "%s : deinit_hardware()\n", DEVICE_NAME);
427
 
423
 
428
    err = CmdMachine(pd, deinit_element_pre);  
424
    err = CmdMachine(pd, deinit_element_pre);  
429
    if (err)
425
    if (err)
430
        goto fail;
426
        goto fail;
431
 
427
 
432
    err = CmdMachine(pd, element);
428
    err = CmdMachine(pd, element);
433
    if (err)
429
    if (err)
434
        goto fail;
430
        goto fail;
435
 
431
 
436
    err = CmdMachine(pd, deinit_element_post);
432
    err = CmdMachine(pd, deinit_element_post);
437
    if (err)
433
    if (err)
438
        goto fail;
434
        goto fail;
439
 
435
 
440
    return 0;
436
    return 0;
441
 
437
 
442
    fail:
438
    fail:
443
    return err;
439
    return err;
444
}
440
}
445
 
441
 
446
static int access_command(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_ACCESS_COMMAND *cmd)
442
static int access_command(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_ACCESS_COMMAND *cmd)
447
{
443
{
448
    PRINTK(KERN_DEBUG "%s : access_command()\n", DEVICE_NAME);
444
    PRINTK(KERN_DEBUG "%s : access_command()\n", DEVICE_NAME);
449
 
445
 
450
    pp->bModifier    = cmd->bModifier;
446
    pp->bModifier    = cmd->bModifier;
451
    pp->bAccessType  = cmd->bAccessType;
447
    pp->bAccessType  = cmd->bAccessType;
452
    pp->bIncrement   = cmd->bIncrement;
448
    pp->bIncrement   = cmd->bIncrement;
453
 
449
 
454
    switch (pp->bAccessType)
450
    switch (pp->bAccessType)
455
    {
451
    {
456
        case BYTE_ACCESS:
452
        case BYTE_ACCESS:
457
            pp->read  = readByte;
453
            pp->read  = readByte;
458
            pp->write = writeByte;
454
            pp->write = writeByte;
459
            pp->AlignmentCheck = MisalignmentForByteAccess;
455
            pp->AlignmentCheck = MisalignmentForByteAccess;
460
            break;
456
            break;
461
        case WORD_ACCESS:
457
        case WORD_ACCESS:
462
            pp->read  = readWord;
458
            pp->read  = readWord;
463
            pp->write = writeWord;
459
            pp->write = writeWord;
464
            pp->AlignmentCheck = MisalignmentForWordAccess;
460
            pp->AlignmentCheck = MisalignmentForWordAccess;
465
            break;
461
            break;
466
        case LONG_ACCESS:
462
        case LONG_ACCESS:
467
            pp->read  = readLong;
463
            pp->read  = readLong;
468
            pp->write = writeLong;
464
            pp->write = writeLong;
469
            pp->AlignmentCheck = MisalignmentForLongAccess;
465
            pp->AlignmentCheck = MisalignmentForLongAccess;
470
            break;
466
            break;
471
        default:
467
        default:
472
            return -EINVAL;
468
            return -EINVAL;
473
    }
469
    }
474
 
470
 
475
    return 0;
471
    return 0;
476
}
472
}
477
 
473
 
478
static int get_static_status(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_STATIC_STATUS *static_status)
474
static int get_static_status(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_STATIC_STATUS *static_status)
479
{
475
{
480
    PRINTK(KERN_DEBUG "%s : get_static_status()\n", DEVICE_NAME);
476
    PRINTK(KERN_DEBUG "%s : get_static_status()\n", DEVICE_NAME);
481
 
477
 
482
    static_status->bConnected        = pd->bConnected;
478
    static_status->bConnected        = pd->bConnected;
483
    static_status->cModuleNumber     = pd->cModuleNumber;
479
    static_status->cModuleNumber     = pd->cModuleNumber;
484
    static_status->cFPGAVersion      = pd->cFPGAVersion;
480
    static_status->cFPGAVersion      = pd->cFPGAVersion;
485
    static_status->cSystemController = pd->cSystemController;
481
    static_status->cSystemController = pd->cSystemController;
486
    static_status->cWordMode         = pd->cWordMode;
482
    static_status->cWordMode         = pd->cWordMode;
487
 
483
 
488
    return 0;
484
    return 0;
489
}
485
}
490
 
486
 
491
static int get_dynamic_status(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_DYNAMIC_STATUS *dynamic_status)
487
static int get_dynamic_status(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_DYNAMIC_STATUS *dynamic_status)
492
{
488
{
493
    u16 cntrl  = readw((const volatile void *)  pd->pPCIADACntrl);
489
    u16 cntrl  = readw((const volatile void *)  pd->pPCIADACntrl);
494
    u16 intCSR = readw((const volatile void *)  pd->pPCIADAIntCSR);
490
    u16 intCSR = readw((const volatile void *)  pd->pPCIADAIntCSR);
495
 
491
 
496
    PRINTK(KERN_DEBUG "%s : get_dynamic_status()\n", DEVICE_NAME);
492
    PRINTK(KERN_DEBUG "%s : get_dynamic_status()\n", DEVICE_NAME);
497
 
493
 
498
    dynamic_status->bConnected = (cntrl  & 0x0800) ? 1 : 0;
494
    dynamic_status->bConnected = (cntrl  & 0x0800) ? 1 : 0;
499
    dynamic_status->bPCIADAIrq = (intCSR & 0x0020) ? 1 : 0;
495
    dynamic_status->bPCIADAIrq = (intCSR & 0x0020) ? 1 : 0;
500
    dynamic_status->bVMEMMIrq  = (intCSR & 0x0004) ? 1 : 0;
496
    dynamic_status->bVMEMMIrq  = (intCSR & 0x0004) ? 1 : 0;
501
 
497
 
502
    return 0;
498
    return 0;
503
}
499
}
504
 
500
 
505
static int read_vector_polling(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VECTOR_LEVEL *vector)
501
static int read_vector_polling(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VECTOR_LEVEL *vector)
506
{
502
{
507
    u16 cntrl  = readw((const volatile void *) pd->pPCIADACntrl);
503
    u16 cntrl  = readw((const volatile void *) pd->pPCIADACntrl);
508
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
504
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
509
 
505
 
510
    PRINTK(KERN_DEBUG "%s : read_vector()\n", DEVICE_NAME);
506
    PRINTK(KERN_DEBUG "%s : read_vector()\n", DEVICE_NAME);
511
 
507
 
512
    vector->dwStatusID = 0;  
508
    vector->dwStatusID = 0;  
513
    vector->bLevel     = 0;
509
    vector->bLevel     = 0;
514
    vector->bPCIADAIrq = 0;
510
    vector->bPCIADAIrq = 0;
515
 
511
 
516
    if (intCSR & 0x20) // check for PCIADA interrupt
512
    if (intCSR & 0x20) // check for PCIADA interrupt
517
    {
513
    {
518
        vector->bPCIADAIrq = 1;
514
        vector->bPCIADAIrq = 1;
519
        vector->dwStatusID = 1; // force for PCIADA irqs
515
        vector->dwStatusID = 1; // force for PCIADA irqs
520
 
516
 
521
        writew(cntrl & ~0x0100, (volatile void *) pd->pPCIADACntrl);   // clear pending PCIADA irq
517
        writew(cntrl & ~0x0100, (volatile void *) pd->pPCIADACntrl);   // clear pending PCIADA irq
522
        writew(cntrl,           (volatile void *) pd->pPCIADACntrl);
518
        writew(cntrl,           (volatile void *) pd->pPCIADACntrl);
523
    }
519
    }
524
    else
520
    else
525
    {
521
    {
526
        if ((cntrl & 0x0980) == 0x0980) // check if VMEMM is connected and ready
522
        if ((cntrl & 0x0980) == 0x0980) // check if VMEMM is connected and ready
527
        {
523
        {
528
            vector->bLevel = (u8)readw((const volatile void *) ( pd->pCtl + VICRES ));
524
            vector->bLevel = (u8)readw((const volatile void *) ( pd->pCtl + VICRES ));
529
            if (vector->bLevel & 1)
525
            if (vector->bLevel & 1)
530
            {
526
            {
531
                if (vector->bLevel != 1)
527
                if (vector->bLevel != 1)
532
                    vector->dwStatusID = (u32)readb((const volatile void *) (pd->pCtl + VECBASE + vector->bLevel));
528
                    vector->dwStatusID = (u32)readb((const volatile void *) (pd->pCtl + VECBASE + vector->bLevel));
533
 
529
 
534
                vector->bLevel >>= 1;
530
                vector->bLevel >>= 1;
535
            }
531
            }
536
        }
532
        }
537
    }
533
    }
538
    return 0;
534
    return 0;
539
}
535
}
540
 
536
 
541
static int read_vector_blocking(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VECTOR_LEVEL *vector, struct file *pFile)
537
static int read_vector_blocking(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VECTOR_LEVEL *vector, struct file *pFile)
542
{
538
{
543
    int error;
539
    int error;
544
 
540
 
545
    vector->dwStatusID = 0;  
541
    vector->dwStatusID = 0;  
546
    vector->bLevel     = 0;
542
    vector->bLevel     = 0;
547
    vector->bPCIADAIrq = 0;
543
    vector->bPCIADAIrq = 0;
548
 
544
 
549
    // support nonblocking read if requested
545
    // support nonblocking read if requested
550
    if ((pFile->f_flags & O_NONBLOCK) && (!pd->wIrqStatus))
546
    if ((pFile->f_flags & O_NONBLOCK) && (!pd->wIrqStatus))
551
        return -EAGAIN;
547
        return -EAGAIN;
552
 
548
 
553
    // sleep until data are available
549
    // sleep until data are available
554
    if ((error = wait_event_interruptible(pd->event_queue, (pd->wIrqStatus))))
550
    if ((error = wait_event_interruptible(pd->event_queue, (pd->wIrqStatus))))
555
        return error;
551
        return error;
556
 
552
 
557
    error = read_vector_polling(pp, pd, vector);
553
    error = read_vector_polling(pp, pd, vector);
558
 
554
 
559
    pd->wIrqStatus  = 0;  // clear the status since it is read  
555
    pd->wIrqStatus  = 0;  // clear the status since it is read  
560
 
556
 
561
    return error;
557
    return error;
562
}
558
}
563
 
559
 
564
 
560
 
565
static int control_interrupts(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_IRQ_CONTROL *irq_control)
561
static int control_interrupts(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_IRQ_CONTROL *irq_control)
566
{
562
{
567
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
563
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
568
    u8  ret    = (intCSR & 0x40) ? 1 : 0;
564
    u8  ret    = (intCSR & 0x40) ? 1 : 0;
569
 
565
 
570
    PRINTK(KERN_DEBUG "%s : control_interrupts()\n", DEVICE_NAME);
566
    PRINTK(KERN_DEBUG "%s : control_interrupts()\n", DEVICE_NAME);
571
 
567
 
572
    if (irq_control->bEnable)
568
    if (irq_control->bEnable)
573
        writew(intCSR |  0x40, (volatile void *) pd->pPCIADAIntCSR);
569
        writew(intCSR |  0x40, (volatile void *) pd->pPCIADAIntCSR);
574
    else
570
    else
575
        writew(intCSR & ~0x40, (volatile void *) pd->pPCIADAIntCSR);
571
        writew(intCSR & ~0x40, (volatile void *) pd->pPCIADAIntCSR);
576
 
572
 
577
    // return the switch before set
573
    // return the switch before set
578
    irq_control->bEnable = ret;
574
    irq_control->bEnable = ret;
579
 
575
 
580
    return 0;
576
    return 0;
581
}
577
}
582
 
578
 
583
static int VME_TAS(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_TAS_STRUCT *tas_cmd)
579
static int VME_TAS(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_TAS_STRUCT *tas_cmd)
584
{
580
{
585
    u32 access_adr = pd->pVME + (tas_cmd->dwAddress & LO_ADDRESS_MASK); // make low part of address
581
    u32 access_adr = pd->pVME + (tas_cmd->dwAddress & LO_ADDRESS_MASK); // make low part of address
586
    u8  data;
582
    u8  data;
587
 
583
 
588
    // save old contents
584
    // save old contents
589
    u32 old_address         = readl((const volatile void *) pd->pAdrReg);
585
    u32 old_address         = readl((const volatile void *) pd->pAdrReg);
590
    u16 old_CSR             = readw((const volatile void *) pd->pCSR);
586
    u16 old_CSR             = readw((const volatile void *) pd->pCSR);
591
    u16 intCSR              = readw((const volatile void *) pd->pPCIADAIntCSR);
587
    u16 intCSR              = readw((const volatile void *) pd->pPCIADAIntCSR);
592
    pd->bCurrentModifier    = readb((const volatile void *) pd->pAdrMod) & 0x3f;
588
    pd->bCurrentModifier    = readb((const volatile void *) pd->pAdrMod) & 0x3f;
593
 
589
 
594
    PRINTK(KERN_DEBUG "%s : VME_TAS()\n", DEVICE_NAME);
590
    PRINTK(KERN_DEBUG "%s : VME_TAS()\n", DEVICE_NAME);
595
 
591
 
596
    // set new contents
592
    // set new contents
597
    writew(DISABLE_PCIADA_IRQS,           (volatile void *) pd->pPCIADAIntCSR);
593
    writew(DISABLE_PCIADA_IRQS,           (volatile void *) pd->pPCIADAIntCSR);
598
    writeb((u8)tas_cmd->bModifier & 0x3f, (volatile void *) pd->pAdrMod);
594
    writeb((u8)tas_cmd->bModifier & 0x3f, (volatile void *) pd->pAdrMod);
599
    writel(tas_cmd->dwAddress,            (volatile void *) pd->pAdrReg);
595
    writel(tas_cmd->dwAddress,            (volatile void *) pd->pAdrReg);
600
    writew(old_CSR | FLAG_RMC,            (volatile void *) pd->pCSR);
596
    writew(old_CSR | FLAG_RMC,            (volatile void *) pd->pCSR);
601
 
597
 
602
    // do the read - modify - write
598
    // do the read - modify - write
603
    data = readb((const volatile void *) access_adr);
599
    data = readb((const volatile void *) access_adr);
604
    writeb(tas_cmd->bContent, (volatile void *) access_adr);
600
    writeb(tas_cmd->bContent, (volatile void *) access_adr);
605
 
601
 
606
    // restore old contents
602
    // restore old contents
607
    writeb(pd->bCurrentModifier, (volatile void *) pd->pAdrMod);
603
    writeb(pd->bCurrentModifier, (volatile void *) pd->pAdrMod);
608
    writew(old_CSR,              (volatile void *) pd->pCSR);
604
    writew(old_CSR,              (volatile void *) pd->pCSR);
609
    writel(old_address,          (volatile void *) pd->pAdrReg);
605
    writel(old_address,          (volatile void *) pd->pAdrReg);
610
    writew(intCSR,               (volatile void *) pd->pPCIADAIntCSR);
606
    writew(intCSR,               (volatile void *) pd->pPCIADAIntCSR);
611
 
607
 
612
    // get back read data
608
    // get back read data
613
    tas_cmd->bContent = data;
609
    tas_cmd->bContent = data;
614
 
610
 
615
    return 0;
611
    return 0;
616
}
612
}
617
 
613
 
618
static int VMEMM_RESET(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_RESET_COMMAND *reset_cmd)
614
static int VMEMM_RESET(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_RESET_COMMAND *reset_cmd)
619
{
615
{
620
    u16 cntrl  = readw((const volatile void *) pd->pPCIADACntrl);
616
    u16 cntrl  = readw((const volatile void *) pd->pPCIADACntrl);
621
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
617
    u16 intCSR = readw((const volatile void *) pd->pPCIADAIntCSR);
622
    int status = 0;
618
    int status = 0;
623
 
619
 
624
    PRINTK(KERN_INFO "%s : VMEMM_RESET()\n", DEVICE_NAME);
620
    PRINTK(KERN_INFO "%s : VMEMM_RESET()\n", DEVICE_NAME);
625
 
621
 
626
    // am I connected and switched on??
622
    // am I connected and switched on??
627
    if ((cntrl & 0x0980) == 0x0980)
623
    if ((cntrl & 0x0980) == 0x0980)
628
    {
624
    {
629
        // do command
625
        // do command
630
        switch (reset_cmd->bCommand)
626
        switch (reset_cmd->bCommand)
631
        {
627
        {
632
            case POLL_RESET_CMD:
628
            case POLL_RESET_CMD:
633
                break;
629
                break;
634
            case VME_RESET_CMD:
630
            case VME_RESET_CMD:
635
                writeb(0, (volatile void *) pd->pAdrMod);
631
                writeb(0, (volatile void *) pd->pAdrMod);
636
                writeb(0xf0, (volatile void *) (pd->pCtl + VICBASE + SRR));  // make VME reset
632
                writeb(0xf0, (volatile void *) (pd->pCtl + VICBASE + SRR));  // make VME reset
637
                break;
633
                break;
638
            case LOCAL_RESET_CMD:
634
            case LOCAL_RESET_CMD:
639
                writeb(0, (volatile void *) pd->pAdrMod);
635
                writeb(0, (volatile void *) pd->pAdrMod);
640
                writew(LOCAL_RESET,  (volatile void *) (pd->pCtl + VICRES));
636
                writew(LOCAL_RESET,  (volatile void *) (pd->pCtl + VICRES));
641
                break;
637
                break;
642
            case GLOBAL_RESET_CMD:
638
            case GLOBAL_RESET_CMD:
643
                writeb(0, (volatile void *) pd->pAdrMod);
639
                writeb(0, (volatile void *) pd->pAdrMod);
644
                writew(GLOBAL_RESET, (volatile void *) (pd->pCtl + VICRES));
640
                writew(GLOBAL_RESET, (volatile void *) (pd->pCtl + VICRES));
645
                break;
641
                break;
646
 
642
 
647
            default: status = -EINVAL;
643
            default: status = -EINVAL;
648
        }
644
        }
649
 
645
 
650
        // inhibit PCIADA generated irqs
646
        // inhibit PCIADA generated irqs
651
        writew(DISABLE_PCIADA_IRQS, (volatile void *) pd->pPCIADAIntCSR);
647
        writew(DISABLE_PCIADA_IRQS, (volatile void *) pd->pPCIADAIntCSR);
652
 
648
 
653
        // always poll reset status - access will sometimes generate PCIADA #2 interrupt
649
        // always poll reset status - access will sometimes generate PCIADA #2 interrupt
654
        reset_cmd->bResult = readb((const volatile void *) pd->pAdrMod);
650
        reset_cmd->bResult = readb((const volatile void *) pd->pAdrMod);
655
 
651
 
656
        // reset any pending PCIADA interrupt #2
652
        // reset any pending PCIADA interrupt #2
657
        writew(cntrl & ~0x0100, (volatile void *) pd->pPCIADACntrl);
653
        writew(cntrl & ~0x0100, (volatile void *) pd->pPCIADACntrl);
658
        writew(cntrl          , (volatile void *) pd->pPCIADACntrl);
654
        writew(cntrl          , (volatile void *) pd->pPCIADACntrl);
659
 
655
 
660
        // restore IRQStatus
656
        // restore IRQStatus
661
        writew(intCSR          , (volatile void *) pd->pPCIADAIntCSR);
657
        writew(intCSR          , (volatile void *) pd->pPCIADAIntCSR);
662
    }
658
    }
663
    else
659
    else
664
        status = -EBUSY;
660
        status = -EBUSY;
665
 
661
 
666
    // sync storage with hardware
662
    // sync storage with hardware
667
    pd->bCurrentModifier = readb((const volatile void *) pd->pAdrMod) & 0x3f;
663
    pd->bCurrentModifier = readb((const volatile void *) pd->pAdrMod) & 0x3f;
668
 
664
 
669
    return status;
665
    return status;
670
}
666
}
671
 
667
 
672
static int access_VIC68A(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VIC68A_ACTION *action)
668
static int access_VIC68A(PATH_OBJ *pp, DEVICE_OBJ *pd, PCIVME_VIC68A_ACTION *action)
673
{
669
{
674
    int nStatus = 0;
670
    int nStatus = 0;
675
 
671
 
676
    PRINTK(KERN_DEBUG "%s : access_VIC68A()\n", DEVICE_NAME);
672
    PRINTK(KERN_DEBUG "%s : access_VIC68A()\n", DEVICE_NAME);
677
 
673
 
678
    if ((action->wRegisterAddress <= SRR) && ((action->wRegisterAddress & 0x03) == 3))
674
    if ((action->wRegisterAddress <= SRR) && ((action->wRegisterAddress & 0x03) == 3))
679
    {
675
    {
680
        u32 dwAddress;
676
        u32 dwAddress;
681
        u8  bByte = 0;
677
        u8  bByte = 0;
682
 
678
 
683
        dwAddress = (pd->pCtl + VICBASE + action->wRegisterAddress);
679
        dwAddress = (pd->pCtl + VICBASE + action->wRegisterAddress);
684
 
680
 
685
        switch (action->bAccessMode)
681
        switch (action->bAccessMode)
686
        {
682
        {
687
            case VIC68A_WRITE_ONLY:
683
            case VIC68A_WRITE_ONLY:
688
                writeb(action->bContent, (volatile void *) dwAddress);
684
                writeb(action->bContent, (volatile void *) dwAddress);
689
                break;
685
                break;
690
            case VIC68A_WRITE:  
686
            case VIC68A_WRITE:  
691
                writeb(action->bContent, (volatile void *) dwAddress);
687
                writeb(action->bContent, (volatile void *) dwAddress);
692
                action->bContent = readb((const volatile void *) dwAddress);
688
                action->bContent = readb((const volatile void *) dwAddress);
693
                break;
689
                break;
694
            case VIC68A_OR:    
690
            case VIC68A_OR:    
695
                bByte      = readb((const volatile void *) dwAddress);
691
                bByte      = readb((const volatile void *) dwAddress);
696
                bByte     |= action->bContent;
692
                bByte     |= action->bContent;
697
                writeb(bByte, (volatile void *) dwAddress);
693
                writeb(bByte, (volatile void *) dwAddress);
698
                action->bContent = readb((const volatile void *) dwAddress);
694
                action->bContent = readb((const volatile void *) dwAddress);
699
                break;
695
                break;
700
            case VIC68A_AND:    
696
            case VIC68A_AND:    
701
                bByte      = readb((const volatile void *) dwAddress);
697
                bByte      = readb((const volatile void *) dwAddress);
702
                bByte     &= action->bContent;
698
                bByte     &= action->bContent;
703
                writeb(bByte, (volatile void *) dwAddress);
699
                writeb(bByte, (volatile void *) dwAddress);
704
                action->bContent = readb((const volatile void *) dwAddress);
700
                action->bContent = readb((const volatile void *) dwAddress);
705
                break;
701
                break;
706
            case VIC68A_READ:  
702
            case VIC68A_READ:  
707
                action->bContent = readb((const volatile void *) dwAddress);
703
                action->bContent = readb((const volatile void *) dwAddress);
708
                break;
704
                break;
709
            default:            
705
            default:            
710
                nStatus = -EINVAL;
706
                nStatus = -EINVAL;
711
        }
707
        }
712
    }
708
    }
713
    else
709
    else
714
        nStatus = -EINVAL;
710
        nStatus = -EINVAL;
715
 
711
 
716
    return nStatus;
712
    return nStatus;
717
}
713
}
718
 
714
 
719
// the dispatcher ----------------------------------------------------------------------------------
715
// the dispatcher ----------------------------------------------------------------------------------
720
int pcivme_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
716
int pcivme_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
721
{
717
{
722
    PATH_OBJ   *pp = (PATH_OBJ *)pFile->private_data;
718
    PATH_OBJ   *pp = (PATH_OBJ *)pFile->private_data;
723
    DEVICE_OBJ *pd = pp->pDo;
719
    DEVICE_OBJ *pd = pp->pDo;
724
    int err = 1;
720
    int err = 1;
725
   
721
   
726
    PRINTK(KERN_DEBUG "%s : pcivme_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
722
    PRINTK(KERN_DEBUG "%s : pcivme_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
727
 
723
 
728
    if (_IOC_TYPE(cmd) != PCIVME_MAGIC)
724
    if (_IOC_TYPE(cmd) != PCIVME_MAGIC)
729
        return -EINVAL;
725
        return -EINVAL;
730
 
726
 
731
    // check for accessible user buffer
727
    // check for accessible user buffer
732
    if (_IOC_DIR(cmd) & _IOC_READ)
728
    if (_IOC_DIR(cmd) & _IOC_READ)
733
        err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
729
        err = !access_ok( (void *)arg, _IOC_SIZE(cmd));
734
    if (_IOC_DIR(cmd) & _IOC_WRITE)
730
    if (_IOC_DIR(cmd) & _IOC_WRITE)
735
        err = !access_ok(VERIFY_READ,  (void *)arg, _IOC_SIZE(cmd));
731
        err = !access_ok( (void *)arg, _IOC_SIZE(cmd));
736
    if (err)
732
    if (err)
737
        return -EFAULT;
733
        return -EFAULT;
738
 
734
 
739
    switch (_IOC_NR(cmd))
735
    switch (_IOC_NR(cmd))
740
    {
736
    {
741
        case _IOC_NR(PCIVME_READ_VECTOR_BLOCK):
737
        case _IOC_NR(PCIVME_READ_VECTOR_BLOCK):
742
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VECTOR_LEVEL))
738
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VECTOR_LEVEL))
743
                return -EINVAL;
739
                return -EINVAL;
744
            return read_vector_blocking(pp, pd, (PCIVME_VECTOR_LEVEL *)arg, pFile);
740
            return read_vector_blocking(pp, pd, (PCIVME_VECTOR_LEVEL *)arg, pFile);
745
 
741
 
746
        case _IOC_NR(PCIVME_READ_VECTOR_POLL):
742
        case _IOC_NR(PCIVME_READ_VECTOR_POLL):
747
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VECTOR_LEVEL))
743
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VECTOR_LEVEL))
748
                return -EINVAL;
744
                return -EINVAL;
749
            return read_vector_polling(pp, pd, (PCIVME_VECTOR_LEVEL *)arg);
745
            return read_vector_polling(pp, pd, (PCIVME_VECTOR_LEVEL *)arg);
750
 
746
 
751
        case _IOC_NR(PCIVME_CONTROL_INTERRUPTS):
747
        case _IOC_NR(PCIVME_CONTROL_INTERRUPTS):
752
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_IRQ_CONTROL))
748
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_IRQ_CONTROL))
753
                return -EINVAL;
749
                return -EINVAL;
754
            return control_interrupts(pp, pd, (PCIVME_IRQ_CONTROL *)arg);
750
            return control_interrupts(pp, pd, (PCIVME_IRQ_CONTROL *)arg);
755
 
751
 
756
        case _IOC_NR(PCIVME_TAS):
752
        case _IOC_NR(PCIVME_TAS):
757
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_TAS_STRUCT))
753
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_TAS_STRUCT))
758
                return -EINVAL;
754
                return -EINVAL;
759
            return VME_TAS(pp, pd, (PCIVME_TAS_STRUCT *)arg);
755
            return VME_TAS(pp, pd, (PCIVME_TAS_STRUCT *)arg);
760
 
756
 
761
        case _IOC_NR(PCIVME_ACCESS_VIC68A):
757
        case _IOC_NR(PCIVME_ACCESS_VIC68A):
762
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VIC68A_ACTION))
758
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_VIC68A_ACTION))
763
                return -EINVAL;
759
                return -EINVAL;
764
            return access_VIC68A(pp, pd, (PCIVME_VIC68A_ACTION *)arg);
760
            return access_VIC68A(pp, pd, (PCIVME_VIC68A_ACTION *)arg);
765
 
761
 
766
        case _IOC_NR(PCIVME_GET_DYNAMIC_STATUS):
762
        case _IOC_NR(PCIVME_GET_DYNAMIC_STATUS):
767
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_DYNAMIC_STATUS))
763
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_DYNAMIC_STATUS))
768
                return -EINVAL;
764
                return -EINVAL;
769
            return get_dynamic_status(pp, pd, (PCIVME_DYNAMIC_STATUS *)arg);
765
            return get_dynamic_status(pp, pd, (PCIVME_DYNAMIC_STATUS *)arg);
770
 
766
 
771
        case _IOC_NR(PCIVME_RESET):
767
        case _IOC_NR(PCIVME_RESET):
772
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_RESET_COMMAND))
768
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_RESET_COMMAND))
773
                return -EINVAL;
769
                return -EINVAL;
774
            return VMEMM_RESET(pp, pd, (PCIVME_RESET_COMMAND *)arg);
770
            return VMEMM_RESET(pp, pd, (PCIVME_RESET_COMMAND *)arg);
775
 
771
 
776
        case _IOC_NR(PCIVME_SET_ACCESS_PARA):
772
        case _IOC_NR(PCIVME_SET_ACCESS_PARA):
777
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_ACCESS_COMMAND))
773
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_ACCESS_COMMAND))
778
                return -EINVAL;
774
                return -EINVAL;
779
            return access_command(pp, pd, (PCIVME_ACCESS_COMMAND *)arg);
775
            return access_command(pp, pd, (PCIVME_ACCESS_COMMAND *)arg);
780
 
776
 
781
        case _IOC_NR(PCIVME_GET_STATIC_STATUS):
777
        case _IOC_NR(PCIVME_GET_STATIC_STATUS):
782
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_STATIC_STATUS))
778
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_STATIC_STATUS))
783
                return -EINVAL;
779
                return -EINVAL;
784
            return get_static_status(pp, pd, (PCIVME_STATIC_STATUS *)arg);
780
            return get_static_status(pp, pd, (PCIVME_STATIC_STATUS *)arg);
785
 
781
 
786
        case _IOC_NR(PCIVME_INIT_HARDWARE):
782
        case _IOC_NR(PCIVME_INIT_HARDWARE):
787
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_INIT_COMMAND))
783
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_INIT_COMMAND))
788
                return -EINVAL;
784
                return -EINVAL;
789
            return init_hardware(pp, pd, (PCIVME_INIT_COMMAND *)arg);
785
            return init_hardware(pp, pd, (PCIVME_INIT_COMMAND *)arg);
790
 
786
 
791
        case _IOC_NR(PCIVME_DEINIT_HARDWARE):
787
        case _IOC_NR(PCIVME_DEINIT_HARDWARE):
792
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_INIT_COMMAND))
788
            if (_IOC_SIZE(cmd) < sizeof(PCIVME_INIT_COMMAND))
793
                 return -EINVAL;
789
                 return -EINVAL;
794
            return deinit_hardware(pp, pd, (PCIVME_INIT_COMMAND *)arg);
790
            return deinit_hardware(pp, pd, (PCIVME_INIT_COMMAND *)arg);
795
                                               
791
                                               
796
        default:
792
        default:
797
            PRINTK(KERN_DEBUG "%s : pcivme_ioctl(0x%08x) is illegal\n", DEVICE_NAME, cmd);
793
            PRINTK(KERN_DEBUG "%s : pcivme_ioctl(0x%08x) is illegal\n", DEVICE_NAME, cmd);
798
            return -EINVAL;
794
            return -EINVAL;
799
    }
795
    }
800
 
796
 
801
    return 0;
797
    return 0;
802
}
798
}
803
 
799
 
804
/*
800
/*
805
static long  pcivme_compat_ioctl(struct file *pFile, unsigned int cmd, unsigned long arg){
801
static long  pcivme_compat_ioctl(struct file *pFile, unsigned int cmd, unsigned long arg){
806
PRINTK(KERN_DEBUG "%s : pcivme_compat_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
802
PRINTK(KERN_DEBUG "%s : pcivme_compat_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
807
return pcivme_ioctl(NULL, pFile, cmd,arg);
803
return pcivme_ioctl(NULL, pFile, cmd,arg);
808
}
804
}
809
*/
805
*/
810
 
806
 
811
static long  pcivme_unlocked_ioctl(struct file *pFile, unsigned int cmd, unsigned long arg){
807
static long  pcivme_unlocked_ioctl(struct file *pFile, unsigned int cmd, unsigned long arg){
812
long retval=0;
808
long retval=0;
813
 
809
 
814
 
810
 
815
#if HAVE_UNLOCKED_IOCTL
-
 
816
    struct mutex  fs_mutex;
811
    struct mutex  fs_mutex;
817
   mutex_init(&fs_mutex);
812
   mutex_init(&fs_mutex);
818
   mutex_lock(&fs_mutex);
813
   mutex_lock(&fs_mutex);
819
#else
-
 
820
   lock_kernel();
-
 
821
#endif
-
 
822
 
814
 
823
PRINTK(KERN_DEBUG "%s : pcivme_unlocked_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
815
PRINTK(KERN_DEBUG "%s : pcivme_unlocked_ioctl(0x%08x), size = %d\n", DEVICE_NAME, cmd, _IOC_SIZE(cmd));
824
retval = pcivme_ioctl(NULL, pFile, cmd,arg);
816
retval = pcivme_ioctl(NULL, pFile, cmd,arg);
825
 
817
 
826
#if HAVE_UNLOCKED_IOCTL
-
 
827
   mutex_unlock(&fs_mutex);
818
   mutex_unlock(&fs_mutex);
828
#else
-
 
829
   unlock_kernel();
-
 
830
#endif
-
 
831
 
819
 
832
return retval;
820
return retval;
833
}
821
}
834
 
822
 
835
int pcivme_open(struct inode *pInode, struct file *pFile)
823
int pcivme_open(struct inode *pInode, struct file *pFile)
836
{
824
{
837
    DEVICE_OBJ *pd   = 0;
825
    DEVICE_OBJ *pd   = 0;
838
    DEVICE_OBJ *desc = 0;
826
    DEVICE_OBJ *desc = 0;
839
    int nMinor = MINOR(pInode->i_rdev);
827
    int nMinor = MINOR(pInode->i_rdev);
840
    struct list_head *ptr;
828
    struct list_head *ptr;
841
 
829
 
842
    PRINTK(KERN_DEBUG "%s : pcivme_open(), %d, scanning %d devices\n", DEVICE_NAME, nMinor, drv.count);
830
    PRINTK(KERN_DEBUG "%s : pcivme_open(), %d, scanning %d devices\n", DEVICE_NAME, nMinor, drv.count);
843
 
831
 
844
    /* search for device */
832
    /* search for device */
845
    for (ptr = drv.devList.next; ptr != &drv.devList; ptr = ptr->next)
833
    for (ptr = drv.devList.next; ptr != &drv.devList; ptr = ptr->next)
846
    {
834
    {
847
        pd = list_entry(ptr, DEVICE_OBJ, list);
835
        pd = list_entry(ptr, DEVICE_OBJ, list);
848
        pd->bConnected =  get_module_info(pd);
836
        pd->bConnected =  get_module_info(pd);
849
        if (pd->bConnected)
837
        if (pd->bConnected)
850
        {
838
        {
851
            if (test_connection(pd))
839
            if (test_connection(pd))
852
            {
840
            {
853
                printk(KERN_ERR "%s :  pcivme_open() connection test for module %d failed!\n", DEVICE_NAME, pd->cModuleNumber);
841
                printk(KERN_ERR "%s :  pcivme_open() connection test for module %d failed!\n", DEVICE_NAME, pd->cModuleNumber);
854
                pd->bConnected = 0;
842
                pd->bConnected = 0;
855
            }
843
            }
856
            else
844
            else
857
                if (pd->cModuleNumber == nMinor)
845
                if (pd->cModuleNumber == nMinor)
858
            {
846
            {
859
                desc = pd;
847
                desc = pd;
860
                break;
848
                break;
861
            }
849
            }
862
        }
850
        }
863
        else
851
        else
864
            PRINTK(KERN_DEBUG "%s  pcivme_open(): module %d not connected!\n", DEVICE_NAME, nMinor);
852
            PRINTK(KERN_DEBUG "%s  pcivme_open(): module %d not connected!\n", DEVICE_NAME, nMinor);
865
    }
853
    }
866
 
854
 
867
    if (desc)
855
    if (desc)
868
    {
856
    {
869
        int       err;
857
        int       err;
870
        PATH_OBJ  *pp;
858
        PATH_OBJ  *pp;
871
 
859
 
872
        pp = (PATH_OBJ *)kmalloc(sizeof(PATH_OBJ), GFP_ATOMIC);
860
        pp = (PATH_OBJ *)kmalloc(sizeof(PATH_OBJ), GFP_ATOMIC);
873
        if (!pp)
861
        if (!pp)
874
            return -ENOMEM;
862
            return -ENOMEM;
875
 
863
 
876
        // file PATH_OBJ structure with initialisation data             
864
        // file PATH_OBJ structure with initialisation data             
877
        pp->pDo            = pd;
865
        pp->pDo            = pd;
878
        pp->bAccessType    = pp->bIncrement = BYTE_ACCESS;  
866
        pp->bAccessType    = pp->bIncrement = BYTE_ACCESS;  
879
        pp->bModifier      = Short_NoPriv;  
867
        pp->bModifier      = Short_NoPriv;  
880
        pp->read           = readByte;
868
        pp->read           = readByte;
881
        pp->write          = writeByte;
869
        pp->write          = writeByte;
882
        pp->AlignmentCheck = MisalignmentForByteAccess;
870
        pp->AlignmentCheck = MisalignmentForByteAccess;
883
        pFile->private_data = (void *)pp;
871
        pFile->private_data = (void *)pp;
884
 
872
 
885
        PRINTK(KERN_DEBUG "%s :  pcivme_open() found VMEMM module with number %d.\n", DEVICE_NAME, nMinor);
873
        PRINTK(KERN_DEBUG "%s :  pcivme_open() found VMEMM module with number %d.\n", DEVICE_NAME, nMinor);
886
 
874
 
887
        if (!pd->nOpenCounter)
875
        if (!pd->nOpenCounter)
888
        {
876
        {
889
            err = CmdMachine(pd, init_element);
877
            err = CmdMachine(pd, init_element);
890
            if (err)
878
            if (err)
891
            {
879
            {
892
                printk(KERN_ERR "%s :  pcivme_open() default init failed with err = %d!\n", DEVICE_NAME, err);
880
                printk(KERN_ERR "%s :  pcivme_open() default init failed with err = %d!\n", DEVICE_NAME, err);
893
                kfree_s(pp, sizeof(*pp));    // FREE(pFile->private_data);
881
                kfree_s(pp, sizeof(*pp));    // FREE(pFile->private_data);
894
                return err;
882
                return err;
895
            }
883
            }
896
        }
884
        }
897
 
885
 
898
        pd->nOpenCounter++;
886
        pd->nOpenCounter++;
899
    }
887
    }
900
    else
888
    else
901
    {
889
    {
902
        printk(KERN_ERR "%s  pcivme_open(): No VMEMM module found.\n", DEVICE_NAME);
890
        printk(KERN_ERR "%s  pcivme_open(): No VMEMM module found.\n", DEVICE_NAME);
903
        return -ENODEV;
891
        return -ENODEV;
904
    }      
892
    }      
905
 
893
 
906
    __MOD_INC_USE_COUNT__;
894
    __MOD_INC_USE_COUNT__;
907
    return 0;
895
    return 0;
908
}
896
}
909
 
897
 
910
int pcivme_release(struct inode *pInode, struct file *pFile)
898
int pcivme_release(struct inode *pInode, struct file *pFile)
911
{
899
{
912
    PATH_OBJ *pp;
900
    PATH_OBJ *pp;
913
 
901
 
914
    PRINTK(KERN_DEBUG "%s : pcivme_release()\n", DEVICE_NAME);
902
    PRINTK(KERN_DEBUG "%s : pcivme_release()\n", DEVICE_NAME);
915
 
903
 
916
    if (pFile->private_data)
904
    if (pFile->private_data)
917
    {
905
    {
918
        pp = (PATH_OBJ *)pFile->private_data;
906
        pp = (PATH_OBJ *)pFile->private_data;
919
        if (pp && pp->pDo )
907
        if (pp && pp->pDo )
920
        {
908
        {
921
            DEVICE_OBJ *pd = pp->pDo;
909
            DEVICE_OBJ *pd = pp->pDo;
922
 
910
 
923
            pd->nOpenCounter--;
911
            pd->nOpenCounter--;
924
 
912
 
925
            // the last one closes the door
913
            // the last one closes the door
926
            if (pd->nOpenCounter <= 0)
914
            if (pd->nOpenCounter <= 0)
927
            {
915
            {
928
                CmdMachine(pd, deinit_element_pre);
916
                CmdMachine(pd, deinit_element_pre);
929
                CmdMachine(pd, deinit_element_post);
917
                CmdMachine(pd, deinit_element_post);
930
 
918
 
931
                // Vorsicht ist die Mutter der Porzelankiste!
919
                // Vorsicht ist die Mutter der Porzelankiste!
932
                pd->nOpenCounter = 0;
920
                pd->nOpenCounter = 0;
933
            }
921
            }
934
 
922
 
935
            pp->pDo = 0;            
923
            pp->pDo = 0;            
936
        }
924
        }
937
 
925
 
938
        kfree_s(pp, sizeof(*pp));    // FREE(pFile->private_data);
926
        kfree_s(pp, sizeof(*pp));    // FREE(pFile->private_data);
939
    }
927
    }
940
 
928
 
941
    __MOD_DEC_USE_COUNT__;
929
    __MOD_DEC_USE_COUNT__;
942
    return 0;
930
    return 0;
943
}
931
}
944
 
932
 
945
static ssize_t pcivme_read(struct file *pFile, char *pcBuffer, size_t count, loff_t *offp)
933
static ssize_t pcivme_read(struct file *pFile, char *pcBuffer, size_t count, loff_t *offp)
946
{
934
{
947
    PATH_OBJ *pp     = (PATH_OBJ *)pFile->private_data;
935
    PATH_OBJ *pp     = (PATH_OBJ *)pFile->private_data;
948
    DEVICE_OBJ *pd   = pp->pDo;
936
    DEVICE_OBJ *pd   = pp->pDo;
949
    u32 dwLocalCount = count;
937
    u32 dwLocalCount = count;
950
    register u32 dwLocalPageAddress;
938
    register u32 dwLocalPageAddress;
951
    u32 dwLocalAddressInPage;
939
    u32 dwLocalAddressInPage;
952
 
940
 
953
    PRINTK(KERN_DEBUG "%s : pcivme_read(0x%08x, %d)\n", DEVICE_NAME, (u32)*offp, dwLocalCount);
941
    PRINTK(KERN_DEBUG "%s : pcivme_read(0x%08x, %d)\n", DEVICE_NAME, (u32)*offp, dwLocalCount);
954
 
942
 
955
    // inhibit misaligned accesses
943
    // inhibit misaligned accesses
956
    if (pp->AlignmentCheck(*offp))
944
    if (pp->AlignmentCheck(*offp))
957
        return -EFAULT;
945
        return -EFAULT;
958
 
946
 
959
    // check for free access to user buffer
947
    // check for free access to user buffer
960
    if (!access_ok(VERIFY_WRITE, pcBuffer, count))
948
    if (!access_ok( pcBuffer, count))
961
        return -EFAULT;
949
        return -EFAULT;
962
 
950
 
963
    // do I still have the same modifier?
951
    // do I still have the same modifier?
964
    if (pp->bModifier != pd->bCurrentModifier)
952
    if (pp->bModifier != pd->bCurrentModifier)
965
        setModifier(pd, pp->bModifier);
953
        setModifier(pd, pp->bModifier);
966
 
954
 
967
    while (count >= pp->bAccessType)
955
    while (count >= pp->bAccessType)
968
    {
956
    {
969
        dwLocalPageAddress   = *offp & HI_ADDRESS_MASK;
957
        dwLocalPageAddress   = *offp & HI_ADDRESS_MASK;
970
        dwLocalAddressInPage = *offp & LO_ADDRESS_MASK;
958
        dwLocalAddressInPage = *offp & LO_ADDRESS_MASK;
971
 
959
 
972
        // do I still work in the same page?
960
        // do I still work in the same page?
973
        if (dwLocalPageAddress != pd->dwCurrentPageAddress)
961
        if (dwLocalPageAddress != pd->dwCurrentPageAddress)
974
            setPageAddress(pd, dwLocalPageAddress);
962
            setPageAddress(pd, dwLocalPageAddress);
975
 
963
 
976
        // standard access method
964
        // standard access method
977
        pp->read(pd, (void **)&pcBuffer, dwLocalAddressInPage);  
965
        pp->read(pd, (void **)&pcBuffer, dwLocalAddressInPage);  
978
 
966
 
979
        // decrement count and update pointer to next access address
967
        // decrement count and update pointer to next access address
980
        count -= pp->bAccessType;
968
        count -= pp->bAccessType;
981
        *offp += pp->bIncrement;
969
        *offp += pp->bIncrement;
982
    }
970
    }
983
 
971
 
984
    return dwLocalCount - count;
972
    return dwLocalCount - count;
985
}
973
}
986
 
974
 
987
static ssize_t pcivme_write(struct file *pFile, const char *pcBuffer, size_t count, loff_t *offp)
975
static ssize_t pcivme_write(struct file *pFile, const char *pcBuffer, size_t count, loff_t *offp)
988
{
976
{
989
    PATH_OBJ *pp     = (PATH_OBJ *)pFile->private_data;
977
    PATH_OBJ *pp     = (PATH_OBJ *)pFile->private_data;
990
    DEVICE_OBJ *pd   = pp->pDo;
978
    DEVICE_OBJ *pd   = pp->pDo;
991
    u32 dwLocalCount = count;
979
    u32 dwLocalCount = count;
992
    register u32 dwLocalPageAddress;
980
    register u32 dwLocalPageAddress;
993
    u32 dwLocalAddressInPage;
981
    u32 dwLocalAddressInPage;
994
 
982
 
995
    PRINTK(KERN_DEBUG "%s : pcivme_write(0x%08x, %d)\n", DEVICE_NAME, (u32)*offp, dwLocalCount);
983
    PRINTK(KERN_DEBUG "%s : pcivme_write(0x%08x, %d)\n", DEVICE_NAME, (u32)*offp, dwLocalCount);
996
 
984
 
997
    // inhibit misaligned accesses
985
    // inhibit misaligned accesses
998
    if (pp->AlignmentCheck(*offp))
986
    if (pp->AlignmentCheck(*offp))
999
        return -EFAULT;
987
        return -EFAULT;
1000
 
988
 
1001
    // check for free access to user buffer
989
    // check for free access to user buffer
1002
    if (!access_ok(VERIFY_READ, pcBuffer, count))
990
    if (!access_ok( pcBuffer, count))
1003
        return -EFAULT;
991
        return -EFAULT;
1004
 
992
 
1005
    // do I still have the same modifier?
993
    // do I still have the same modifier?
1006
    if (pp->bModifier != pd->bCurrentModifier)
994
    if (pp->bModifier != pd->bCurrentModifier)
1007
        setModifier(pd, pp->bModifier);
995
        setModifier(pd, pp->bModifier);
1008
 
996
 
1009
    while (count >= pp->bAccessType)
997
    while (count >= pp->bAccessType)
1010
    {
998
    {
1011
        dwLocalPageAddress   = *offp & HI_ADDRESS_MASK;
999
        dwLocalPageAddress   = *offp & HI_ADDRESS_MASK;
1012
        dwLocalAddressInPage = *offp & LO_ADDRESS_MASK;
1000
        dwLocalAddressInPage = *offp & LO_ADDRESS_MASK;
1013
 
1001
 
1014
        // do I still work in the same page?
1002
        // do I still work in the same page?
1015
        if (dwLocalPageAddress != pd->dwCurrentPageAddress)
1003
        if (dwLocalPageAddress != pd->dwCurrentPageAddress)
1016
            setPageAddress(pd, dwLocalPageAddress);
1004
            setPageAddress(pd, dwLocalPageAddress);
1017
 
1005
 
1018
        // standard access method
1006
        // standard access method
1019
        pp->write(pd, dwLocalAddressInPage, (void **)&pcBuffer);
1007
        pp->write(pd, dwLocalAddressInPage, (void **)&pcBuffer);
1020
 
1008
 
1021
        // decrement count and update pointer to next access address
1009
        // decrement count and update pointer to next access address
1022
        count -= pp->bAccessType;
1010
        count -= pp->bAccessType;
1023
        *offp += pp->bIncrement;
1011
        *offp += pp->bIncrement;
1024
    }
1012
    }
1025
 
1013
 
1026
    return dwLocalCount - count;
1014
    return dwLocalCount - count;
1027
}
1015
}
1028
 
1016
 
1029
 
1017
 
1030
// http://learninglinuxkernel.in/writing-char-driver-for-linux-kernel-2-6/
1018
// http://learninglinuxkernel.in/writing-char-driver-for-linux-kernel-2-6/
1031
// http://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/
1019
// http://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/
1032
loff_t pcivme_lseek(struct file* filep, loff_t offset, int whence)
1020
loff_t pcivme_lseek(struct file* filep, loff_t offset, int whence)
1033
{
1021
{
1034
 
1022
 
1035
PRINTK(KERN_DEBUG "%s : pcivme_lseek(0x%08x, %d)\n", DEVICE_NAME, (u32) offset, whence);
1023
PRINTK(KERN_DEBUG "%s : pcivme_lseek(0x%08x, %d)\n", DEVICE_NAME, (u32) offset, whence);
1036
    switch (whence) {
1024
    switch (whence) {
1037
      case 0: /* SEEK_SET */
1025
      case 0: /* SEEK_SET */
1038
        filep->f_pos = offset;
1026
        filep->f_pos = offset;
1039
        break;
1027
        break;
1040
      case 1: /* SEEK_CUR */
1028
      case 1: /* SEEK_CUR */
1041
        filep->f_pos += offset;
1029
        filep->f_pos += offset;
1042
        break;
1030
        break;
1043
      case 2: /* SEEK_END */
1031
      case 2: /* SEEK_END */
1044
        return -EINVAL;
1032
        return -EINVAL;
1045
      default:
1033
      default:
1046
        return -EINVAL;
1034
        return -EINVAL;
1047
    };
1035
    };
1048
 
1036
 
1049
    return filep->f_pos;
1037
    return filep->f_pos;
1050
}
1038
}
1051
 
1039
 
1052
 
1040
 
1053
 
1041
 
1054
struct file_operations pcivme_fops =
1042
struct file_operations pcivme_fops =
1055
{
1043
{
1056
    .llseek    =    pcivme_lseek,  /* lseek  */
1044
    .llseek    =    pcivme_lseek,  /* lseek  */
1057
    .read    =    pcivme_read,     /* read  */
1045
    .read    =    pcivme_read,     /* read  */
1058
    .write   =    pcivme_write,    /* write */
1046
    .write   =    pcivme_write,    /* write */
1059
//    .compat_ioctl = pcivme_compat_ioctl,  /* ioctl */
1047
//    .compat_ioctl = pcivme_compat_ioctl,  /* ioctl */
1060
    .unlocked_ioctl = pcivme_unlocked_ioctl,  /* ioctl */
1048
    .unlocked_ioctl = pcivme_unlocked_ioctl,  /* ioctl */
1061
    .open    =    pcivme_open,     /* open */
1049
    .open    =    pcivme_open,     /* open */
1062
    .release =    pcivme_release,  /* release */
1050
    .release =    pcivme_release,  /* release */
1063
};
1051
};
1064
 
1052
 
1065
 
1053
 
1066
 
1054
 
1067
                                                                                                                             
1055
                                                                                                                             
1068
                                                                                                                             
1056
                                                                                                                             
1069
                                                                                                                             
1057
                                                                                                                             
1070
 
1058