]>
Commit | Line | Data |
---|---|---|
c995fe94 | 1 | /* |
15d8826a GKH |
2 | * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. |
3 | * | |
4 | * ADDI-DATA GmbH | |
5 | * Dieselstrasse 3 | |
6 | * D-77833 Ottersweier | |
7 | * Tel: +19(0)7223/9493-0 | |
8 | * Fax: +49(0)7223/9493-92 | |
9 | * http://www.addi-data-com | |
10 | * info@addi-data.com | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the Free | |
14 | * Software Foundation; either version 2 of the License, or (at your option) | |
15 | * any later version. | |
16 | */ | |
17 | ||
18 | /* Header file for AMCC s 5933 */ | |
c995fe94 ADG |
19 | |
20 | #ifndef _AMCC_S5933_H_ | |
21 | #define _AMCC_S5933_H_ | |
22 | ||
23 | #include "../../comedidev.h" | |
24 | ||
25 | #include "../comedi_pci.h" | |
26 | ||
27 | #ifdef PCI_SUPPORT_VER1 | |
28 | #error No support for 2.1.55 and older | |
29 | #endif | |
30 | ||
15d8826a GKH |
31 | /* written on base0 */ |
32 | #define FIFO_ADVANCE_ON_BYTE_2 0x20000000 | |
c995fe94 | 33 | |
15d8826a GKH |
34 | /* added for step 6 dma written on base2 */ |
35 | #define AMWEN_ENABLE 0x02 | |
c995fe94 | 36 | |
15d8826a | 37 | #define A2P_FIFO_WRITE_ENABLE 0x01 |
c995fe94 | 38 | |
15d8826a GKH |
39 | /* for transfer count enable bit */ |
40 | #define AGCSTS_TC_ENABLE 0x10000000 | |
c995fe94 | 41 | |
15d8826a GKH |
42 | /* |
43 | * ADDON RELATED ADDITIONS | |
44 | */ | |
45 | /* Constant */ | |
46 | #define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 | |
47 | #define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 | |
48 | #define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L | |
49 | #define APCI3120_AMWEN_ENABLE 0x02 | |
50 | #define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 | |
51 | #define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L | |
52 | #define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L | |
53 | #define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L | |
54 | #define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 | |
55 | #define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 | |
56 | #define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 | |
57 | ||
58 | /* ADD_ON ::: this needed since apci supports 16 bit interface to add on */ | |
59 | #define APCI3120_ADD_ON_AGCSTS_LOW 0x3C | |
60 | #define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2) | |
61 | #define APCI3120_ADD_ON_MWAR_LOW 0x24 | |
62 | #define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2) | |
63 | #define APCI3120_ADD_ON_MWTC_LOW 0x058 | |
64 | #define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2) | |
65 | ||
66 | /* AMCC */ | |
67 | #define APCI3120_AMCC_OP_MCSR 0x3C | |
68 | #define APCI3120_AMCC_OP_REG_INTCSR 0x38 | |
c995fe94 | 69 | |
15d8826a GKH |
70 | /* |
71 | * AMCC Operation Register Offsets - PCI | |
72 | */ | |
73 | #define AMCC_OP_REG_OMB1 0x00 | |
74 | #define AMCC_OP_REG_OMB2 0x04 | |
75 | #define AMCC_OP_REG_OMB3 0x08 | |
76 | #define AMCC_OP_REG_OMB4 0x0c | |
77 | #define AMCC_OP_REG_IMB1 0x10 | |
78 | #define AMCC_OP_REG_IMB2 0x14 | |
79 | #define AMCC_OP_REG_IMB3 0x18 | |
80 | #define AMCC_OP_REG_IMB4 0x1c | |
81 | #define AMCC_OP_REG_FIFO 0x20 | |
82 | #define AMCC_OP_REG_MWAR 0x24 | |
83 | #define AMCC_OP_REG_MWTC 0x28 | |
84 | #define AMCC_OP_REG_MRAR 0x2c | |
85 | #define AMCC_OP_REG_MRTC 0x30 | |
86 | #define AMCC_OP_REG_MBEF 0x34 | |
87 | #define AMCC_OP_REG_INTCSR 0x38 | |
74b894e5 | 88 | /* int source */ |
15d8826a GKH |
89 | #define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) |
90 | /* FIFO ctrl */ | |
91 | #define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) | |
92 | #define AMCC_OP_REG_MCSR 0x3c | |
93 | /* Data in byte 2 */ | |
94 | #define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) | |
95 | /* Command in byte 3 */ | |
96 | #define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) | |
c995fe94 | 97 | |
15d8826a GKH |
98 | #define AMCC_FIFO_DEPTH_DWORD 8 |
99 | #define AMCC_FIFO_DEPTH_BYTES (8 * sizeof(u32)) | |
c995fe94 | 100 | |
15d8826a GKH |
101 | /* |
102 | * AMCC Operation Registers Size - PCI | |
103 | */ | |
104 | #define AMCC_OP_REG_SIZE 64 /* in bytes */ | |
c995fe94 | 105 | |
15d8826a GKH |
106 | /* |
107 | * AMCC Operation Register Offsets - Add-on | |
108 | */ | |
109 | #define AMCC_OP_REG_AIMB1 0x00 | |
110 | #define AMCC_OP_REG_AIMB2 0x04 | |
111 | #define AMCC_OP_REG_AIMB3 0x08 | |
112 | #define AMCC_OP_REG_AIMB4 0x0c | |
113 | #define AMCC_OP_REG_AOMB1 0x10 | |
114 | #define AMCC_OP_REG_AOMB2 0x14 | |
115 | #define AMCC_OP_REG_AOMB3 0x18 | |
116 | #define AMCC_OP_REG_AOMB4 0x1c | |
117 | #define AMCC_OP_REG_AFIFO 0x20 | |
118 | #define AMCC_OP_REG_AMWAR 0x24 | |
119 | #define AMCC_OP_REG_APTA 0x28 | |
120 | #define AMCC_OP_REG_APTD 0x2c | |
121 | #define AMCC_OP_REG_AMRAR 0x30 | |
122 | #define AMCC_OP_REG_AMBEF 0x34 | |
123 | #define AMCC_OP_REG_AINT 0x38 | |
124 | #define AMCC_OP_REG_AGCSTS 0x3c | |
125 | #define AMCC_OP_REG_AMWTC 0x58 | |
126 | #define AMCC_OP_REG_AMRTC 0x5c | |
c995fe94 | 127 | |
15d8826a GKH |
128 | /* |
129 | * AMCC - Add-on General Control/Status Register | |
130 | */ | |
c995fe94 ADG |
131 | #define AGCSTS_CONTROL_MASK 0xfffff000 |
132 | #define AGCSTS_NV_ACC_MASK 0xe0000000 | |
133 | #define AGCSTS_RESET_MASK 0x0e000000 | |
134 | #define AGCSTS_NV_DA_MASK 0x00ff0000 | |
135 | #define AGCSTS_BIST_MASK 0x0000f000 | |
136 | #define AGCSTS_STATUS_MASK 0x000000ff | |
137 | #define AGCSTS_TCZERO_MASK 0x000000c0 | |
138 | #define AGCSTS_FIFO_ST_MASK 0x0000003f | |
139 | ||
140 | #define AGCSTS_RESET_MBFLAGS 0x08000000 | |
141 | #define AGCSTS_RESET_P2A_FIFO 0x04000000 | |
142 | #define AGCSTS_RESET_A2P_FIFO 0x02000000 | |
143 | #define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) | |
144 | ||
145 | #define AGCSTS_A2P_TCOUNT 0x00000080 | |
146 | #define AGCSTS_P2A_TCOUNT 0x00000040 | |
147 | ||
148 | #define AGCSTS_FS_P2A_EMPTY 0x00000020 | |
149 | #define AGCSTS_FS_P2A_HALF 0x00000010 | |
150 | #define AGCSTS_FS_P2A_FULL 0x00000008 | |
151 | ||
152 | #define AGCSTS_FS_A2P_EMPTY 0x00000004 | |
153 | #define AGCSTS_FS_A2P_HALF 0x00000002 | |
154 | #define AGCSTS_FS_A2P_FULL 0x00000001 | |
155 | ||
15d8826a GKH |
156 | /* |
157 | * AMCC - Add-on Interrupt Control/Status Register | |
158 | */ | |
c995fe94 ADG |
159 | #define AINT_INT_MASK 0x00ff0000 |
160 | #define AINT_SEL_MASK 0x0000ffff | |
161 | #define AINT_IS_ENSEL_MASK 0x00001f1f | |
162 | ||
163 | #define AINT_INT_ASSERTED 0x00800000 | |
164 | #define AINT_BM_ERROR 0x00200000 | |
165 | #define AINT_BIST_INT 0x00100000 | |
166 | ||
167 | #define AINT_RT_COMPLETE 0x00080000 | |
168 | #define AINT_WT_COMPLETE 0x00040000 | |
169 | ||
170 | #define AINT_OUT_MB_INT 0x00020000 | |
171 | #define AINT_IN_MB_INT 0x00010000 | |
172 | ||
173 | #define AINT_READ_COMPL 0x00008000 | |
174 | #define AINT_WRITE_COMPL 0x00004000 | |
175 | ||
176 | #define AINT_OMB_ENABLE 0x00001000 | |
177 | #define AINT_OMB_SELECT 0x00000c00 | |
178 | #define AINT_OMB_BYTE 0x00000300 | |
179 | ||
180 | #define AINT_IMB_ENABLE 0x00000010 | |
181 | #define AINT_IMB_SELECT 0x0000000c | |
182 | #define AINT_IMB_BYTE 0x00000003 | |
183 | ||
184 | /* Enable Bus Mastering */ | |
185 | #define EN_A2P_TRANSFERS 0x00000400 | |
186 | /* FIFO Flag Reset */ | |
187 | #define RESET_A2P_FLAGS 0x04000000L | |
188 | /* FIFO Relative Priority */ | |
189 | #define A2P_HI_PRIORITY 0x00000100L | |
190 | /* Identify Interrupt Sources */ | |
191 | #define ANY_S593X_INT 0x00800000L | |
192 | #define READ_TC_INT 0x00080000L | |
193 | #define WRITE_TC_INT 0x00040000L | |
194 | #define IN_MB_INT 0x00020000L | |
195 | #define MASTER_ABORT_INT 0x00100000L | |
196 | #define TARGET_ABORT_INT 0x00200000L | |
197 | #define BUS_MASTER_INT 0x00200000L | |
198 | ||
199 | /****************************************************************************/ | |
200 | ||
201 | struct pcilst_struct { | |
202 | struct pcilst_struct *next; | |
203 | int used; | |
204 | struct pci_dev *pcidev; | |
205 | unsigned short vendor; | |
206 | unsigned short device; | |
207 | unsigned char pci_bus; | |
208 | unsigned char pci_slot; | |
209 | unsigned char pci_func; | |
210 | resource_size_t io_addr[5]; | |
211 | unsigned int irq; | |
212 | }; | |
213 | ||
15d8826a | 214 | /* ptr to root list of all amcc devices */ |
ad2d4714 | 215 | static struct pcilst_struct *amcc_devices; |
c995fe94 ADG |
216 | |
217 | static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 }; | |
218 | ||
219 | /****************************************************************************/ | |
220 | ||
221 | void v_pci_card_list_init(unsigned short pci_vendor, char display); | |
222 | void v_pci_card_list_cleanup(unsigned short pci_vendor); | |
223 | struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, | |
15d8826a GKH |
224 | unsigned short |
225 | device_id); | |
c995fe94 | 226 | int i_find_free_pci_card_by_position(unsigned short vendor_id, |
15d8826a GKH |
227 | unsigned short device_id, |
228 | unsigned short pci_bus, | |
229 | unsigned short pci_slot, | |
230 | struct pcilst_struct **card); | |
c995fe94 | 231 | struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, |
15d8826a GKH |
232 | unsigned short device_id, |
233 | unsigned short pci_bus, | |
234 | unsigned short pci_slot, | |
235 | int i_Master); | |
c995fe94 ADG |
236 | |
237 | int pci_card_alloc(struct pcilst_struct *amcc, int master); | |
238 | int i_pci_card_free(struct pcilst_struct *amcc); | |
239 | void v_pci_card_list_display(void); | |
240 | int i_pci_card_data(struct pcilst_struct *amcc, | |
15d8826a GKH |
241 | unsigned char *pci_bus, unsigned char *pci_slot, |
242 | unsigned char *pci_func, resource_size_t * io_addr, | |
243 | unsigned int *irq); | |
c995fe94 ADG |
244 | |
245 | /****************************************************************************/ | |
246 | ||
247 | /* build list of amcc cards in this system */ | |
248 | void v_pci_card_list_init(unsigned short pci_vendor, char display) | |
249 | { | |
250 | struct pci_dev *pcidev; | |
251 | struct pcilst_struct *amcc, *last; | |
252 | int i; | |
253 | int i_Count = 0; | |
254 | amcc_devices = NULL; | |
255 | last = NULL; | |
256 | ||
257 | for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); | |
15d8826a GKH |
258 | pcidev != NULL; |
259 | pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { | |
c995fe94 ADG |
260 | for (i_Count = 0; i_Count < 2; i_Count++) { |
261 | pci_vendor = i_ADDIDATADeviceID[i_Count]; | |
262 | if (pcidev->vendor == pci_vendor) { | |
7a6cb0d5 | 263 | amcc = kzalloc(sizeof(*amcc), GFP_KERNEL); |
a2279ae5 RK |
264 | if (amcc == NULL) |
265 | continue; | |
266 | ||
c995fe94 | 267 | amcc->pcidev = pcidev; |
15d8826a | 268 | if (last) |
c995fe94 | 269 | last->next = amcc; |
15d8826a | 270 | else |
c995fe94 | 271 | amcc_devices = amcc; |
c995fe94 ADG |
272 | last = amcc; |
273 | ||
274 | amcc->vendor = pcidev->vendor; | |
275 | amcc->device = pcidev->device; | |
276 | amcc->pci_bus = pcidev->bus->number; | |
277 | amcc->pci_slot = PCI_SLOT(pcidev->devfn); | |
278 | amcc->pci_func = PCI_FUNC(pcidev->devfn); | |
279 | /* Note: resources may be invalid if PCI device | |
280 | * not enabled, but they are corrected in | |
281 | * pci_card_alloc. */ | |
282 | for (i = 0; i < 5; i++) | |
283 | amcc->io_addr[i] = | |
15d8826a | 284 | pci_resource_start(pcidev, i); |
c995fe94 ADG |
285 | amcc->irq = pcidev->irq; |
286 | ||
287 | } | |
288 | } | |
289 | } | |
290 | ||
291 | if (display) | |
292 | v_pci_card_list_display(); | |
293 | } | |
294 | ||
295 | /****************************************************************************/ | |
296 | /* free up list of amcc cards in this system */ | |
297 | void v_pci_card_list_cleanup(unsigned short pci_vendor) | |
298 | { | |
299 | struct pcilst_struct *amcc, *next; | |
300 | ||
301 | for (amcc = amcc_devices; amcc; amcc = next) { | |
302 | next = amcc->next; | |
303 | kfree(amcc); | |
304 | } | |
305 | ||
306 | amcc_devices = NULL; | |
307 | } | |
308 | ||
309 | /****************************************************************************/ | |
310 | /* find first unused card with this device_id */ | |
311 | struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, | |
15d8826a | 312 | unsigned short device_id) |
c995fe94 ADG |
313 | { |
314 | struct pcilst_struct *amcc, *next; | |
315 | ||
316 | for (amcc = amcc_devices; amcc; amcc = next) { | |
317 | next = amcc->next; | |
318 | if ((!amcc->used) && (amcc->device == device_id) | |
15d8826a | 319 | && (amcc->vendor == vendor_id)) |
c995fe94 ADG |
320 | return amcc; |
321 | ||
322 | } | |
323 | ||
324 | return NULL; | |
325 | } | |
326 | ||
327 | /****************************************************************************/ | |
328 | /* find card on requested position */ | |
329 | int i_find_free_pci_card_by_position(unsigned short vendor_id, | |
15d8826a GKH |
330 | unsigned short device_id, |
331 | unsigned short pci_bus, | |
332 | unsigned short pci_slot, | |
333 | struct pcilst_struct **card) | |
c995fe94 ADG |
334 | { |
335 | struct pcilst_struct *amcc, *next; | |
336 | ||
337 | *card = NULL; | |
338 | for (amcc = amcc_devices; amcc; amcc = next) { | |
339 | next = amcc->next; | |
340 | if ((amcc->vendor == vendor_id) && (amcc->device == device_id) | |
15d8826a GKH |
341 | && (amcc->pci_bus == pci_bus) |
342 | && (amcc->pci_slot == pci_slot)) { | |
c995fe94 ADG |
343 | if (!(amcc->used)) { |
344 | *card = amcc; | |
15d8826a | 345 | return 0; /* ok, card is found */ |
c995fe94 | 346 | } else { |
5f74ea14 | 347 | printk(" - \nCard on requested position is used b:s %d:%d!\n", |
15d8826a GKH |
348 | pci_bus, pci_slot); |
349 | return 2; /* card exist but is used */ | |
c995fe94 ADG |
350 | } |
351 | } | |
352 | } | |
353 | ||
15d8826a GKH |
354 | /* no card found */ |
355 | return 1; | |
c995fe94 ADG |
356 | } |
357 | ||
358 | /****************************************************************************/ | |
359 | /* mark card as used */ | |
360 | int pci_card_alloc(struct pcilst_struct *amcc, int master) | |
361 | { | |
362 | int i; | |
363 | ||
364 | if (!amcc) | |
365 | return -1; | |
366 | ||
367 | if (amcc->used) | |
368 | return 1; | |
369 | if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933")) | |
370 | return -1; | |
371 | /* Resources will be accurate now. */ | |
372 | for (i = 0; i < 5; i++) | |
373 | amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i); | |
374 | if (master) | |
375 | pci_set_master(amcc->pcidev); | |
376 | amcc->used = 1; | |
377 | ||
378 | return 0; | |
379 | } | |
380 | ||
381 | /****************************************************************************/ | |
382 | /* mark card as free */ | |
383 | int i_pci_card_free(struct pcilst_struct *amcc) | |
384 | { | |
385 | if (!amcc) | |
386 | return -1; | |
387 | ||
388 | if (!amcc->used) | |
389 | return 1; | |
390 | amcc->used = 0; | |
391 | comedi_pci_disable(amcc->pcidev); | |
392 | return 0; | |
393 | } | |
394 | ||
395 | /****************************************************************************/ | |
396 | /* display list of found cards */ | |
397 | void v_pci_card_list_display(void) | |
398 | { | |
399 | struct pcilst_struct *amcc, *next; | |
400 | ||
15d8826a GKH |
401 | printk(KERN_DEBUG "List of pci cards\n"); |
402 | printk(KERN_DEBUG "bus:slot:func vendor device io_amcc io_daq irq used\n"); | |
c995fe94 ADG |
403 | |
404 | for (amcc = amcc_devices; amcc; amcc = next) { | |
405 | next = amcc->next; | |
15d8826a GKH |
406 | printk |
407 | ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n", | |
408 | amcc->pci_bus, amcc->pci_slot, amcc->pci_func, | |
409 | amcc->vendor, amcc->device, | |
410 | (unsigned long long)amcc->io_addr[0], | |
411 | (unsigned long long)amcc->io_addr[2], amcc->irq, | |
412 | amcc->used); | |
c995fe94 ADG |
413 | |
414 | } | |
415 | } | |
416 | ||
417 | /****************************************************************************/ | |
418 | /* return all card information for driver */ | |
419 | int i_pci_card_data(struct pcilst_struct *amcc, | |
15d8826a GKH |
420 | unsigned char *pci_bus, unsigned char *pci_slot, |
421 | unsigned char *pci_func, resource_size_t * io_addr, | |
422 | unsigned int *irq) | |
c995fe94 ADG |
423 | { |
424 | int i; | |
425 | ||
426 | if (!amcc) | |
427 | return -1; | |
428 | *pci_bus = amcc->pci_bus; | |
429 | *pci_slot = amcc->pci_slot; | |
430 | *pci_func = amcc->pci_func; | |
431 | for (i = 0; i < 5; i++) | |
432 | io_addr[i] = amcc->io_addr[i]; | |
433 | *irq = amcc->irq; | |
434 | return 0; | |
435 | } | |
436 | ||
437 | /****************************************************************************/ | |
438 | /* select and alloc card */ | |
439 | struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, | |
15d8826a GKH |
440 | unsigned short device_id, |
441 | unsigned short pci_bus, | |
442 | unsigned short pci_slot, | |
443 | int i_Master) | |
c995fe94 ADG |
444 | { |
445 | struct pcilst_struct *card; | |
446 | ||
15d8826a GKH |
447 | if ((pci_bus < 1) & (pci_slot < 1)) { |
448 | /* use autodetection */ | |
449 | card = ptr_find_free_pci_card_by_device(vendor_id, device_id); | |
450 | if (card == NULL) { | |
5f74ea14 | 451 | printk(" - Unused card not found in system!\n"); |
c995fe94 ADG |
452 | return NULL; |
453 | } | |
454 | } else { | |
455 | switch (i_find_free_pci_card_by_position(vendor_id, device_id, | |
15d8826a GKH |
456 | pci_bus, pci_slot, |
457 | &card)) { | |
c995fe94 | 458 | case 1: |
5f74ea14 | 459 | printk(" - Card not found on requested position b:s %d:%d!\n", |
15d8826a | 460 | pci_bus, pci_slot); |
c995fe94 ADG |
461 | return NULL; |
462 | case 2: | |
5f74ea14 | 463 | printk(" - Card on requested position is used b:s %d:%d!\n", |
15d8826a | 464 | pci_bus, pci_slot); |
c995fe94 ADG |
465 | return NULL; |
466 | } | |
467 | } | |
468 | ||
469 | if (pci_card_alloc(card, i_Master) != 0) { | |
5f74ea14 | 470 | printk(" - Can't allocate card!\n"); |
c995fe94 ADG |
471 | return NULL; |
472 | ||
473 | } | |
474 | ||
475 | return card; | |
476 | } | |
477 | #endif |