diff options
-rw-r--r-- | drivers/net/pcmcia/fmvj18x_cs.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index e4f8fe3c5da..69dcfbbabe8 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -125,6 +125,7 @@ typedef struct local_info_t { u_short tx_queue_len; cardtype_t cardtype; u_short sent; + u_char __iomem *base; } local_info_t; #define MC_FILTERBREAK 64 @@ -242,6 +243,7 @@ static int fmvj18x_probe(struct pcmcia_device *link) lp = netdev_priv(dev); link->priv = dev; lp->p_dev = link; + lp->base = NULL; /* The io structure describes IO port mapping */ link->io.NumPorts1 = 32; @@ -442,8 +444,10 @@ static int fmvj18x_config(struct pcmcia_device *link) dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - if (link->io.BasePort2 != 0) - fmvj18x_setup_mfc(link); + if (link->io.BasePort2 != 0) { + ret = fmvj18x_setup_mfc(link); + if (ret != 0) goto failed; + } ioaddr = dev->base_addr; @@ -610,10 +614,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link) { win_req_t req; memreq_t mem; - u_char __iomem *base; - int i, j; + int i; struct net_device *dev = link->priv; unsigned int ioaddr; + local_info_t *lp = netdev_priv(dev); /* Allocate a small memory window */ req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; @@ -625,25 +629,32 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link) return -1; } - base = ioremap(req.Base, req.Size); + lp->base = ioremap(req.Base, req.Size); + if (lp->base == NULL) { + printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n"); + return -1; + } + mem.Page = 0; mem.CardOffset = 0; - pcmcia_map_mem_page(link->win, &mem); - + i = pcmcia_map_mem_page(link->win, &mem); + if (i != 0) { + iounmap(lp->base); + lp->base = NULL; + cs_error(link, MapMemPage, i); + return -1; + } + ioaddr = dev->base_addr; - writeb(0x47, base+0x800); /* Config Option Register of LAN */ - writeb(0x0, base+0x802); /* Config and Status Register */ + writeb(0x47, lp->base+0x800); /* Config Option Register of LAN */ + writeb(0x0, lp->base+0x802); /* Config and Status Register */ - writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */ - writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */ + writeb(ioaddr & 0xff, lp->base+0x80a); /* I/O Base(Low) of LAN */ + writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */ - writeb(0x45, base+0x820); /* Config Option Register of Modem */ - writeb(0x8, base+0x822); /* Config and Status Register */ + writeb(0x45, lp->base+0x820); /* Config Option Register of Modem */ + writeb(0x8, lp->base+0x822); /* Config and Status Register */ - iounmap(base); - j = pcmcia_release_window(link->win); - if (j != 0) - cs_error(link, ReleaseWindow, j); return 0; } @@ -651,8 +662,25 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link) static void fmvj18x_release(struct pcmcia_device *link) { - DEBUG(0, "fmvj18x_release(0x%p)\n", link); - pcmcia_disable_device(link); + + struct net_device *dev = link->priv; + local_info_t *lp = netdev_priv(dev); + u_char __iomem *tmp; + int j; + + DEBUG(0, "fmvj18x_release(0x%p)\n", link); + + if (lp->base != NULL) { + tmp = lp->base; + lp->base = NULL; /* set NULL before iounmap */ + iounmap(tmp); + j = pcmcia_release_window(link->win); + if (j != 0) + cs_error(link, ReleaseWindow, j); + } + + pcmcia_disable_device(link); + } static int fmvj18x_suspend(struct pcmcia_device *link) @@ -783,6 +811,13 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id) outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR); + + if (lp->base != NULL) { + /* Ack interrupt for multifunction card */ + writeb(0x01, lp->base+0x802); + writeb(0x09, lp->base+0x822); + } + return IRQ_HANDLED; } /* fjn_interrupt */ |