aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index e4f8fe3c5dae..69dcfbbabe82 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -125,6 +125,7 @@ typedef struct local_info_t {
125 u_short tx_queue_len; 125 u_short tx_queue_len;
126 cardtype_t cardtype; 126 cardtype_t cardtype;
127 u_short sent; 127 u_short sent;
128 u_char __iomem *base;
128} local_info_t; 129} local_info_t;
129 130
130#define MC_FILTERBREAK 64 131#define MC_FILTERBREAK 64
@@ -242,6 +243,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
242 lp = netdev_priv(dev); 243 lp = netdev_priv(dev);
243 link->priv = dev; 244 link->priv = dev;
244 lp->p_dev = link; 245 lp->p_dev = link;
246 lp->base = NULL;
245 247
246 /* The io structure describes IO port mapping */ 248 /* The io structure describes IO port mapping */
247 link->io.NumPorts1 = 32; 249 link->io.NumPorts1 = 32;
@@ -442,8 +444,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
442 dev->irq = link->irq.AssignedIRQ; 444 dev->irq = link->irq.AssignedIRQ;
443 dev->base_addr = link->io.BasePort1; 445 dev->base_addr = link->io.BasePort1;
444 446
445 if (link->io.BasePort2 != 0) 447 if (link->io.BasePort2 != 0) {
446 fmvj18x_setup_mfc(link); 448 ret = fmvj18x_setup_mfc(link);
449 if (ret != 0) goto failed;
450 }
447 451
448 ioaddr = dev->base_addr; 452 ioaddr = dev->base_addr;
449 453
@@ -610,10 +614,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
610{ 614{
611 win_req_t req; 615 win_req_t req;
612 memreq_t mem; 616 memreq_t mem;
613 u_char __iomem *base; 617 int i;
614 int i, j;
615 struct net_device *dev = link->priv; 618 struct net_device *dev = link->priv;
616 unsigned int ioaddr; 619 unsigned int ioaddr;
620 local_info_t *lp = netdev_priv(dev);
617 621
618 /* Allocate a small memory window */ 622 /* Allocate a small memory window */
619 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; 623 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)
625 return -1; 629 return -1;
626 } 630 }
627 631
628 base = ioremap(req.Base, req.Size); 632 lp->base = ioremap(req.Base, req.Size);
633 if (lp->base == NULL) {
634 printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
635 return -1;
636 }
637
629 mem.Page = 0; 638 mem.Page = 0;
630 mem.CardOffset = 0; 639 mem.CardOffset = 0;
631 pcmcia_map_mem_page(link->win, &mem); 640 i = pcmcia_map_mem_page(link->win, &mem);
632 641 if (i != 0) {
642 iounmap(lp->base);
643 lp->base = NULL;
644 cs_error(link, MapMemPage, i);
645 return -1;
646 }
647
633 ioaddr = dev->base_addr; 648 ioaddr = dev->base_addr;
634 writeb(0x47, base+0x800); /* Config Option Register of LAN */ 649 writeb(0x47, lp->base+0x800); /* Config Option Register of LAN */
635 writeb(0x0, base+0x802); /* Config and Status Register */ 650 writeb(0x0, lp->base+0x802); /* Config and Status Register */
636 651
637 writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */ 652 writeb(ioaddr & 0xff, lp->base+0x80a); /* I/O Base(Low) of LAN */
638 writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */ 653 writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
639 654
640 writeb(0x45, base+0x820); /* Config Option Register of Modem */ 655 writeb(0x45, lp->base+0x820); /* Config Option Register of Modem */
641 writeb(0x8, base+0x822); /* Config and Status Register */ 656 writeb(0x8, lp->base+0x822); /* Config and Status Register */
642 657
643 iounmap(base);
644 j = pcmcia_release_window(link->win);
645 if (j != 0)
646 cs_error(link, ReleaseWindow, j);
647 return 0; 658 return 0;
648 659
649} 660}
@@ -651,8 +662,25 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
651 662
652static void fmvj18x_release(struct pcmcia_device *link) 663static void fmvj18x_release(struct pcmcia_device *link)
653{ 664{
654 DEBUG(0, "fmvj18x_release(0x%p)\n", link); 665
655 pcmcia_disable_device(link); 666 struct net_device *dev = link->priv;
667 local_info_t *lp = netdev_priv(dev);
668 u_char __iomem *tmp;
669 int j;
670
671 DEBUG(0, "fmvj18x_release(0x%p)\n", link);
672
673 if (lp->base != NULL) {
674 tmp = lp->base;
675 lp->base = NULL; /* set NULL before iounmap */
676 iounmap(tmp);
677 j = pcmcia_release_window(link->win);
678 if (j != 0)
679 cs_error(link, ReleaseWindow, j);
680 }
681
682 pcmcia_disable_device(link);
683
656} 684}
657 685
658static int fmvj18x_suspend(struct pcmcia_device *link) 686static int fmvj18x_suspend(struct pcmcia_device *link)
@@ -783,6 +811,13 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
783 811
784 outb(D_TX_INTR, ioaddr + TX_INTR); 812 outb(D_TX_INTR, ioaddr + TX_INTR);
785 outb(D_RX_INTR, ioaddr + RX_INTR); 813 outb(D_RX_INTR, ioaddr + RX_INTR);
814
815 if (lp->base != NULL) {
816 /* Ack interrupt for multifunction card */
817 writeb(0x01, lp->base+0x802);
818 writeb(0x09, lp->base+0x822);
819 }
820
786 return IRQ_HANDLED; 821 return IRQ_HANDLED;
787 822
788} /* fjn_interrupt */ 823} /* fjn_interrupt */