X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Firda%2Fnsc-ircc.c;fp=drivers%2Fnet%2Firda%2Fnsc-ircc.c;h=ee717d0e939e5e016726b112b18c914363ce3223;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=cb62f2a9676aeb7d46395c162aed054939f93de5;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index cb62f2a96..ee717d0e9 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -12,7 +12,6 @@ * Copyright (c) 1998-2000 Dag Brattli * Copyright (c) 1998 Lichen Wang, * Copyright (c) 1998 Actisys Corp., www.actisys.com - * Copyright (c) 2000-2004 Jean Tourrilhes * All Rights Reserved * * This program is free software; you can redistribute it and/or @@ -54,13 +53,14 @@ #include #include #include -#include -#include #include #include #include +#include +#include + #include #include #include @@ -72,27 +72,14 @@ static char *driver_name = "nsc-ircc"; -/* Power Management */ -#define NSC_IRCC_DRIVER_NAME "nsc-ircc" -static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); -static int nsc_ircc_resume(struct platform_device *dev); - -static struct platform_driver nsc_ircc_driver = { - .suspend = nsc_ircc_suspend, - .resume = nsc_ircc_resume, - .driver = { - .name = NSC_IRCC_DRIVER_NAME, - }, -}; - /* Module parameters */ static int qos_mtt_bits = 0x07; /* 1 ms or more */ static int dongle_id; /* Use BIOS settions by default, but user may supply module parameters */ -static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 }; -static unsigned int irq[] = { 0, 0, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0, 0 }; +static unsigned int io[] = { ~0, ~0, ~0, ~0 }; +static unsigned int irq[] = { 0, 0, 0, 0, 0 }; +static unsigned int dma[] = { 0, 0, 0, 0, 0 }; static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); @@ -100,7 +87,6 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); /* These are the known NSC chips */ static nsc_chip_t chips[] = { @@ -115,16 +101,11 @@ static nsc_chip_t chips[] = { /* Contributed by Jan Frey - IBM A30/A31 */ { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, nsc_ircc_probe_39x, nsc_ircc_init_39x }, - /* IBM ThinkPads using PC8738x (T60/X60/Z60) */ - { "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, - /* IBM ThinkPads using PC8394T (T43/R52/?) */ - { "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, { NULL } }; -static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL }; +/* Max 4 instances for now */ +static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; static char *dongle_types[] = { "Differential serial interface", @@ -145,24 +126,8 @@ static char *dongle_types[] = { "No dongle connected", }; -/* PNP probing */ -static chipio_t pnp_info; -static const struct pnp_device_id nsc_ircc_pnp_table[] = { - { .id = "NSC6001", .driver_data = 0 }, - { .id = "IBM0071", .driver_data = 0 }, - { } -}; - -MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); - -static struct pnp_driver nsc_ircc_pnp_driver = { - .name = "nsc-ircc", - .id_table = nsc_ircc_pnp_table, - .probe = nsc_ircc_pnp_probe, -}; - /* Some prototypes */ -static int nsc_ircc_open(chipio_t *info); +static int nsc_ircc_open(int i, chipio_t *info); static int nsc_ircc_close(struct nsc_ircc_cb *self); static int nsc_ircc_setup(chipio_t *info); static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); @@ -181,10 +146,7 @@ static int nsc_ircc_net_open(struct net_device *dev); static int nsc_ircc_net_close(struct net_device *dev); static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); - -/* Globals */ -static int pnp_registered; -static int pnp_succeeded; +static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); /* * Function nsc_ircc_init () @@ -196,36 +158,28 @@ static int __init nsc_ircc_init(void) { chipio_t info; nsc_chip_t *chip; - int ret; + int ret = -ENODEV; int cfg_base; int cfg, id; int reg; int i = 0; - ret = platform_driver_register(&nsc_ircc_driver); - if (ret) { - IRDA_ERROR("%s, Can't register driver!\n", driver_name); - return ret; - } - - /* Register with PnP subsystem to detect disable ports */ - ret = pnp_register_driver(&nsc_ircc_pnp_driver); - - if (!ret) - pnp_registered = 1; - - ret = -ENODEV; - /* Probe for all the NSC chipsets we know about */ - for (chip = chips; chip->name ; chip++) { + for (chip=chips; chip->name ; chip++) { IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, chip->name); /* Try all config registers for this chip */ - for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { + for (cfg=0; cfg<3; cfg++) { cfg_base = chip->cfg[cfg]; if (!cfg_base) continue; + + memset(&info, 0, sizeof(chipio_t)); + info.cfg_base = cfg_base; + info.fir_base = io[i]; + info.dma = dma[i]; + info.irq = irq[i]; /* Read index register */ reg = inb(cfg_base); @@ -240,65 +194,24 @@ static int __init nsc_ircc_init(void) if ((id & chip->cid_mask) == chip->cid_value) { IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", __FUNCTION__, chip->name, id & ~chip->cid_mask); + /* + * If the user supplies the base address, then + * we init the chip, if not we probe the values + * set by the BIOS + */ + if (io[i] < 0x2000) { + chip->init(chip, &info); + } else + chip->probe(chip, &info); - /* - * If we found a correct PnP setting, - * we first try it. - */ - if (pnp_succeeded) { - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = pnp_info.fir_base; - info.dma = pnp_info.dma; - info.irq = pnp_info.irq; - - if (info.fir_base < 0x2000) { - IRDA_MESSAGE("%s, chip->init\n", driver_name); - chip->init(chip, &info); - } else - chip->probe(chip, &info); - - if (nsc_ircc_open(&info) >= 0) - ret = 0; - } - - /* - * Opening based on PnP values failed. - * Let's fallback to user values, or probe - * the chip. - */ - if (ret) { - IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = io[i]; - info.dma = dma[i]; - info.irq = irq[i]; - - /* - * If the user supplies the base address, then - * we init the chip, if not we probe the values - * set by the BIOS - */ - if (io[i] < 0x2000) { - chip->init(chip, &info); - } else - chip->probe(chip, &info); - - if (nsc_ircc_open(&info) >= 0) - ret = 0; - } + if (nsc_ircc_open(i, &info) == 0) + ret = 0; i++; } else { IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); } } - } - - if (ret) { - platform_driver_unregister(&nsc_ircc_driver); - pnp_unregister_driver(&nsc_ircc_pnp_driver); - pnp_registered = 0; + } return ret; @@ -314,17 +227,12 @@ static void __exit nsc_ircc_cleanup(void) { int i; - for (i = 0; i < ARRAY_SIZE(dev_self); i++) { + pm_unregister_all(nsc_ircc_pmproc); + + for (i=0; i < 4; i++) { if (dev_self[i]) nsc_ircc_close(dev_self[i]); } - - platform_driver_unregister(&nsc_ircc_driver); - - if (pnp_registered) - pnp_unregister_driver(&nsc_ircc_pnp_driver); - - pnp_registered = 0; } /* @@ -333,26 +241,16 @@ static void __exit nsc_ircc_cleanup(void) * Open driver instance * */ -static int __init nsc_ircc_open(chipio_t *info) +static int __init nsc_ircc_open(int i, chipio_t *info) { struct net_device *dev; struct nsc_ircc_cb *self; + struct pm_dev *pmdev; void *ret; - int err, chip_index; + int err; IRDA_DEBUG(2, "%s()\n", __FUNCTION__); - - for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { - if (!dev_self[chip_index]) - break; - } - - if (chip_index == ARRAY_SIZE(dev_self)) { - IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__); - return -ENOMEM; - } - IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base); @@ -373,8 +271,8 @@ static int __init nsc_ircc_open(chipio_t *info) spin_lock_init(&self->lock); /* Need to store self somewhere */ - dev_self[chip_index] = self; - self->index = chip_index; + dev_self[i] = self; + self->index = i; /* Initialize IO */ self->io.cfg_base = info->cfg_base; @@ -453,7 +351,7 @@ static int __init nsc_ircc_open(chipio_t *info) /* Check if user has supplied a valid dongle id or not */ if ((dongle_id <= 0) || - (dongle_id >= ARRAY_SIZE(dongle_types))) { + (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, @@ -466,18 +364,11 @@ static int __init nsc_ircc_open(chipio_t *info) self->io.dongle_id = dongle_id; nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); - self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, - self->index, NULL, 0); - if (IS_ERR(self->pldev)) { - err = PTR_ERR(self->pldev); - goto out5; - } - platform_set_drvdata(self->pldev, self); - - return chip_index; + pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); + if (pmdev) + pmdev->data = self; - out5: - unregister_netdev(dev); + return 0; out4: dma_free_coherent(NULL, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); @@ -488,7 +379,7 @@ static int __init nsc_ircc_open(chipio_t *info) release_region(self->io.fir_base, self->io.fir_ext); out1: free_netdev(dev); - dev_self[chip_index] = NULL; + dev_self[i] = NULL; return err; } @@ -508,8 +399,6 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) iobase = self->io.fir_base; - platform_device_unregister(self->pldev); - /* Remove netdevice */ unregister_netdev(self->netdev); @@ -816,7 +705,7 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) int cfg_base = info->cfg_base; int enabled; - /* User is sure about his config... accept it. */ + /* User is shure about his config... accept it. */ IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " "io=0x%04x, irq=%d, dma=%d\n", __FUNCTION__, info->fir_base, info->irq, info->dma); @@ -917,43 +806,6 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) return 0; } -/* PNP probing */ -static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) -{ - memset(&pnp_info, 0, sizeof(chipio_t)); - pnp_info.irq = -1; - pnp_info.dma = -1; - pnp_succeeded = 1; - - /* There don't seem to be any way to get the cfg_base. - * On my box, cfg_base is in the PnP descriptor of the - * motherboard. Oh well... Jean II */ - - if (pnp_port_valid(dev, 0) && - !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.fir_base = pnp_port_start(dev, 0); - - if (pnp_irq_valid(dev, 0) && - !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.irq = pnp_irq(dev, 0); - - if (pnp_dma_valid(dev, 0) && - !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.dma = pnp_dma(dev, 0); - - IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", - __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); - - if((pnp_info.fir_base == 0) || - (pnp_info.irq == -1) || (pnp_info.dma == -1)) { - /* Returning an error will disable the device. Yuck ! */ - //return -EINVAL; - pnp_succeeded = 0; - } - - return 0; -} - /* * Function nsc_ircc_setup (info) * @@ -2309,83 +2161,45 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev) return &self->stats; } -static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) +static void nsc_ircc_suspend(struct nsc_ircc_cb *self) { - struct nsc_ircc_cb *self = platform_get_drvdata(dev); - int bank; - unsigned long flags; - int iobase = self->io.fir_base; + IRDA_MESSAGE("%s, Suspending\n", driver_name); if (self->io.suspended) - return 0; - - IRDA_DEBUG(1, "%s, Suspending\n", driver_name); - - rtnl_lock(); - if (netif_running(self->netdev)) { - netif_device_detach(self->netdev); - spin_lock_irqsave(&self->lock, flags); - /* Save current bank */ - bank = inb(iobase+BSR); + return; - /* Disable interrupts */ - switch_bank(iobase, BANK0); - outb(0, iobase+IER); - - /* Restore bank register */ - outb(bank, iobase+BSR); + nsc_ircc_net_close(self->netdev); - spin_unlock_irqrestore(&self->lock, flags); - free_irq(self->io.irq, self->netdev); - disable_dma(self->io.dma); - } self->io.suspended = 1; - rtnl_unlock(); - - return 0; } -static int nsc_ircc_resume(struct platform_device *dev) +static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) { - struct nsc_ircc_cb *self = platform_get_drvdata(dev); - unsigned long flags; - if (!self->io.suspended) - return 0; + return; - IRDA_DEBUG(1, "%s, Waking up\n", driver_name); - - rtnl_lock(); nsc_ircc_setup(&self->io); - nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); - - if (netif_running(self->netdev)) { - if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, - self->netdev->name, self->netdev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); - - /* - * Don't fail resume process, just kill this - * network interface - */ - unregister_netdevice(self->netdev); - } else { - spin_lock_irqsave(&self->lock, flags); - nsc_ircc_change_speed(self, self->io.speed); - spin_unlock_irqrestore(&self->lock, flags); - netif_device_attach(self->netdev); - } + nsc_ircc_net_open(self->netdev); + + IRDA_MESSAGE("%s, Waking up\n", driver_name); - } else { - spin_lock_irqsave(&self->lock, flags); - nsc_ircc_change_speed(self, 9600); - spin_unlock_irqrestore(&self->lock, flags); - } self->io.suspended = 0; - rtnl_unlock(); +} - return 0; +static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data; + if (self) { + switch (rqst) { + case PM_SUSPEND: + nsc_ircc_suspend(self); + break; + case PM_RESUME: + nsc_ircc_wakeup(self); + break; + } + } + return 0; } MODULE_AUTHOR("Dag Brattli ");