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