patch-2.2.19 linux/drivers/isdn/hisax/bkm_a8.c

Next file: linux/drivers/isdn/hisax/bkm_ax.h
Previous file: linux/drivers/isdn/hisax/bkm_a4t.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.9 1999/12/19 13:09:41 keil Exp $
+/* $Id: bkm_a8.c,v 1.14.6.3 2001/02/13 10:33:58 kai Exp $
  * bkm_a8.c     low level stuff for Scitel Quadro (4*S0, passive)
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -6,69 +6,29 @@
  *
  * Author       Roland Klabunde (R.Klabunde@Berkom.de)
  *
- * $Log: bkm_a8.c,v $
- * Revision 1.9  1999/12/19 13:09:41  keil
- * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
- * signal proof delays
- *
- * Revision 1.8  1999/09/04 06:20:05  keil
- * Changes from kernel set_current_state()
- *
- * Revision 1.7  1999/08/22 20:26:58  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.6  1999/08/11 21:01:24  keil
- * new PCI codefix
- *
- * Revision 1.5  1999/08/10 16:01:48  calle
- * struct pci_dev changed in 2.3.13. Made the necessary changes.
- *
- * Revision 1.4  1999/07/14 11:43:15  keil
- * correct PCI_SUBSYSTEM_VENDOR_ID
- *
- * Revision 1.3  1999/07/12 21:04:59  keil
- * fix race in IRQ handling
- * added watchdog for lost IRQs
- *
- * Revision 1.2  1999/07/01 08:07:54  keil
- * Initial version
- *
+ * This file is (c) under GNU PUBLIC LICENSE
  *
  */
 #define __NO_VERSION__
 
 #include <linux/config.h>
+#include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
 #include "ipac.h"
 #include "hscx.h"
 #include "isdnl1.h"
-#include "bkm_ax.h"
 #include <linux/pci.h>
+#include <linux/isdn_compat.h>
+#include "bkm_ax.h"
+
+#if CONFIG_PCI
 
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
 extern const char *CardType[];
 
-const char sct_quadro_revision[] = "$Revision: 1.9 $";
-
-/* To survive the startup phase */
-typedef struct {
-	u_int active;		/* true/false */
-	u_int base;		/* ipac base address */
-} IPAC_STATE;
-
-static IPAC_STATE ipac_state[4 + 1] __initdata =
-{
-	{0, 0},			/* dummy */
-	{0, 0},			/* SCT_1 */
-	{0, 0},			/* SCT_2 */
-	{0, 0},			/* SCT_3 */
-	{0, 0}			/* SCT_4 */
-};
+const char sct_quadro_revision[] = "$Revision: 1.14.6.3 $";
 
 static const char *sct_quadro_subtypes[] =
 {
@@ -167,19 +127,13 @@
 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value);
 }
 
-/* Check whether the specified ipac is already active or not */
-static int
-is_ipac_active(u_int ipac_nr)
-{
-	return (ipac_state[ipac_nr].active);
-}
-
 /* Set the specific ipac to active */
 static void
-set_ipac_active(u_int ipac_nr, u_int active)
+set_ipac_active(struct IsdnCardState *cs, u_int active)
 {
-	/* set activation state */
-	ipac_state[ipac_nr].active = active;
+	/* set irq mask */
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK,
+		active ? 0xc0 : 0xff);
 }
 
 /*
@@ -202,13 +156,14 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val, icnt = 5;
-	int i;
+
 	if (!cs) {
 		printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n");
 		return;
 	}
 	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
-
+	if (!(ista & 0x3f)) /* not this IPAC */
+		return;
       Start_IPAC:
 	if (cs->debug & L1_DEB_IPAC)
 		debugl1(cs, "IPAC ISTA %02X", ista);
@@ -245,30 +200,15 @@
 		       sct_quadro_subtypes[cs->subtyp]);
 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
-
-	/* Read out all interrupt sources from currently not active ipacs */
-	/* "Handle" all interrupts from currently not active ipac by reading the regs */
-	for (i = SCT_1; i <= SCT_4; i++)
-		if (!is_ipac_active(i)) {
-			u_int base = ipac_state[i].base;
-			if (readreg(base, base + 4, 0xC1)) {
-				readreg(base, base + 4, 0xA0);
-				readreg(base, base + 4, 0xA4);
-				readreg(base, base + 4, 0x20);
-				readreg(base, base + 4, 0x24);
-				readreg(base, base + 4, 0x60);
-				readreg(base, base + 4, 0x64);
-				readreg(base, base + 4, 0xC1);
-				readreg(base, base + 4, ISAC_CIR0 + 0x80);
-			}
-		}
 }
 
 
 void
 release_io_sct_quadro(struct IsdnCardState *cs)
 {
-	/* ?? */
+	release_region(cs->hw.ax.base & 0xffffffc0, 256);
+	if (cs->subtyp == SCT_1)
+		release_region(cs->hw.ax.plx_adr, 256);
 }
 
 static void
@@ -278,11 +218,6 @@
 		if (bEnable)
 			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
 		else
-			/* Issue general di only if no ipac is active */
-			if (!is_ipac_active(SCT_1) &&
-			    !is_ipac_active(SCT_2) &&
-			    !is_ipac_active(SCT_3) &&
-			    !is_ipac_active(SCT_4))
 			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
 	}
 }
@@ -292,26 +227,17 @@
 {
 	long flags;
 
-	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
-		if (!is_ipac_active(SCT_1) &&
-		    !is_ipac_active(SCT_2) &&
-		    !is_ipac_active(SCT_3) &&
-		    !is_ipac_active(SCT_4)) {
-			/* Issue total reset only if no ipac is active */
-			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
-
-			save_flags(flags);
-			sti();
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout((10 * HZ) / 1000);
-
-			/* Remove the soft reset */
-			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
-
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout((10 * HZ) / 1000);
-			restore_flags(flags);
-		}
+	if (cs->subtyp == SCT_1) {
+		wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
+		save_flags(flags);
+		sti();
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((10 * HZ) / 1000);
+		/* Remove the soft reset */
+		wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((10 * HZ) / 1000);
+		restore_flags(flags);
 	}
 }
 
@@ -321,20 +247,19 @@
 	switch (mt) {
 		case CARD_RESET:
 			/* Disable ints */
-			set_ipac_active(cs->subtyp, 0);
+			set_ipac_active(cs, 0);
 			enable_bkm_int(cs, 0);
 			reset_bkm(cs);
 			return (0);
 		case CARD_RELEASE:
 			/* Sanity */
-			set_ipac_active(cs->subtyp, 0);
+			set_ipac_active(cs, 0);
 			enable_bkm_int(cs, 0);
-			reset_bkm(cs);
 			release_io_sct_quadro(cs);
 			return (0);
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
-			set_ipac_active(cs->subtyp, 1);
+			set_ipac_active(cs, 1);
 			inithscxisac(cs, 3);
 			/* Enable ints */
 			enable_bkm_int(cs, 1);
@@ -345,18 +270,38 @@
 	return (0);
 }
 
+int __init
+sct_alloc_io(u_int adr, u_int len)
+{
+	if (check_region(adr, len)) {
+		printk(KERN_WARNING
+			"HiSax: Scitel port %#x-%#x already in use\n",
+			adr, adr + len);
+		return (1);
+	} else {
+		request_region(adr, len, "scitel");
+	}
+	return(0);
+}
+
 static struct pci_dev *dev_a8 __initdata = NULL;
+static u16  sub_vendor_id __initdata = 0;
+static u16  sub_sys_id __initdata = 0;
+static u_char pci_bus __initdata = 0;
+static u_char pci_device_fn __initdata = 0;
+static u_char pci_irq __initdata = 0;
+
+#endif /* CONFIG_PCI */
 
-__initfunc(int
-	   setup_sct_quadro(struct IsdnCard *card))
+int __init
+setup_sct_quadro(struct IsdnCard *card)
 {
+#if CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-#if CONFIG_PCI
-	u_char pci_bus = 0, pci_device_fn = 0, pci_irq = 0, pci_rev_id;
+	u_char pci_rev_id;
 	u_int found = 0;
 	u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
-#endif
 
 	strcpy(tmp, sct_quadro_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
@@ -368,32 +313,61 @@
 	/* Identify subtype by para[0] */
 	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
 		cs->subtyp = card->para[0];
-	else
+	else {
 		printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
-		       CardType[card->typ]);
-#if CONFIG_PCI
-	if (!pci_present()) {
-		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
+			CardType[card->typ]);
 		return (0);
 	}
-	if ((dev_a8 = pci_find_device(PLX_VENDOR_ID, PLX_DEVICE_ID, dev_a8))) {
-		u_int sub_sys_id = 0;
-
-		pci_read_config_dword(dev_a8, PCI_SUBSYSTEM_VENDOR_ID,
-			&sub_sys_id);
-		if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
-			found = 1;
-			pci_ioaddr1 = dev_a8->base_address[ 1];
-			pci_irq = dev_a8->irq;
-			pci_bus = dev_a8->bus->number;
-			pci_device_fn = dev_a8->devfn;
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
-		       CardType[card->typ],
-		       sct_quadro_subtypes[cs->subtyp]);
+	if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) ||
+		(sub_vendor_id != PCI_VENDOR_ID_BERKOM)))
 		return (0);
+	if (cs->subtyp == SCT_1) {
+		if (!pci_present()) {
+			printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
+			return (0);
+		}
+		while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX,
+			PCI_DEVICE_ID_PLX_9050, dev_a8))) {
+			
+			pci_read_config_word(dev_a8, PCI_SUBSYSTEM_VENDOR_ID, &sub_vendor_id);
+			pci_read_config_word(dev_a8, PCI_SUBSYSTEM_ID, &sub_sys_id);
+			if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) &&
+				(sub_vendor_id == PCI_VENDOR_ID_BERKOM)) {
+				if (pci_enable_device(dev_a8))
+					return(0);
+				pci_ioaddr1 = dev_a8->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
+				pci_irq = dev_a8->irq;
+				pci_bus = dev_a8->bus->number;
+				pci_device_fn = dev_a8->devfn;
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
+				CardType[card->typ],
+				sct_quadro_subtypes[cs->subtyp]);
+			return (0);
+		}
+#ifdef ATTEMPT_PCI_REMAPPING
+/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
+		pcibios_read_config_byte(pci_bus, pci_device_fn,
+			PCI_REVISION_ID, &pci_rev_id);
+		if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+			printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
+				CardType[card->typ],
+				sct_quadro_subtypes[cs->subtyp]);
+			/* Restart PCI negotiation */
+			pcibios_write_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_1, (u_int) - 1);
+			/* Move up by 0x80 byte */
+			pci_ioaddr1 += 0x80;
+			pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+			pcibios_write_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_1, pci_ioaddr1);
+			dev_a8->base_address[ 1] = pci_ioaddr1;
+		}
+#endif /* End HACK */
 	}
 	if (!pci_irq) {		/* IRQ range check ?? */
 		printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
@@ -401,25 +375,6 @@
 		       sct_quadro_subtypes[cs->subtyp]);
 		return (0);
 	}
-#ifdef ATTEMPT_PCI_REMAPPING
-/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
-	pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_REVISION_ID, &pci_rev_id);
-	if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
-		printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
-			CardType[card->typ],
-			sct_quadro_subtypes[cs->subtyp]);
-		/* Restart PCI negotiation */
-		pcibios_write_config_dword(pci_bus, pci_device_fn,
-			PCI_BASE_ADDRESS_1, (u_int) - 1);
-		/* Move up by 0x80 byte */
-		pci_ioaddr1 += 0x80;
-		pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
-		pcibios_write_config_dword(pci_bus, pci_device_fn,
-			PCI_BASE_ADDRESS_1, pci_ioaddr1);
-		dev_a8->base_address[ 1] = pci_ioaddr1;
-	}
-/* End HACK */
-#endif
 	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1);
 	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2);
 	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3);
@@ -446,23 +401,42 @@
 	/* pci_ioaddr5 is for the first subdevice only */
 	cs->hw.ax.plx_adr = pci_ioaddr1;
 	/* Enter all ipac_base addresses */
-	ipac_state[SCT_1].base = pci_ioaddr5 + 0x00;
-	ipac_state[SCT_2].base = pci_ioaddr4 + 0x08;
-	ipac_state[SCT_3].base = pci_ioaddr3 + 0x10;
-	ipac_state[SCT_4].base = pci_ioaddr2 + 0x20;
-	/* For isac and hscx control path */
-	cs->hw.ax.base = ipac_state[cs->subtyp].base;
+	switch(cs->subtyp) {
+		case 1:
+			cs->hw.ax.base = pci_ioaddr5 + 0x00;
+			if (sct_alloc_io(pci_ioaddr1, 256))
+				return(0);
+			if (sct_alloc_io(pci_ioaddr5, 256))
+				return(0);
+			/* disable all IPAC */
+			writereg(pci_ioaddr5, pci_ioaddr5 + 4,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14,
+				IPAC_MASK, 0xFF);
+			writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24,
+				IPAC_MASK, 0xFF);
+			break;
+		case 2:
+			cs->hw.ax.base = pci_ioaddr4 + 0x08;
+			if (sct_alloc_io(pci_ioaddr4, 256))
+				return(0);
+			break;
+		case 3:
+			cs->hw.ax.base = pci_ioaddr3 + 0x10;
+			if (sct_alloc_io(pci_ioaddr3, 256))
+				return(0);
+			break;
+		case 4:
+			cs->hw.ax.base = pci_ioaddr2 + 0x20;
+			if (sct_alloc_io(pci_ioaddr2, 256))
+				return(0);
+			break;
+	}	
 	/* For isac and hscx data path */
 	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
-#else
-	printk(KERN_WARNING "HiSax: %s (%s): NO_PCI_BIOS\n",
-	       CardType[card->typ],
-	       sct_quadro_subtypes[cs->subtyp]);
-	printk(KERN_WARNING "HiSax: %s (%s): Unable to configure\n",
-	       CardType[card->typ],
-	       sct_quadro_subtypes[cs->subtyp]);
-	return (0);
-#endif				/* CONFIG_PCI */
+
 	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4X, 0x%.4X, 0x%.4X and IRQ %d\n",
 	       CardType[card->typ],
 	       sct_quadro_subtypes[cs->subtyp],
@@ -473,19 +447,6 @@
 
 	test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 
-	/* Disable all currently not active ipacs */
-	if (!is_ipac_active(SCT_1))
-		set_ipac_active(SCT_1, 0);
-	if (!is_ipac_active(SCT_2))
-		set_ipac_active(SCT_2, 0);
-	if (!is_ipac_active(SCT_3))
-		set_ipac_active(SCT_3, 0);
-	if (!is_ipac_active(SCT_4))
-		set_ipac_active(SCT_4, 0);
-
-	/* Perfom general reset (if possible) */
-	reset_bkm(cs);
-
 	cs->readisac = &ReadISAC;
 	cs->writeisac = &WriteISAC;
 	cs->readisacfifo = &ReadISACfifo;
@@ -502,4 +463,7 @@
 		sct_quadro_subtypes[cs->subtyp],
 		readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
 	return (1);
+#else
+	printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
+#endif /* CONFIG_PCI */
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)