1 /*
2 * Copyright (C) Eicon Technology Corporation, 2000.
3 *
4 * Eicon File Revision : 1.9
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 */
10
11 #include <linux/fs.h>
12 #undef N_DATA /* Because we have our own definition */
13
14 #include <asm/segment.h>
15 #include <asm/io.h>
16
17 #include "sys.h"
18 #include "idi.h"
19 #include "constant.h"
20 #include "divas.h"
21 #undef ID_MASK
22 #include "pc.h"
23 #include "pr_pc.h"
24
25 #include "adapter.h"
26 #include "uxio.h"
27
28 #include <linux/pci.h>
29 #include <linux/kernel.h>
30 #include <linux/ioport.h>
31
32 struct file_operations Divas_fops;
33 int Divas_major;
34
35 extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
36 unsigned int command, unsigned long arg);
37 extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
38 extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
39 extern int do_open(struct inode *, struct file *);
40 extern int do_release(struct inode *, struct file *);
41
42 int FPGA_Done=0;
43
DivasCardsDiscover(void)44 int DivasCardsDiscover(void)
45 {
46 word wNumCards = 0, wDeviceIndex = 0;
47 byte byBus, byFunc;
48 word wPCIConsultation, PCItmp;
49 dword j, i;
50 unsigned int PCIserial;
51 dia_card_t Card;
52 byte *b;
53
54 while (wDeviceIndex < 10)
55 {
56 wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
57 PCI_DEVICE_ID_EICON_MAESTRAQ,
58 wDeviceIndex,
59 &byBus, &byFunc);
60
61 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
62 {
63
64 dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
65 byte byIRQ;
66
67 printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
68 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
69 dwRAM &= 0xFFC00000;
70
71 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
72 dwDivasIOBase &= 0xFFFFFF00;
73
74 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
75 dwCFG &= 0xFFFFFF00;
76
77 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
78 dwCTL &= 0xFFFFE000;
79
80
81 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
82 /* Retrieve the serial number */
83
84 pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
85
86 for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
87 {
88 pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
89 PCItmp &= 0x8000; // extract done flag
90 }
91
92 pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
93
94
95 Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
96 Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
97 Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
98 Card.io_base=dwDivasIOBase;
99
100 Card.irq = byIRQ;
101
102 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
103 Card.bus_type = DIA_BUS_TYPE_PCI;
104
105 FPGA_Done = 0;
106
107 /* Create four virtual card structures as we want to treat
108 the 4Bri card as 4 Bri cards*/
109 for(i=0;i<4;i++)
110 {
111
112 b=Card.memory[DIVAS_RAM_MEMORY];
113 b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1);
114 DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
115 Card.memory[DIVAS_RAM_MEMORY]=b;
116
117 b = Card.memory[DIVAS_RAM_MEMORY];
118 b += MQ_SM_OFFSET;
119 Card.memory[DIVAS_SHARED_MEMORY] = b;
120
121 Card.bus_num = byBus;
122 Card.func_num = byFunc;
123 Card.slot = -1;
124
125
126 /* Fill in Name */
127 Card.name[0] = 'D';
128 Card.name[1] = 'I';
129 Card.name[2] = 'V';
130 Card.name[3] = 'A';
131 Card.name[4] = 'S';
132 Card.name[5] = 'Q';
133 Card.name[6] = '0' + i;
134 Card.name[7] = '\0';
135
136 Card.serial = PCIserial;
137
138 Card.card_id = wNumCards;
139
140 if (DivasCardNew(&Card) != 0)
141 {
142 // Force for loop to terminate
143 i = 4;
144 continue;
145 }
146 wNumCards++;
147
148 }//for
149 }
150 wDeviceIndex++;
151 }
152
153 wDeviceIndex = 0;
154
155 while (wDeviceIndex < 10)
156 {
157 wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
158 PCI_DEVICE_ID_EICON_MAESTRA,
159 wDeviceIndex,
160 &byBus, &byFunc);
161
162 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
163 {
164 dword dwPLXIOBase, dwDivasIOBase;
165 byte byIRQ;
166
167 printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
168 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
169 dwPLXIOBase &= 0xFFFFFF80;
170
171 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
172 dwDivasIOBase &= 0xFFFFFFFC;
173
174 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
175
176 Card.card_id = wNumCards;
177 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
178 Card.bus_type = DIA_BUS_TYPE_PCI;
179 Card.irq = byIRQ;
180 Card.reset_base = dwPLXIOBase;
181 Card.io_base = dwDivasIOBase;
182 Card.bus_num = byBus;
183 Card.func_num = byFunc;
184 Card.slot = -1;
185 Card.name[0] = 'D';
186 Card.name[1] = 'I';
187 Card.name[2] = 'V';
188 Card.name[3] = 'A';
189 Card.name[4] = 'S';
190 Card.name[5] = 'B';
191 Card.name[6] = '\0';
192
193 if (check_region(Card.io_base, 0x20))
194 {
195 printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
196 wDeviceIndex++;
197 continue;
198 }
199
200 if (check_region(Card.reset_base, 0x80))
201 {
202 printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
203 wDeviceIndex++;
204 continue;
205 }
206
207 if (DivasCardNew(&Card) != 0)
208 {
209 wDeviceIndex++;
210 continue;
211 }
212 wNumCards++;
213 }
214
215 wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
216 PCI_DEVICE_ID_EICON_MAESTRAQ_U,
217 wDeviceIndex,
218 &byBus, &byFunc);
219
220 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
221 {
222 dword dwPLXIOBase, dwDivasIOBase;
223 byte byIRQ;
224
225 printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
226
227 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
228 dwPLXIOBase &= 0xFFFFFF80;
229
230 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
231 dwDivasIOBase &= 0xFFFFFFFC;
232
233 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
234
235 Card.card_id = wNumCards;
236 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
237 Card.bus_type = DIA_BUS_TYPE_PCI;
238 Card.irq = byIRQ;
239 Card.reset_base = dwPLXIOBase;
240 Card.io_base = dwDivasIOBase;
241 Card.bus_num = byBus;
242 Card.func_num = byFunc;
243 Card.slot = -1;
244 Card.name[0] = 'D';
245 Card.name[1] = 'I';
246 Card.name[2] = 'V';
247 Card.name[3] = 'A';
248 Card.name[4] = 'S';
249 Card.name[5] = 'B';
250 Card.name[6] = '\0';
251
252 if (check_region(Card.io_base, 0x20))
253 {
254 printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
255 wDeviceIndex++;
256 continue;
257 }
258
259 if (check_region(Card.reset_base, 0x80))
260 {
261 printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
262 wDeviceIndex++;
263 continue;
264 }
265
266 if (DivasCardNew(&Card) != 0)
267 {
268 wDeviceIndex++;
269 continue;
270 }
271 wNumCards++;
272 }
273
274 wDeviceIndex++;
275 }
276
277 wDeviceIndex = 0;
278
279 while (wDeviceIndex < 10)
280 {
281 wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
282 PCI_DEVICE_ID_EICON_MAESTRAP,
283 wDeviceIndex,
284 &byBus, &byFunc);
285
286 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
287 {
288 dword dwRAM, dwREG, dwCFG;
289 byte byIRQ;
290
291 printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
292
293 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
294 dwRAM &= 0xFFFFF000;
295
296 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
297 dwREG &= 0xFFFFF000;
298
299 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
300 dwCFG &= 0xFFFFF000;
301
302 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
303
304 Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
305 Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
306 Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
307 Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
308
309 /* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
310 dwPLXIOBase &= 0xFFFFFFFc;
311
312 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
313 dwDivasIOBase &= 0xFFFFFF80;
314
315 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
316 */
317 Card.card_id = wNumCards;
318 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
319 Card.bus_type = DIA_BUS_TYPE_PCI;
320 Card.irq = byIRQ;
321 /* Card.reset_base = dwPLXIOBase;
322 Card.io_base = dwDivasIOBase;*/
323 Card.bus_num = byBus;
324 Card.func_num = byFunc;
325 Card.slot = -1;
326 Card.name[0] = 'D';
327 Card.name[1] = 'I';
328 Card.name[2] = 'V';
329 Card.name[3] = 'A';
330 Card.name[4] = 'S';
331 Card.name[5] = 'P';
332 Card.name[6] = '\0';
333
334 if (DivasCardNew(&Card) != 0)
335 {
336 wDeviceIndex++;
337 continue;
338 }
339 wNumCards++;
340 }
341
342 wDeviceIndex++;
343 }
344
345
346 printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
347
348 if(wNumCards == 0)
349 {
350 return -1;
351 }
352
353 Divas_fops.ioctl = do_ioctl;
354 Divas_fops.poll = do_poll;
355 Divas_fops.read = do_read;
356 Divas_fops.open = do_open;
357 Divas_fops.release = do_release;
358
359 Divas_major = register_chrdev(0, "Divas", &Divas_fops);
360
361 if (Divas_major < 0)
362 {
363 printk(KERN_WARNING "Divas: Unable to register character driver\n");
364 return -1;
365 }
366
367 return 0;
368 }
369
370 /* Error return -1 */
DivasConfigGet(dia_card_t * card)371 int DivasConfigGet(dia_card_t *card)
372 {
373 /* Retrieve Config from O/S? Not in Linux */
374 return 0;
375 }
376
DivasConfig(card_t * card,dia_config_t * config)377 dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
378 {
379 /* If config retrieved from OS then copy the data into a dia_config_t structure here
380 and return the pointer here. If the config 'came from above' then just
381
382 return config;
383 */
384
385 return config;
386 }
387
388