Commit 2ce4fa29 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Add in-kernel ISAPnP support to HiSax driven cards

(by Karsten Keil)
parent 4a0540b8
...@@ -76,7 +76,6 @@ Note: PCF, PCF-Pro: up to now, only the ISDN part is supported ...@@ -76,7 +76,6 @@ Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
Eicon.Diehl Diva U interface not tested Eicon.Diehl Diva U interface not tested
If you know other passive cards with the Siemens chipset, please let me know. If you know other passive cards with the Siemens chipset, please let me know.
To use the PNP cards you need the isapnptools.
You can combine any card, if there is no conflict between the resources You can combine any card, if there is no conflict between the resources
(io, mem, irq). (io, mem, irq).
...@@ -92,8 +91,15 @@ There is also some config needed before you compile the kernel and/or ...@@ -92,8 +91,15 @@ There is also some config needed before you compile the kernel and/or
modules. It is included in the normal "make [menu]config" target at the modules. It is included in the normal "make [menu]config" target at the
kernel. Don't forget it, especially to select the right D-channel protocol. kernel. Don't forget it, especially to select the right D-channel protocol.
Please note: All PnP cards need to be configured with isapnp and will work Please note: In older versions of the HiSax driver, all PnP cards
only with the HiSax driver used as a module. needed to be configured with isapnp and worked only with the HiSax
driver used as a module.
In the current version, HiSax will automatically use the in-kernel
ISAPnP support, provided you selected it during kernel configuration
(CONFIG_ISAPNP), if you don't give the io=, irq= command line parameters.
The affected card types are: 4,7,12,14,19,27-30
a) when built as a module a) when built as a module
------------------------- -------------------------
...@@ -221,6 +227,13 @@ Examples for module loading ...@@ -221,6 +227,13 @@ Examples for module loading
(IO 1 (BASE 0x0180)) (IO 1 (BASE 0x0180))
modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180 modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180
In the current version of HiSax, you can instead simply use
modprobe hisax type=4 protocol=2
if you configured your kernel for ISAPnP. Don't run isapnp in
this case!
6. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 12 and 6. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 12 and
Teles 16.0, 1TR6, IRQ 5, Memory d0000 hex Teles 16.0, 1TR6, IRQ 5, Memory d0000 hex
modprobe hisax type=3,1 protocol=2,1 io=0x280 mem=0,0xd0000 modprobe hisax type=3,1 protocol=2,1 io=0x280 mem=0,0xd0000
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define __NO_VERSION__ #define __NO_VERSION__
#include <linux/init.h> #include <linux/init.h>
#include <linux/isapnp.h>
#include "hisax.h" #include "hisax.h"
#include "isac.h" #include "isac.h"
#include "ipac.h" #include "ipac.h"
...@@ -309,6 +310,27 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -309,6 +310,27 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0); return(0);
} }
#ifdef __ISAPNP__
static struct isapnp_device_id asus_ids[] __initdata = {
{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
(unsigned long) "Asus1688 PnP" },
{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
(unsigned long) "Asus1690 PnP" },
{ ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
(unsigned long) "Isurf2 PnP" },
{ ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
(unsigned long) "Iscas TE320" },
{ 0, }
};
static struct isapnp_device_id *adev = &asus_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __init int __init
setup_asuscom(struct IsdnCard *card) setup_asuscom(struct IsdnCard *card)
{ {
...@@ -321,7 +343,45 @@ setup_asuscom(struct IsdnCard *card) ...@@ -321,7 +343,45 @@ setup_asuscom(struct IsdnCard *card)
printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
if (cs->typ != ISDN_CTYPE_ASUSCOM) if (cs->typ != ISDN_CTYPE_ASUSCOM)
return (0); return (0);
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(adev->card_vendor) {
if ((pb = isapnp_find_card(adev->card_vendor,
adev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
adev->vendor, adev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)adev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] = pd->resource[0].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
break;
} else {
printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
}
}
adev++;
pnp_c=NULL;
}
if (!adev->card_vendor) {
printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
return(0);
}
}
#endif
bytecnt = 8; bytecnt = 8;
cs->hw.asus.cfg_reg = card->para[1]; cs->hw.asus.cfg_reg = card->para[1];
cs->irq = card->para[0]; cs->irq = card->para[0];
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "isac.h" #include "isac.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
extern const char *CardType[]; extern const char *CardType[];
...@@ -763,6 +764,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -763,6 +764,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
} }
static struct pci_dev *dev_avm __initdata = NULL; static struct pci_dev *dev_avm __initdata = NULL;
#ifdef __ISAPNP__
static struct pci_bus *bus_avm __initdata = NULL;
static struct pci_dev *pnp_avm __initdata = NULL;
#endif
int __init int __init
setup_avm_pcipnp(struct IsdnCard *card) setup_avm_pcipnp(struct IsdnCard *card)
...@@ -776,10 +781,47 @@ setup_avm_pcipnp(struct IsdnCard *card) ...@@ -776,10 +781,47 @@ setup_avm_pcipnp(struct IsdnCard *card)
if (cs->typ != ISDN_CTYPE_FRITZPCI) if (cs->typ != ISDN_CTYPE_FRITZPCI)
return (0); return (0);
if (card->para[1]) { if (card->para[1]) {
/* old manual method */
cs->hw.avm.cfg_reg = card->para[1]; cs->hw.avm.cfg_reg = card->para[1];
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->subtyp = AVM_FRITZ_PNP; cs->subtyp = AVM_FRITZ_PNP;
} else { } else {
#ifdef __ISAPNP__
if (isapnp_present()) {
struct pci_bus *ba;
if ((ba = isapnp_find_card(
ISAPNP_VENDOR('A', 'V', 'M'),
ISAPNP_FUNCTION(0x0900), bus_avm))) {
bus_avm = ba;
pnp_avm = NULL;
if ((pnp_avm = isapnp_find_dev(bus_avm,
ISAPNP_VENDOR('A', 'V', 'M'),
ISAPNP_FUNCTION(0x0900), pnp_avm))) {
pnp_avm->prepare(pnp_avm);
pnp_avm->deactivate(pnp_avm);
pnp_avm->activate(pnp_avm);
cs->hw.avm.cfg_reg =
pnp_avm->resource[0].start;
cs->irq =
pnp_avm->irq_resource[0].start;
if (!cs->irq) {
printk(KERN_ERR "FritzPnP:No IRQ\n");
pnp_avm->deactivate(pnp_avm);
return(0);
}
if (!cs->hw.avm.cfg_reg) {
printk(KERN_ERR "FritzPnP:No IO address\n");
pnp_avm->deactivate(pnp_avm);
return(0);
}
cs->subtyp = AVM_FRITZ_PNP;
goto ready;
}
}
} else {
printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
}
#endif
#if CONFIG_PCI #if CONFIG_PCI
if (!pci_present()) { if (!pci_present()) {
printk(KERN_ERR "FritzPCI: no PCI bus present\n"); printk(KERN_ERR "FritzPCI: no PCI bus present\n");
...@@ -810,6 +852,7 @@ setup_avm_pcipnp(struct IsdnCard *card) ...@@ -810,6 +852,7 @@ setup_avm_pcipnp(struct IsdnCard *card)
return (0); return (0);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
ready:
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
if (check_region((cs->hw.avm.cfg_reg), 32)) { if (check_region((cs->hw.avm.cfg_reg), 32)) {
printk(KERN_WARNING printk(KERN_WARNING
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "ipacx.h" #include "ipacx.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/isapnp.h>
extern const char *CardType[]; extern const char *CardType[];
...@@ -911,11 +912,38 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -911,11 +912,38 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva __initdata = NULL;
static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL;
static struct pci_dev *dev_diva201 __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL;
#ifdef __ISAPNP__
static struct isapnp_device_id diva_ids[] __initdata = {
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
(unsigned long) "Diva picola" },
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51),
(unsigned long) "Diva picola" },
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
(unsigned long) "Diva 2.0" },
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71),
(unsigned long) "Diva 2.0" },
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
(unsigned long) "Diva 2.01" },
{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1),
(unsigned long) "Diva 2.01" },
{ 0, }
};
static struct isapnp_device_id *pdev = &diva_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __init int __init
setup_diva(struct IsdnCard *card) setup_diva(struct IsdnCard *card)
{ {
int bytecnt; int bytecnt = 8;
u_char val; u_char val;
struct IsdnCardState *cs = card->cs; struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
...@@ -948,8 +976,75 @@ setup_diva(struct IsdnCard *card) ...@@ -948,8 +976,75 @@ setup_diva(struct IsdnCard *card)
cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
} }
cs->irq = card->para[0]; cs->irq = card->para[0];
bytecnt = 8;
} else { } else {
#ifdef __ISAPNP__
if (isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(pdev->card_vendor) {
if ((pb = isapnp_find_card(pdev->card_vendor,
pdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
pdev->vendor, pdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)pdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] =
pd->resource[0].start;
card->para[0] =
pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
cs->hw.diva.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
cs->subtyp = DIVA_IPAC_ISA;
cs->hw.diva.ctrl = 0;
cs->hw.diva.isac =
card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.hscx =
card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.isac_adr =
card->para[1] + DIVA_IPAC_ADR;
cs->hw.diva.hscx_adr =
card->para[1] + DIVA_IPAC_ADR;
test_and_set_bit(HW_IPAC, &cs->HW_Flags);
} else {
cs->subtyp = DIVA_ISA;
cs->hw.diva.ctrl =
card->para[1] + DIVA_ISA_CTRL;
cs->hw.diva.isac =
card->para[1] + DIVA_ISA_ISAC_DATA;
cs->hw.diva.hscx =
card->para[1] + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr =
card->para[1] + DIVA_ISA_ISAC_ADR;
cs->hw.diva.hscx_adr =
card->para[1] + DIVA_HSCX_ADR;
}
goto ready;
} else {
printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
return(0);
}
}
pdev++;
pnp_c=NULL;
}
if (!pdev->card_vendor) {
printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
}
}
#endif
#if CONFIG_PCI #if CONFIG_PCI
if (!pci_present()) { if (!pci_present()) {
printk(KERN_ERR "Diva: no PCI bus present\n"); printk(KERN_ERR "Diva: no PCI bus present\n");
...@@ -1019,7 +1114,7 @@ setup_diva(struct IsdnCard *card) ...@@ -1019,7 +1114,7 @@ setup_diva(struct IsdnCard *card)
bytecnt = 32; bytecnt = 32;
} }
} }
ready:
printk(KERN_INFO printk(KERN_INFO
"Diva: %s card configured at %#lx IRQ %d\n", "Diva: %s card configured at %#lx IRQ %d\n",
(cs->subtyp == DIVA_PCI) ? "PCI" : (cs->subtyp == DIVA_PCI) ? "PCI" :
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "hscx.h" #include "hscx.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
...@@ -860,6 +861,21 @@ probe_elsa(struct IsdnCardState *cs) ...@@ -860,6 +861,21 @@ probe_elsa(struct IsdnCardState *cs)
static struct pci_dev *dev_qs1000 __devinitdata = NULL; static struct pci_dev *dev_qs1000 __devinitdata = NULL;
static struct pci_dev *dev_qs3000 __devinitdata = NULL; static struct pci_dev *dev_qs3000 __devinitdata = NULL;
#ifdef __ISAPNP__
static struct isapnp_device_id elsa_ids[] __initdata = {
{ ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
(unsigned long) "Elsa QS1000" },
{ ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
(unsigned long) "Elsa QS3000" },
{ 0, }
};
static struct isapnp_device_id *pdev = &elsa_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __devinit int __devinit
setup_elsa(struct IsdnCard *card) setup_elsa(struct IsdnCard *card)
{ {
...@@ -874,6 +890,7 @@ setup_elsa(struct IsdnCard *card) ...@@ -874,6 +890,7 @@ setup_elsa(struct IsdnCard *card)
cs->hw.elsa.ctrl_reg = 0; cs->hw.elsa.ctrl_reg = 0;
cs->hw.elsa.status = 0; cs->hw.elsa.status = 0;
cs->hw.elsa.MFlag = 0; cs->hw.elsa.MFlag = 0;
cs->subtyp = 0;
if (cs->typ == ISDN_CTYPE_ELSA) { if (cs->typ == ISDN_CTYPE_ELSA) {
cs->hw.elsa.base = card->para[0]; cs->hw.elsa.base = card->para[0];
printk(KERN_INFO "Elsa: Microlink IO probing\n"); printk(KERN_INFO "Elsa: Microlink IO probing\n");
...@@ -935,9 +952,60 @@ setup_elsa(struct IsdnCard *card) ...@@ -935,9 +952,60 @@ setup_elsa(struct IsdnCard *card)
return (0); return (0);
} }
} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(pdev->card_vendor) {
if ((pb = isapnp_find_card(pdev->card_vendor,
pdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
pdev->vendor, pdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)pdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] =
pd->resource[0].start;
card->para[0] =
pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
if (pdev->function == ISAPNP_FUNCTION(0x133))
cs->subtyp = ELSA_QS1000;
else
cs->subtyp = ELSA_QS3000;
break;
} else {
printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
return(0);
}
}
pdev++;
pnp_c=NULL;
}
if (!pdev->card_vendor) {
printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
return(0);
}
}
#endif
if (card->para[1] && card->para[0]) {
cs->hw.elsa.base = card->para[1]; cs->hw.elsa.base = card->para[1];
cs->irq = card->para[0]; cs->irq = card->para[0];
if (!cs->subtyp)
cs->subtyp = ELSA_QS1000; cs->subtyp = ELSA_QS1000;
} else {
printk(KERN_ERR "Elsa PnP: no parameter\n");
}
cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
...@@ -1048,6 +1116,7 @@ setup_elsa(struct IsdnCard *card) ...@@ -1048,6 +1116,7 @@ setup_elsa(struct IsdnCard *card)
break; break;
case ELSA_PCFPRO: case ELSA_PCFPRO:
case ELSA_PCF: case ELSA_PCF:
case ELSA_QS3000:
case ELSA_QS3000PCI: case ELSA_QS3000PCI:
bytecnt = 16; bytecnt = 16;
break; break;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "hfc_sx.h" #include "hfc_sx.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/isapnp.h>
extern const char *CardType[]; extern const char *CardType[];
...@@ -1460,7 +1461,17 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -1460,7 +1461,17 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0); return (0);
} }
#ifdef __ISAPNP__
static struct isapnp_device_id hfc_ids[] __initdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
(unsigned long) "Teles 16.3c2" },
{ 0, }
};
static struct isapnp_device_id *hdev = &hfc_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __devinit int __devinit
setup_hfcsx(struct IsdnCard *card) setup_hfcsx(struct IsdnCard *card)
...@@ -1471,6 +1482,45 @@ setup_hfcsx(struct IsdnCard *card) ...@@ -1471,6 +1482,45 @@ setup_hfcsx(struct IsdnCard *card)
strcpy(tmp, hfcsx_revision); strcpy(tmp, hfcsx_revision);
printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(hdev->card_vendor) {
if ((pb = isapnp_find_card(hdev->card_vendor,
hdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
hdev->vendor, hdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)hdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] = pd->resource[0].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
break;
} else {
printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
}
}
hdev++;
pnp_c=NULL;
}
if (!hdev->card_vendor) {
printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
return(0);
}
}
#endif
cs->hw.hfcsx.base = card->para[1] & 0xfffe; cs->hw.hfcsx.base = card->para[1] & 0xfffe;
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.hfcsx.int_s1 = 0; cs->hw.hfcsx.int_s1 = 0;
...@@ -1553,7 +1603,3 @@ setup_hfcsx(struct IsdnCard *card) ...@@ -1553,7 +1603,3 @@ setup_hfcsx(struct IsdnCard *card)
cs->auxcmd = &hfcsx_auxcmd; cs->auxcmd = &hfcsx_auxcmd;
return (1); return (1);
} }
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define __NO_VERSION__ #define __NO_VERSION__
#include <linux/init.h> #include <linux/init.h>
#include <linux/isapnp.h>
#include "hisax.h" #include "hisax.h"
#include "hfc_2bds0.h" #include "hfc_2bds0.h"
#include "isdnl1.h" #include "isdnl1.h"
...@@ -139,6 +140,36 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -139,6 +140,36 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0); return(0);
} }
#ifdef __ISAPNP__
static struct isapnp_device_id hfc_ids[] __initdata = {
{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
(unsigned long) "Acer P10" },
{ ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
(unsigned long) "Billion 2" },
{ ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
(unsigned long) "Billion 1" },
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
(unsigned long) "IStar PnP" },
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
(unsigned long) "Teles 16.3c" },
{ ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
(unsigned long) "Tornado Tipa C" },
{ ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
(unsigned long) "Genius Speed Surfer" },
{ 0, }
};
static struct isapnp_device_id *hdev = &hfc_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __init int __init
setup_hfcs(struct IsdnCard *card) setup_hfcs(struct IsdnCard *card)
{ {
...@@ -147,6 +178,46 @@ setup_hfcs(struct IsdnCard *card) ...@@ -147,6 +178,46 @@ setup_hfcs(struct IsdnCard *card)
strcpy(tmp, hfcs_revision); strcpy(tmp, hfcs_revision);
printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(hdev->card_vendor) {
if ((pb = isapnp_find_card(hdev->card_vendor,
hdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
hdev->vendor, hdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)hdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] = pd->resource[0].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
break;
} else {
printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
}
}
hdev++;
pnp_c=NULL;
}
if (!hdev->card_vendor) {
printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
return(0);
}
}
#endif
cs->hw.hfcD.addr = card->para[1] & 0xfffe; cs->hw.hfcD.addr = card->para[1] & 0xfffe;
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.hfcD.cip = 0; cs->hw.hfcD.cip = 0;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "isac.h" #include "isac.h"
#include "isar.h" #include "isar.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/isapnp.h>
extern const char *CardType[]; extern const char *CardType[];
...@@ -193,6 +194,10 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { ...@@ -193,6 +194,10 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
return(isar_auxcmd(cs, ic)); return(isar_auxcmd(cs, ic));
} }
#ifdef __ISAPNP__
static struct pci_bus *pnp_surf __devinitdata = NULL;
#endif
int __init int __init
setup_isurf(struct IsdnCard *card) setup_isurf(struct IsdnCard *card)
{ {
...@@ -210,9 +215,48 @@ setup_isurf(struct IsdnCard *card) ...@@ -210,9 +215,48 @@ setup_isurf(struct IsdnCard *card)
cs->hw.isurf.phymem = card->para[2]; cs->hw.isurf.phymem = card->para[2];
cs->irq = card->para[0]; cs->irq = card->para[0];
} else { } else {
#ifdef __ISAPNP__
struct pci_bus *pb;
struct pci_dev *pd;
if (isapnp_present()) {
cs->subtyp = 0;
if ((pb = isapnp_find_card(
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pnp_surf))) {
pnp_surf = pb;
pd = NULL;
if (!(pd = isapnp_find_dev(pnp_surf,
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pd))) {
printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
return (0);
}
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
cs->hw.isurf.reset = pd->resource[0].start;
cs->hw.isurf.phymem = pd->resource[1].start;
cs->irq = pd->irq_resource[0].start;
if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
pd->deactivate(pd);
return(0);
}
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
return(0);
}
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
return(0);
}
#else
printk(KERN_WARNING "HiSax: %s port/mem not set\n", printk(KERN_WARNING "HiSax: %s port/mem not set\n",
CardType[card->typ]); CardType[card->typ]);
return (0); return (0);
#endif
} }
if (check_region(cs->hw.isurf.reset, 1)) { if (check_region(cs->hw.isurf.reset, 1)) {
printk(KERN_WARNING printk(KERN_WARNING
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define __NO_VERSION__ #define __NO_VERSION__
#include <linux/init.h> #include <linux/init.h>
#include <linux/isapnp.h>
#include "hisax.h" #include "hisax.h"
#include "isac.h" #include "isac.h"
#include "hscx.h" #include "hscx.h"
...@@ -218,6 +219,21 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -218,6 +219,21 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0); return(0);
} }
#ifdef __ISAPNP__
static struct isapnp_device_id itk_ids[] __initdata = {
{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
(unsigned long) "ITK micro 2" },
{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
(unsigned long) "ITK micro 2." },
{ 0, }
};
static struct isapnp_device_id *idev = &itk_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __init int __init
setup_ix1micro(struct IsdnCard *card) setup_ix1micro(struct IsdnCard *card)
...@@ -230,6 +246,45 @@ setup_ix1micro(struct IsdnCard *card) ...@@ -230,6 +246,45 @@ setup_ix1micro(struct IsdnCard *card)
if (cs->typ != ISDN_CTYPE_IX1MICROR2) if (cs->typ != ISDN_CTYPE_IX1MICROR2)
return (0); return (0);
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(idev->card_vendor) {
if ((pb = isapnp_find_card(idev->card_vendor,
idev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
idev->vendor, idev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)idev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] = pd->resource[0].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
break;
} else {
printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
}
}
idev++;
pnp_c=NULL;
}
if (!idev->card_vendor) {
printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
return(0);
}
}
#endif
/* IO-Ports */ /* IO-Ports */
cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET; cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "hscx.h" #include "hscx.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/isapnp.h>
extern const char *CardType[]; extern const char *CardType[];
const char *niccy_revision = "$Revision: 1.15.6.6 $"; const char *niccy_revision = "$Revision: 1.15.6.6 $";
...@@ -238,6 +239,9 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -238,6 +239,9 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
} }
static struct pci_dev *niccy_dev __initdata = NULL; static struct pci_dev *niccy_dev __initdata = NULL;
#ifdef __ISAPNP__
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __init int __init
setup_niccy(struct IsdnCard *card) setup_niccy(struct IsdnCard *card)
...@@ -249,7 +253,39 @@ setup_niccy(struct IsdnCard *card) ...@@ -249,7 +253,39 @@ setup_niccy(struct IsdnCard *card)
printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
if (cs->typ != ISDN_CTYPE_NICCY) if (cs->typ != ISDN_CTYPE_NICCY)
return (0); return (0);
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
if ((pb = isapnp_find_card(
ISAPNP_VENDOR('S', 'D', 'A'),
ISAPNP_FUNCTION(0x0150), pnp_c))) {
pnp_c = pb;
pd = NULL;
if (!(pd = isapnp_find_dev(pnp_c,
ISAPNP_VENDOR('S', 'D', 'A'),
ISAPNP_FUNCTION(0x0150), pd))) {
printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
return (0);
}
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] = pd->resource[0].start;
card->para[2] = pd->resource[1].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1] || !card->para[2]) {
printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
card->para[0], card->para[1], card->para[2]);
pd->deactivate(pd);
return(0);
}
} else {
printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
}
}
#endif
if (card->para[1]) { if (card->para[1]) {
cs->hw.niccy.isac = card->para[1] + ISAC_PNP; cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "isar.h" #include "isar.h"
#include "isdnl1.h" #include "isdnl1.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/isapnp.h>
extern const char *CardType[]; extern const char *CardType[];
...@@ -530,6 +531,21 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -530,6 +531,21 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static struct pci_dev *dev_sedl __devinitdata = NULL; static struct pci_dev *dev_sedl __devinitdata = NULL;
#ifdef __ISAPNP__
static struct isapnp_device_id sedl_ids[] __initdata = {
{ ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
(unsigned long) "Speed win" },
{ ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
(unsigned long) "Speed Fax+" },
{ 0, }
};
static struct isapnp_device_id *pdev = &sedl_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __devinit int __devinit
setup_sedlbauer(struct IsdnCard *card) setup_sedlbauer(struct IsdnCard *card)
{ {
...@@ -565,6 +581,57 @@ setup_sedlbauer(struct IsdnCard *card) ...@@ -565,6 +581,57 @@ setup_sedlbauer(struct IsdnCard *card)
bytecnt = 16; bytecnt = 16;
} }
} else { } else {
#ifdef __ISAPNP__
if (isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(pdev->card_vendor) {
if ((pb = isapnp_find_card(pdev->card_vendor,
pdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
pdev->vendor, pdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)pdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[1] =
pd->resource[0].start;
card->para[0] =
pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1]) {
printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
card->para[0], card->para[1]);
pd->deactivate(pd);
return(0);
}
cs->hw.sedl.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0x2)) {
cs->subtyp = SEDL_SPEED_FAX;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
bytecnt = 16;
} else {
cs->subtyp = SEDL_SPEED_CARD_WIN;
cs->hw.sedl.chip = SEDL_CHIP_TEST;
}
goto ready;
} else {
printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
return(0);
}
}
pdev++;
pnp_c=NULL;
}
if (!pdev->card_vendor) {
printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
}
}
#endif
/* Probe for Sedlbauer speed pci */ /* Probe for Sedlbauer speed pci */
#if CONFIG_PCI #if CONFIG_PCI
if (!pci_present()) { if (!pci_present()) {
...@@ -630,7 +697,7 @@ setup_sedlbauer(struct IsdnCard *card) ...@@ -630,7 +697,7 @@ setup_sedlbauer(struct IsdnCard *card)
return (0); return (0);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
ready:
/* In case of the sedlbauer pcmcia card, this region is in use, /* In case of the sedlbauer pcmcia card, this region is in use,
* reserved for us by the card manager. So we do not check it * reserved for us by the card manager. So we do not check it
* here, it would fail. * here, it would fail.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#define __NO_VERSION__ #define __NO_VERSION__
#include <linux/init.h> #include <linux/init.h>
#include <linux/isapnp.h>
#include "hisax.h" #include "hisax.h"
#include "isac.h" #include "isac.h"
#include "hscx.h" #include "hscx.h"
...@@ -254,6 +255,24 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) ...@@ -254,6 +255,24 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0); return(0);
} }
#ifdef __ISAPNP__
static struct isapnp_device_id teles_ids[] __initdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
(unsigned long) "Teles 16.3 PnP" },
{ ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
(unsigned long) "Creatix 16.3 PnP" },
{ ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
(unsigned long) "Compaq ISDN S0" },
{ 0, }
};
static struct isapnp_device_id *tdev = &teles_ids[0];
static struct pci_bus *pnp_c __devinitdata = NULL;
#endif
int __devinit int __devinit
setup_teles3(struct IsdnCard *card) setup_teles3(struct IsdnCard *card)
{ {
...@@ -267,6 +286,47 @@ setup_teles3(struct IsdnCard *card) ...@@ -267,6 +286,47 @@ setup_teles3(struct IsdnCard *card)
&& (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
return (0); return (0);
#ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) {
struct pci_bus *pb;
struct pci_dev *pd;
while(tdev->card_vendor) {
if ((pb = isapnp_find_card(tdev->card_vendor,
tdev->card_device, pnp_c))) {
pnp_c = pb;
pd = NULL;
if ((pd = isapnp_find_dev(pnp_c,
tdev->vendor, tdev->function, pd))) {
printk(KERN_INFO "HiSax: %s detected\n",
(char *)tdev->driver_data);
pd->prepare(pd);
pd->deactivate(pd);
pd->activate(pd);
card->para[3] = pd->resource[2].start;
card->para[2] = pd->resource[1].start;
card->para[1] = pd->resource[0].start;
card->para[0] = pd->irq_resource[0].start;
if (!card->para[0] || !card->para[1] || !card->para[2]) {
printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
card->para[0], card->para[1], card->para[2]);
pd->deactivate(pd);
return(0);
}
break;
} else {
printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
}
}
tdev++;
pnp_c=NULL;
}
if (!tdev->card_vendor) {
printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
return(0);
}
}
#endif
if (cs->typ == ISDN_CTYPE_16_3) { if (cs->typ == ISDN_CTYPE_16_3) {
cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.cfg_reg = card->para[1];
switch (cs->hw.teles3.cfg_reg) { switch (cs->hw.teles3.cfg_reg) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment