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 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 | ||
652 | static void fmvj18x_release(struct pcmcia_device *link) | 663 | static 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 | ||
658 | static int fmvj18x_suspend(struct pcmcia_device *link) | 686 | static 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 */ |