4 * Copyright (C) Eicon Technology Corporation, 2000.
6 * This source file is supplied for the exclusive use with Eicon
7 * Technology Corporation's range of DIVA Server Adapters.
9 * Eicon File Revision : 1.9
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #undef N_DATA /* Because we have our own definition */
31 #include <asm/segment.h>
45 #include <linux/pci.h>
46 #include <linux/kernel.h>
47 #include <linux/ioport.h>
49 #define HW_ID_EICON_PCI 0x1133
50 #define HW_ID_DIVA_SERVER_P 0xE014
51 #define HW_ID_DIVA_SERVER_B_ST 0xE010
52 #define HW_ID_DIVA_SERVER_B_U 0xE013
53 #define HW_ID_DIVA_SERVER_Q 0xE012
55 struct file_operations Divas_fops;
58 extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
59 unsigned int command, unsigned long arg);
60 extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
61 extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
62 extern int do_open(struct inode *, struct file *);
63 extern int do_release(struct inode *, struct file *);
67 int DivasCardsDiscover(void)
69 word wNumCards = 0, wDeviceIndex = 0;
71 word wPCIConsultation, PCItmp;
73 unsigned int PCIserial;
77 while (wDeviceIndex < 10)
79 wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
84 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
87 dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
90 printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
91 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
94 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
95 dwDivasIOBase &= 0xFFFFFF00;
97 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
100 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
104 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
105 /* Retrieve the serial number */
107 pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
109 for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
111 pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
112 PCItmp &= 0x8000; // extract done flag
115 pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
118 Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
119 Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
120 Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
121 Card.io_base=dwDivasIOBase;
125 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
126 Card.bus_type = DIA_BUS_TYPE_PCI;
130 /* Create four virtual card structures as we want to treat
131 the 4Bri card as 4 Bri cards*/
135 b=Card.memory[DIVAS_RAM_MEMORY];
136 b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1);
137 DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
138 Card.memory[DIVAS_RAM_MEMORY]=b;
140 b = Card.memory[DIVAS_RAM_MEMORY];
142 Card.memory[DIVAS_SHARED_MEMORY] = b;
144 Card.bus_num = byBus;
145 Card.func_num = byFunc;
156 Card.name[6] = '0' + i;
159 Card.serial = PCIserial;
161 Card.card_id = wNumCards;
163 if (DivasCardNew(&Card) != 0)
165 // Force for loop to terminate
178 while (wDeviceIndex < 10)
180 wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
181 HW_ID_DIVA_SERVER_B_ST,
185 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
187 dword dwPLXIOBase, dwDivasIOBase;
190 printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
191 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
192 dwPLXIOBase &= 0xFFFFFF80;
194 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
195 dwDivasIOBase &= 0xFFFFFFFC;
197 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
199 Card.card_id = wNumCards;
200 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
201 Card.bus_type = DIA_BUS_TYPE_PCI;
203 Card.reset_base = dwPLXIOBase;
204 Card.io_base = dwDivasIOBase;
205 Card.bus_num = byBus;
206 Card.func_num = byFunc;
216 if (check_region(Card.io_base, 0x20))
218 printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
223 if (check_region(Card.reset_base, 0x80))
225 printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
230 if (DivasCardNew(&Card) != 0)
238 wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
239 HW_ID_DIVA_SERVER_B_U,
243 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
245 dword dwPLXIOBase, dwDivasIOBase;
248 printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
250 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
251 dwPLXIOBase &= 0xFFFFFF80;
253 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
254 dwDivasIOBase &= 0xFFFFFFFC;
256 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
258 Card.card_id = wNumCards;
259 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
260 Card.bus_type = DIA_BUS_TYPE_PCI;
262 Card.reset_base = dwPLXIOBase;
263 Card.io_base = dwDivasIOBase;
264 Card.bus_num = byBus;
265 Card.func_num = byFunc;
275 if (check_region(Card.io_base, 0x20))
277 printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
282 if (check_region(Card.reset_base, 0x80))
284 printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
289 if (DivasCardNew(&Card) != 0)
302 while (wDeviceIndex < 10)
304 wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
309 if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
311 dword dwRAM, dwREG, dwCFG;
314 printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
316 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
319 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
322 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
325 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
327 Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
328 Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
329 Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
330 Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
332 /* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
333 dwPLXIOBase &= 0xFFFFFFFc;
335 pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
336 dwDivasIOBase &= 0xFFFFFF80;
338 pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
340 Card.card_id = wNumCards;
341 Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
342 Card.bus_type = DIA_BUS_TYPE_PCI;
344 /* Card.reset_base = dwPLXIOBase;
345 Card.io_base = dwDivasIOBase;*/
346 Card.bus_num = byBus;
347 Card.func_num = byFunc;
357 if (DivasCardNew(&Card) != 0)
369 printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
376 Divas_fops.ioctl = do_ioctl;
377 Divas_fops.poll = do_poll;
378 Divas_fops.read = do_read;
379 Divas_fops.open = do_open;
380 Divas_fops.release = do_release;
382 Divas_major = register_chrdev(0, "Divas", &Divas_fops);
386 printk(KERN_WARNING "Divas: Unable to register character driver\n");
393 /* Error return -1 */
394 int DivasConfigGet(dia_card_t *card)
396 /* Retrieve Config from O/S? Not in Linux */
400 dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
402 /* If config retrieved from OS then copy the data into a dia_config_t structure here
403 and return the pointer here. If the config 'came from above' then just