Commit 84cadf5c authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/HiSax: Clean up the gazel subdriver

Instead of having "switch (subtype)" in just about every function,
rather use separate functions and invoke the right one using
the now existing struct card_ops infrastructure.
parent 8686ec19
......@@ -70,115 +70,103 @@ write_fifo(unsigned int adr, u8 * data, int size)
}
static u8
isac_read(struct IsdnCardState *cs, u8 offset)
r685_isac_read(struct IsdnCardState *cs, u8 off)
{
u_short off2 = offset;
return readreg(cs->hw.gazel.isac, off);
}
switch (cs->subtyp) {
case R647:
off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
case R685:
return (readreg(cs->hw.gazel.isac, off2));
}
return 0;
static u8
r647_isac_read(struct IsdnCardState *cs, u8 off)
{
return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf));
}
static void
isac_write(struct IsdnCardState *cs, u8 offset, u8 value)
r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
{
u_short off2 = offset;
writereg(cs->hw.gazel.isac, off, value);
}
switch (cs->subtyp) {
case R647:
off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
case R685:
writereg(cs->hw.gazel.isac, off2, value);
break;
}
static void
r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value)
{
writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value);
}
static void
isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size)
{
switch (cs->subtyp) {
case R647:
case R685:
read_fifo(cs->hw.gazel.isacfifo, data, size);
break;
}
}
static void
isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size)
{
switch (cs->subtyp) {
case R647:
case R685:
write_fifo(cs->hw.gazel.isacfifo, data, size);
break;
}
}
static struct dc_hw_ops isac_ops = {
.read_reg = isac_read,
.write_reg = isac_write,
static struct dc_hw_ops r685_isac_ops = {
.read_reg = r685_isac_read,
.write_reg = r685_isac_write,
.read_fifo = isac_read_fifo,
.write_fifo = isac_write_fifo,
};
static struct dc_hw_ops r647_isac_ops = {
.read_reg = r647_isac_read,
.write_reg = r647_isac_write,
.read_fifo = isac_read_fifo,
.write_fifo = isac_write_fifo,
};
static u8
hscx_read(struct IsdnCardState *cs, int hscx, u8 offset)
r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
{
u_short off2 = offset;
return readreg(cs->hw.gazel.hscx[hscx], off);
}
switch (cs->subtyp) {
case R647:
off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
case R685:
return readreg(cs->hw.gazel.hscx[hscx], off2);
}
return 0;
static u8
r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off)
{
return readreg(cs->hw.gazel.hscx[hscx],
(off << 8 & 0xf000) | (off & 0xf));
}
static void
hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value)
r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
{
u_short off2 = offset;
writereg(cs->hw.gazel.hscx[hscx], off, value);
}
switch (cs->subtyp) {
case R647:
off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
case R685:
writereg(cs->hw.gazel.hscx[hscx], off2, value);
break;
}
static void
r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value)
{
writereg(cs->hw.gazel.hscx[hscx],
(off << 8 & 0xf000) | (off & 0xf), value);
}
static void
hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
{
switch (cs->subtyp) {
case R647:
case R685:
read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
break;
}
}
static void
hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size)
{
switch (cs->subtyp) {
case R647:
case R685:
write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
break;
}
}
static struct bc_hw_ops hscx_ops = {
.read_reg = hscx_read,
.write_reg = hscx_write,
static struct bc_hw_ops r685_hscx_ops = {
.read_reg = r685_hscx_read,
.write_reg = r685_hscx_write,
.read_fifo = hscx_read_fifo,
.write_fifo = hscx_write_fifo,
};
static struct bc_hw_ops r647_hscx_ops = {
.read_reg = r647_hscx_read,
.write_reg = r647_hscx_write,
.read_fifo = hscx_read_fifo,
.write_fifo = hscx_write_fifo,
};
......@@ -227,51 +215,21 @@ ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size)
BUILD_IPAC_OPS(ipac);
static void
gazel_release(struct IsdnCardState *cs)
{
unsigned int i;
switch (cs->subtyp) {
case R647:
for (i = 0x0000; i < 0xC000; i += 0x1000)
release_region(i + cs->hw.gazel.hscx[0], 16);
release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
break;
case R685:
release_region(cs->hw.gazel.hscx[0], 0x100);
release_region(cs->hw.gazel.cfg_reg, 0x80);
break;
}
}
static void
gazel_ipac_release(struct IsdnCardState *cs)
static int
r647_reset(struct IsdnCardState *cs)
{
switch (cs->subtyp) {
case R753:
release_region(cs->hw.gazel.ipac, 0x8);
release_region(cs->hw.gazel.cfg_reg, 0x80);
break;
case R742:
release_region(cs->hw.gazel.ipac, 8);
break;
}
writereg(cs->hw.gazel.cfg_reg, 0, 0);
HZDELAY(10);
writereg(cs->hw.gazel.cfg_reg, 0, 1);
HZDELAY(2);
return 0;
}
static int
gazel_reset(struct IsdnCardState *cs)
r685_reset(struct IsdnCardState *cs)
{
unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
switch (cs->subtyp) {
case R647:
writereg(addr, 0, 0);
HZDELAY(10);
writereg(addr, 0, 1);
HZDELAY(2);
break;
case R685:
plxcntrl = inl(addr + PLX_CNTRL);
plxcntrl |= (RESET_9050 + RESET_GAZEL);
outl(plxcntrl, addr + PLX_CNTRL);
......@@ -280,18 +238,14 @@ gazel_reset(struct IsdnCardState *cs)
outl(plxcntrl, addr + PLX_CNTRL);
HZDELAY(10);
outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
break;
}
return 0;
}
static int
gazel_ipac_reset(struct IsdnCardState *cs)
r753_reset(struct IsdnCardState *cs)
{
unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
switch (cs->subtyp) {
case R753:
if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags))
/* we can't read, assume the default */
plxcntrl = 0x18784db6;
......@@ -311,8 +265,12 @@ gazel_ipac_reset(struct IsdnCardState *cs)
ipac_write(cs, IPAC_CONF, 0x1);
outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
ipac_write(cs, IPAC_MASK, 0xc0);
break;
case R742:
return 0;
}
static int
r742_reset(struct IsdnCardState *cs)
{
ipac_write(cs, IPAC_POTA2, 0x20);
HZDELAY(4);
ipac_write(cs, IPAC_POTA2, 0x00);
......@@ -321,8 +279,6 @@ gazel_ipac_reset(struct IsdnCardState *cs)
ipac_write(cs, IPAC_MASK, 0xff);
ipac_write(cs, IPAC_CONF, 0x1);
ipac_write(cs, IPAC_MASK, 0xc0);
break;
}
return 0;
}
......@@ -341,81 +297,133 @@ gazel_init(struct IsdnCardState *cs)
cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
}
inithscxisac(cs);
}
static struct card_ops gazel_ops = {
.init = gazel_init,
.reset = gazel_reset,
.release = gazel_release,
.irq_func = hscxisac_irq,
};
static struct resource *
gazel_request_region(unsigned long start, unsigned long n, const char *name)
{
struct resource *rc = request_region(start, n, name);
static struct card_ops gazel_ipac_ops = {
.init = ipac_init,
.reset = gazel_ipac_reset,
.release = gazel_ipac_release,
.irq_func = ipac_irq,
};
if (!rc)
printk(KERN_WARNING "Gazel: io %#lx-%#lx already in use\n",
start, start + n);
return rc;
}
static int
reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
r647_reserve_regions(struct IsdnCardState *cs)
{
unsigned int i, base = 0, adr = 0, len = 0;
int i, base;
switch (cs->subtyp) {
case R647:
base = cs->hw.gazel.hscx[0];
for (i = 0x0000; i < 0xC000; i += 0x1000) {
if (!request_region(adr = (i + base), len = 16, "gazel")) {
int j;
for (j = 0x0000; j < i; j += 0x1000)
release_region ((j + base), len);
goto error;
if (!gazel_request_region(i + base, 16, "gazel")) {
for (i -= 0x1000; i >= 0; i -= 0x1000)
release_region (i + base, 16);
return -EBUSY;
}
}
if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) {
if (!gazel_request_region(0xC000 + base, 1, "gazel")) {
for (i = 0x0000; i < 0xC000; i += 0x1000)
release_region ((i + base), 16);
goto error;
release_region (i + base, 16);
return -EBUSY;
}
return 0;
}
break;
static void
r647_release(struct IsdnCardState *cs)
{
int i;
case R685:
if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel"))
goto error;
if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
for (i = 0x0000; i < 0xC000; i += 0x1000)
release_region(i + cs->hw.gazel.hscx[0], 16);
release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
}
static int
r685_reserve_regions(struct IsdnCardState *cs)
{
if (!gazel_request_region(cs->hw.gazel.hscx[0], 0x100, "gazel")) {
return -EBUSY;
}
if (!gazel_request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel")) {
release_region (cs->hw.gazel.hscx[0], 0x100);
goto error;
return -EBUSY;
}
return 0;
}
break;
static void
r685_release(struct IsdnCardState *cs)
{
release_region(cs->hw.gazel.hscx[0], 0x100);
release_region(cs->hw.gazel.cfg_reg, 0x80);
}
case R753:
if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
goto error;
if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) {
release_region (cs->hw.gazel.ipac, 0x8);
goto error;
}
static int
r742_reserve_regions(struct IsdnCardState *cs)
{
if (!gazel_request_region(cs->hw.gazel.ipac, 0x8, "gazel"))
return -EBUSY;
return 0;
}
break;
static void
r742_release(struct IsdnCardState *cs)
{
release_region(cs->hw.gazel.ipac, 8);
}
case R742:
if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel"))
goto error;
break;
static int
r753_reserve_regions(struct IsdnCardState *cs)
{
if (!gazel_request_region(cs->hw.gazel.ipac, 0x8, "gazel")) {
return -EBUSY;
}
if (!gazel_request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel")) {
release_region (cs->hw.gazel.ipac, 0x8);
return -EBUSY;
}
return 0;
}
error:
printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
CardType[cs->typ], adr, adr + len);
return 1;
static void
r753_release(struct IsdnCardState *cs)
{
release_region(cs->hw.gazel.ipac, 0x8);
release_region(cs->hw.gazel.cfg_reg, 0x80);
}
static struct card_ops r647_ops = {
.init = gazel_init,
.reset = r647_reset,
.release = r647_release,
.irq_func = hscxisac_irq,
};
static struct card_ops r685_ops = {
.init = gazel_init,
.reset = r685_reset,
.release = r685_release,
.irq_func = hscxisac_irq,
};
static struct card_ops r742_ops = {
.init = ipac_init,
.reset = r742_reset,
.release = r742_release,
.irq_func = ipac_irq,
};
static struct card_ops r753_ops = {
.init = ipac_init,
.reset = r753_reset,
.release = r753_release,
.irq_func = ipac_irq,
};
static int __init
setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
{
......@@ -450,16 +458,15 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
"Gazel: hscx A:0x%X hscx B:0x%X\n",
cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
break;
return r647_reserve_regions(cs);
case R742:
printk(KERN_INFO "Gazel: Card ISA R742 found\n");
printk(KERN_INFO
"Gazel: config irq:%d ipac:0x%X\n",
cs->irq, cs->hw.gazel.ipac);
break;
return r742_reserve_regions(cs);
}
return (0);
return 0;
}
static struct pci_dev *dev_tel __initdata = NULL;
......@@ -504,11 +511,11 @@ setup_gazelpci(struct IsdnCardState *cs)
}
if (!found) {
printk(KERN_WARNING "Gazel: No PCI card found\n");
return (1);
return -ENODEV;
}
if (!pci_irq) {
printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
return 1;
return -ENODEV;
}
cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
......@@ -536,7 +543,7 @@ setup_gazelpci(struct IsdnCardState *cs)
printk(KERN_INFO
"Gazel: hscx A:0x%X hscx B:0x%X\n",
cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
break;
return r685_reserve_regions(cs);
case PCI_DEVICE_ID_PLX_R753:
case PCI_DEVICE_ID_PLX_DJINN_ITOO:
printk(KERN_INFO "Gazel: Card PCI R753 found\n");
......@@ -556,10 +563,9 @@ setup_gazelpci(struct IsdnCardState *cs)
set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
}
}
break;
return r753_reserve_regions(cs);
}
return (0);
return 0;
}
int __init
......@@ -579,42 +585,43 @@ setup_gazel(struct IsdnCard *card)
if (setup_gazelisa(card, cs))
return (0);
} else {
#if CONFIG_PCI
if (setup_gazelpci(cs))
return (0);
#else
printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
return (0);
#endif /* CONFIG_PCI */
}
if (reserve_regions(card, cs)) {
return (0);
}
cs->cardmsg = &Gazel_card_msg;
switch (cs->subtyp) {
case R647:
case R685:
cs->dc_hw_ops = &isac_ops;
cs->bc_hw_ops = &hscx_ops;
gazel_reset(cs);
cs->card_ops = &gazel_ops;
if (cs->subtyp == R647) {
cs->dc_hw_ops = &r647_isac_ops;
cs->bc_hw_ops = &r647_hscx_ops;
cs->card_ops = &r647_ops;
} else {
cs->dc_hw_ops = &r685_isac_ops;
cs->bc_hw_ops = &r685_hscx_ops;
cs->card_ops = &r685_ops;
}
cs->card_ops->reset(cs);
ISACVersion(cs, "Gazel:");
if (HscxVersion(cs, "Gazel:")) {
printk(KERN_WARNING
"Gazel: wrong HSCX versions check IO address\n");
gazel_release(cs);
cs->card_ops->release(cs);
return (0);
}
break;
case R742:
case R753:
if (cs->subtyp == R742) {
cs->card_ops = &r742_ops;
} else {
cs->card_ops = &r753_ops;
}
cs->dc_hw_ops = &ipac_dc_ops;
cs->bc_hw_ops = &ipac_bc_ops;
gazel_ipac_reset(cs);
cs->card_ops = &gazel_ipac_ops;
cs->card_ops->reset(cs);
val = ipac_read(cs, IPAC_ID);
printk(KERN_INFO "Gazel: IPAC version %x\n", val);
break;
......
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