diff options
Diffstat (limited to 'drivers/net/irda/nsc-ircc.c')
-rw-r--r-- | drivers/net/irda/nsc-ircc.c | 320 |
1 files changed, 251 insertions, 69 deletions
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index ee717d0e939e..83141a3ff546 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> | 12 | * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> |
13 | * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> | 13 | * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> |
14 | * Copyright (c) 1998 Actisys Corp., www.actisys.com | 14 | * Copyright (c) 1998 Actisys Corp., www.actisys.com |
15 | * Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.com> | ||
15 | * All Rights Reserved | 16 | * All Rights Reserved |
16 | * | 17 | * |
17 | * This program is free software; you can redistribute it and/or | 18 | * This program is free software; you can redistribute it and/or |
@@ -53,14 +54,13 @@ | |||
53 | #include <linux/init.h> | 54 | #include <linux/init.h> |
54 | #include <linux/rtnetlink.h> | 55 | #include <linux/rtnetlink.h> |
55 | #include <linux/dma-mapping.h> | 56 | #include <linux/dma-mapping.h> |
57 | #include <linux/pnp.h> | ||
58 | #include <linux/platform_device.h> | ||
56 | 59 | ||
57 | #include <asm/io.h> | 60 | #include <asm/io.h> |
58 | #include <asm/dma.h> | 61 | #include <asm/dma.h> |
59 | #include <asm/byteorder.h> | 62 | #include <asm/byteorder.h> |
60 | 63 | ||
61 | #include <linux/pm.h> | ||
62 | #include <linux/pm_legacy.h> | ||
63 | |||
64 | #include <net/irda/wrapper.h> | 64 | #include <net/irda/wrapper.h> |
65 | #include <net/irda/irda.h> | 65 | #include <net/irda/irda.h> |
66 | #include <net/irda/irda_device.h> | 66 | #include <net/irda/irda_device.h> |
@@ -72,14 +72,27 @@ | |||
72 | 72 | ||
73 | static char *driver_name = "nsc-ircc"; | 73 | static char *driver_name = "nsc-ircc"; |
74 | 74 | ||
75 | /* Power Management */ | ||
76 | #define NSC_IRCC_DRIVER_NAME "nsc-ircc" | ||
77 | static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); | ||
78 | static int nsc_ircc_resume(struct platform_device *dev); | ||
79 | |||
80 | static struct platform_driver nsc_ircc_driver = { | ||
81 | .suspend = nsc_ircc_suspend, | ||
82 | .resume = nsc_ircc_resume, | ||
83 | .driver = { | ||
84 | .name = NSC_IRCC_DRIVER_NAME, | ||
85 | }, | ||
86 | }; | ||
87 | |||
75 | /* Module parameters */ | 88 | /* Module parameters */ |
76 | static int qos_mtt_bits = 0x07; /* 1 ms or more */ | 89 | static int qos_mtt_bits = 0x07; /* 1 ms or more */ |
77 | static int dongle_id; | 90 | static int dongle_id; |
78 | 91 | ||
79 | /* Use BIOS settions by default, but user may supply module parameters */ | 92 | /* Use BIOS settions by default, but user may supply module parameters */ |
80 | static unsigned int io[] = { ~0, ~0, ~0, ~0 }; | 93 | static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 }; |
81 | static unsigned int irq[] = { 0, 0, 0, 0, 0 }; | 94 | static unsigned int irq[] = { 0, 0, 0, 0, 0 }; |
82 | static unsigned int dma[] = { 0, 0, 0, 0, 0 }; | 95 | static unsigned int dma[] = { 0, 0, 0, 0, 0 }; |
83 | 96 | ||
84 | static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); | 97 | static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); |
85 | static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); | 98 | static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); |
@@ -87,6 +100,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); | |||
87 | static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); | 100 | static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); |
88 | static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); | 101 | static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); |
89 | static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); | 102 | static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); |
103 | static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); | ||
90 | 104 | ||
91 | /* These are the known NSC chips */ | 105 | /* These are the known NSC chips */ |
92 | static nsc_chip_t chips[] = { | 106 | static nsc_chip_t chips[] = { |
@@ -101,11 +115,12 @@ static nsc_chip_t chips[] = { | |||
101 | /* Contributed by Jan Frey - IBM A30/A31 */ | 115 | /* Contributed by Jan Frey - IBM A30/A31 */ |
102 | { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, | 116 | { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, |
103 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, | 117 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, |
118 | { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, | ||
119 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, | ||
104 | { NULL } | 120 | { NULL } |
105 | }; | 121 | }; |
106 | 122 | ||
107 | /* Max 4 instances for now */ | 123 | static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL }; |
108 | static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; | ||
109 | 124 | ||
110 | static char *dongle_types[] = { | 125 | static char *dongle_types[] = { |
111 | "Differential serial interface", | 126 | "Differential serial interface", |
@@ -126,8 +141,24 @@ static char *dongle_types[] = { | |||
126 | "No dongle connected", | 141 | "No dongle connected", |
127 | }; | 142 | }; |
128 | 143 | ||
144 | /* PNP probing */ | ||
145 | static chipio_t pnp_info; | ||
146 | static const struct pnp_device_id nsc_ircc_pnp_table[] = { | ||
147 | { .id = "NSC6001", .driver_data = 0 }, | ||
148 | { .id = "IBM0071", .driver_data = 0 }, | ||
149 | { } | ||
150 | }; | ||
151 | |||
152 | MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); | ||
153 | |||
154 | static struct pnp_driver nsc_ircc_pnp_driver = { | ||
155 | .name = "nsc-ircc", | ||
156 | .id_table = nsc_ircc_pnp_table, | ||
157 | .probe = nsc_ircc_pnp_probe, | ||
158 | }; | ||
159 | |||
129 | /* Some prototypes */ | 160 | /* Some prototypes */ |
130 | static int nsc_ircc_open(int i, chipio_t *info); | 161 | static int nsc_ircc_open(chipio_t *info); |
131 | static int nsc_ircc_close(struct nsc_ircc_cb *self); | 162 | static int nsc_ircc_close(struct nsc_ircc_cb *self); |
132 | static int nsc_ircc_setup(chipio_t *info); | 163 | static int nsc_ircc_setup(chipio_t *info); |
133 | static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); | 164 | static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); |
@@ -146,7 +177,10 @@ static int nsc_ircc_net_open(struct net_device *dev); | |||
146 | static int nsc_ircc_net_close(struct net_device *dev); | 177 | static int nsc_ircc_net_close(struct net_device *dev); |
147 | static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 178 | static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
148 | static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); | 179 | static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); |
149 | static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | 180 | |
181 | /* Globals */ | ||
182 | static int pnp_registered; | ||
183 | static int pnp_succeeded; | ||
150 | 184 | ||
151 | /* | 185 | /* |
152 | * Function nsc_ircc_init () | 186 | * Function nsc_ircc_init () |
@@ -158,28 +192,36 @@ static int __init nsc_ircc_init(void) | |||
158 | { | 192 | { |
159 | chipio_t info; | 193 | chipio_t info; |
160 | nsc_chip_t *chip; | 194 | nsc_chip_t *chip; |
161 | int ret = -ENODEV; | 195 | int ret; |
162 | int cfg_base; | 196 | int cfg_base; |
163 | int cfg, id; | 197 | int cfg, id; |
164 | int reg; | 198 | int reg; |
165 | int i = 0; | 199 | int i = 0; |
166 | 200 | ||
201 | ret = platform_driver_register(&nsc_ircc_driver); | ||
202 | if (ret) { | ||
203 | IRDA_ERROR("%s, Can't register driver!\n", driver_name); | ||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | /* Register with PnP subsystem to detect disable ports */ | ||
208 | ret = pnp_register_driver(&nsc_ircc_pnp_driver); | ||
209 | |||
210 | if (ret >= 0) | ||
211 | pnp_registered = 1; | ||
212 | |||
213 | ret = -ENODEV; | ||
214 | |||
167 | /* Probe for all the NSC chipsets we know about */ | 215 | /* Probe for all the NSC chipsets we know about */ |
168 | for (chip=chips; chip->name ; chip++) { | 216 | for (chip = chips; chip->name ; chip++) { |
169 | IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, | 217 | IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, |
170 | chip->name); | 218 | chip->name); |
171 | 219 | ||
172 | /* Try all config registers for this chip */ | 220 | /* Try all config registers for this chip */ |
173 | for (cfg=0; cfg<3; cfg++) { | 221 | for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { |
174 | cfg_base = chip->cfg[cfg]; | 222 | cfg_base = chip->cfg[cfg]; |
175 | if (!cfg_base) | 223 | if (!cfg_base) |
176 | continue; | 224 | continue; |
177 | |||
178 | memset(&info, 0, sizeof(chipio_t)); | ||
179 | info.cfg_base = cfg_base; | ||
180 | info.fir_base = io[i]; | ||
181 | info.dma = dma[i]; | ||
182 | info.irq = irq[i]; | ||
183 | 225 | ||
184 | /* Read index register */ | 226 | /* Read index register */ |
185 | reg = inb(cfg_base); | 227 | reg = inb(cfg_base); |
@@ -194,24 +236,65 @@ static int __init nsc_ircc_init(void) | |||
194 | if ((id & chip->cid_mask) == chip->cid_value) { | 236 | if ((id & chip->cid_mask) == chip->cid_value) { |
195 | IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", | 237 | IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", |
196 | __FUNCTION__, chip->name, id & ~chip->cid_mask); | 238 | __FUNCTION__, chip->name, id & ~chip->cid_mask); |
197 | /* | ||
198 | * If the user supplies the base address, then | ||
199 | * we init the chip, if not we probe the values | ||
200 | * set by the BIOS | ||
201 | */ | ||
202 | if (io[i] < 0x2000) { | ||
203 | chip->init(chip, &info); | ||
204 | } else | ||
205 | chip->probe(chip, &info); | ||
206 | 239 | ||
207 | if (nsc_ircc_open(i, &info) == 0) | 240 | /* |
208 | ret = 0; | 241 | * If we found a correct PnP setting, |
242 | * we first try it. | ||
243 | */ | ||
244 | if (pnp_succeeded) { | ||
245 | memset(&info, 0, sizeof(chipio_t)); | ||
246 | info.cfg_base = cfg_base; | ||
247 | info.fir_base = pnp_info.fir_base; | ||
248 | info.dma = pnp_info.dma; | ||
249 | info.irq = pnp_info.irq; | ||
250 | |||
251 | if (info.fir_base < 0x2000) { | ||
252 | IRDA_MESSAGE("%s, chip->init\n", driver_name); | ||
253 | chip->init(chip, &info); | ||
254 | } else | ||
255 | chip->probe(chip, &info); | ||
256 | |||
257 | if (nsc_ircc_open(&info) >= 0) | ||
258 | ret = 0; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * Opening based on PnP values failed. | ||
263 | * Let's fallback to user values, or probe | ||
264 | * the chip. | ||
265 | */ | ||
266 | if (ret) { | ||
267 | IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); | ||
268 | memset(&info, 0, sizeof(chipio_t)); | ||
269 | info.cfg_base = cfg_base; | ||
270 | info.fir_base = io[i]; | ||
271 | info.dma = dma[i]; | ||
272 | info.irq = irq[i]; | ||
273 | |||
274 | /* | ||
275 | * If the user supplies the base address, then | ||
276 | * we init the chip, if not we probe the values | ||
277 | * set by the BIOS | ||
278 | */ | ||
279 | if (io[i] < 0x2000) { | ||
280 | chip->init(chip, &info); | ||
281 | } else | ||
282 | chip->probe(chip, &info); | ||
283 | |||
284 | if (nsc_ircc_open(&info) >= 0) | ||
285 | ret = 0; | ||
286 | } | ||
209 | i++; | 287 | i++; |
210 | } else { | 288 | } else { |
211 | IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); | 289 | IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); |
212 | } | 290 | } |
213 | } | 291 | } |
214 | 292 | } | |
293 | |||
294 | if (ret) { | ||
295 | platform_driver_unregister(&nsc_ircc_driver); | ||
296 | pnp_unregister_driver(&nsc_ircc_pnp_driver); | ||
297 | pnp_registered = 0; | ||
215 | } | 298 | } |
216 | 299 | ||
217 | return ret; | 300 | return ret; |
@@ -227,12 +310,17 @@ static void __exit nsc_ircc_cleanup(void) | |||
227 | { | 310 | { |
228 | int i; | 311 | int i; |
229 | 312 | ||
230 | pm_unregister_all(nsc_ircc_pmproc); | 313 | for (i = 0; i < ARRAY_SIZE(dev_self); i++) { |
231 | |||
232 | for (i=0; i < 4; i++) { | ||
233 | if (dev_self[i]) | 314 | if (dev_self[i]) |
234 | nsc_ircc_close(dev_self[i]); | 315 | nsc_ircc_close(dev_self[i]); |
235 | } | 316 | } |
317 | |||
318 | platform_driver_unregister(&nsc_ircc_driver); | ||
319 | |||
320 | if (pnp_registered) | ||
321 | pnp_unregister_driver(&nsc_ircc_pnp_driver); | ||
322 | |||
323 | pnp_registered = 0; | ||
236 | } | 324 | } |
237 | 325 | ||
238 | /* | 326 | /* |
@@ -241,16 +329,26 @@ static void __exit nsc_ircc_cleanup(void) | |||
241 | * Open driver instance | 329 | * Open driver instance |
242 | * | 330 | * |
243 | */ | 331 | */ |
244 | static int __init nsc_ircc_open(int i, chipio_t *info) | 332 | static int __init nsc_ircc_open(chipio_t *info) |
245 | { | 333 | { |
246 | struct net_device *dev; | 334 | struct net_device *dev; |
247 | struct nsc_ircc_cb *self; | 335 | struct nsc_ircc_cb *self; |
248 | struct pm_dev *pmdev; | ||
249 | void *ret; | 336 | void *ret; |
250 | int err; | 337 | int err, chip_index; |
251 | 338 | ||
252 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | 339 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); |
253 | 340 | ||
341 | |||
342 | for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { | ||
343 | if (!dev_self[chip_index]) | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | if (chip_index == ARRAY_SIZE(dev_self)) { | ||
348 | IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__); | ||
349 | return -ENOMEM; | ||
350 | } | ||
351 | |||
254 | IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, | 352 | IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, |
255 | info->cfg_base); | 353 | info->cfg_base); |
256 | 354 | ||
@@ -271,8 +369,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
271 | spin_lock_init(&self->lock); | 369 | spin_lock_init(&self->lock); |
272 | 370 | ||
273 | /* Need to store self somewhere */ | 371 | /* Need to store self somewhere */ |
274 | dev_self[i] = self; | 372 | dev_self[chip_index] = self; |
275 | self->index = i; | 373 | self->index = chip_index; |
276 | 374 | ||
277 | /* Initialize IO */ | 375 | /* Initialize IO */ |
278 | self->io.cfg_base = info->cfg_base; | 376 | self->io.cfg_base = info->cfg_base; |
@@ -351,7 +449,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
351 | 449 | ||
352 | /* Check if user has supplied a valid dongle id or not */ | 450 | /* Check if user has supplied a valid dongle id or not */ |
353 | if ((dongle_id <= 0) || | 451 | if ((dongle_id <= 0) || |
354 | (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { | 452 | (dongle_id >= ARRAY_SIZE(dongle_types))) { |
355 | dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); | 453 | dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); |
356 | 454 | ||
357 | IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, | 455 | IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, |
@@ -364,11 +462,18 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
364 | self->io.dongle_id = dongle_id; | 462 | self->io.dongle_id = dongle_id; |
365 | nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); | 463 | nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); |
366 | 464 | ||
367 | pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); | 465 | self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, |
368 | if (pmdev) | 466 | self->index, NULL, 0); |
369 | pmdev->data = self; | 467 | if (IS_ERR(self->pldev)) { |
468 | err = PTR_ERR(self->pldev); | ||
469 | goto out5; | ||
470 | } | ||
471 | platform_set_drvdata(self->pldev, self); | ||
370 | 472 | ||
371 | return 0; | 473 | return chip_index; |
474 | |||
475 | out5: | ||
476 | unregister_netdev(dev); | ||
372 | out4: | 477 | out4: |
373 | dma_free_coherent(NULL, self->tx_buff.truesize, | 478 | dma_free_coherent(NULL, self->tx_buff.truesize, |
374 | self->tx_buff.head, self->tx_buff_dma); | 479 | self->tx_buff.head, self->tx_buff_dma); |
@@ -379,7 +484,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
379 | release_region(self->io.fir_base, self->io.fir_ext); | 484 | release_region(self->io.fir_base, self->io.fir_ext); |
380 | out1: | 485 | out1: |
381 | free_netdev(dev); | 486 | free_netdev(dev); |
382 | dev_self[i] = NULL; | 487 | dev_self[chip_index] = NULL; |
383 | return err; | 488 | return err; |
384 | } | 489 | } |
385 | 490 | ||
@@ -399,6 +504,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) | |||
399 | 504 | ||
400 | iobase = self->io.fir_base; | 505 | iobase = self->io.fir_base; |
401 | 506 | ||
507 | platform_device_unregister(self->pldev); | ||
508 | |||
402 | /* Remove netdevice */ | 509 | /* Remove netdevice */ |
403 | unregister_netdev(self->netdev); | 510 | unregister_netdev(self->netdev); |
404 | 511 | ||
@@ -806,6 +913,43 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) | |||
806 | return 0; | 913 | return 0; |
807 | } | 914 | } |
808 | 915 | ||
916 | /* PNP probing */ | ||
917 | static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) | ||
918 | { | ||
919 | memset(&pnp_info, 0, sizeof(chipio_t)); | ||
920 | pnp_info.irq = -1; | ||
921 | pnp_info.dma = -1; | ||
922 | pnp_succeeded = 1; | ||
923 | |||
924 | /* There don't seem to be any way to get the cfg_base. | ||
925 | * On my box, cfg_base is in the PnP descriptor of the | ||
926 | * motherboard. Oh well... Jean II */ | ||
927 | |||
928 | if (pnp_port_valid(dev, 0) && | ||
929 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
930 | pnp_info.fir_base = pnp_port_start(dev, 0); | ||
931 | |||
932 | if (pnp_irq_valid(dev, 0) && | ||
933 | !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
934 | pnp_info.irq = pnp_irq(dev, 0); | ||
935 | |||
936 | if (pnp_dma_valid(dev, 0) && | ||
937 | !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
938 | pnp_info.dma = pnp_dma(dev, 0); | ||
939 | |||
940 | IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", | ||
941 | __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); | ||
942 | |||
943 | if((pnp_info.fir_base == 0) || | ||
944 | (pnp_info.irq == -1) || (pnp_info.dma == -1)) { | ||
945 | /* Returning an error will disable the device. Yuck ! */ | ||
946 | //return -EINVAL; | ||
947 | pnp_succeeded = 0; | ||
948 | } | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
809 | /* | 953 | /* |
810 | * Function nsc_ircc_setup (info) | 954 | * Function nsc_ircc_setup (info) |
811 | * | 955 | * |
@@ -2161,45 +2305,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev) | |||
2161 | return &self->stats; | 2305 | return &self->stats; |
2162 | } | 2306 | } |
2163 | 2307 | ||
2164 | static void nsc_ircc_suspend(struct nsc_ircc_cb *self) | 2308 | static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) |
2165 | { | 2309 | { |
2166 | IRDA_MESSAGE("%s, Suspending\n", driver_name); | 2310 | struct nsc_ircc_cb *self = platform_get_drvdata(dev); |
2311 | int bank; | ||
2312 | unsigned long flags; | ||
2313 | int iobase = self->io.fir_base; | ||
2167 | 2314 | ||
2168 | if (self->io.suspended) | 2315 | if (self->io.suspended) |
2169 | return; | 2316 | return 0; |
2170 | 2317 | ||
2171 | nsc_ircc_net_close(self->netdev); | 2318 | IRDA_DEBUG(1, "%s, Suspending\n", driver_name); |
2172 | 2319 | ||
2320 | rtnl_lock(); | ||
2321 | if (netif_running(self->netdev)) { | ||
2322 | netif_device_detach(self->netdev); | ||
2323 | spin_lock_irqsave(&self->lock, flags); | ||
2324 | /* Save current bank */ | ||
2325 | bank = inb(iobase+BSR); | ||
2326 | |||
2327 | /* Disable interrupts */ | ||
2328 | switch_bank(iobase, BANK0); | ||
2329 | outb(0, iobase+IER); | ||
2330 | |||
2331 | /* Restore bank register */ | ||
2332 | outb(bank, iobase+BSR); | ||
2333 | |||
2334 | spin_unlock_irqrestore(&self->lock, flags); | ||
2335 | free_irq(self->io.irq, self->netdev); | ||
2336 | disable_dma(self->io.dma); | ||
2337 | } | ||
2173 | self->io.suspended = 1; | 2338 | self->io.suspended = 1; |
2339 | rtnl_unlock(); | ||
2340 | |||
2341 | return 0; | ||
2174 | } | 2342 | } |
2175 | 2343 | ||
2176 | static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) | 2344 | static int nsc_ircc_resume(struct platform_device *dev) |
2177 | { | 2345 | { |
2346 | struct nsc_ircc_cb *self = platform_get_drvdata(dev); | ||
2347 | unsigned long flags; | ||
2348 | |||
2178 | if (!self->io.suspended) | 2349 | if (!self->io.suspended) |
2179 | return; | 2350 | return 0; |
2180 | 2351 | ||
2352 | IRDA_DEBUG(1, "%s, Waking up\n", driver_name); | ||
2353 | |||
2354 | rtnl_lock(); | ||
2181 | nsc_ircc_setup(&self->io); | 2355 | nsc_ircc_setup(&self->io); |
2182 | nsc_ircc_net_open(self->netdev); | 2356 | nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); |
2183 | |||
2184 | IRDA_MESSAGE("%s, Waking up\n", driver_name); | ||
2185 | 2357 | ||
2358 | if (netif_running(self->netdev)) { | ||
2359 | if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, | ||
2360 | self->netdev->name, self->netdev)) { | ||
2361 | IRDA_WARNING("%s, unable to allocate irq=%d\n", | ||
2362 | driver_name, self->io.irq); | ||
2363 | |||
2364 | /* | ||
2365 | * Don't fail resume process, just kill this | ||
2366 | * network interface | ||
2367 | */ | ||
2368 | unregister_netdevice(self->netdev); | ||
2369 | } else { | ||
2370 | spin_lock_irqsave(&self->lock, flags); | ||
2371 | nsc_ircc_change_speed(self, self->io.speed); | ||
2372 | spin_unlock_irqrestore(&self->lock, flags); | ||
2373 | netif_device_attach(self->netdev); | ||
2374 | } | ||
2375 | |||
2376 | } else { | ||
2377 | spin_lock_irqsave(&self->lock, flags); | ||
2378 | nsc_ircc_change_speed(self, 9600); | ||
2379 | spin_unlock_irqrestore(&self->lock, flags); | ||
2380 | } | ||
2186 | self->io.suspended = 0; | 2381 | self->io.suspended = 0; |
2187 | } | 2382 | rtnl_unlock(); |
2188 | 2383 | ||
2189 | static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) | 2384 | return 0; |
2190 | { | ||
2191 | struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data; | ||
2192 | if (self) { | ||
2193 | switch (rqst) { | ||
2194 | case PM_SUSPEND: | ||
2195 | nsc_ircc_suspend(self); | ||
2196 | break; | ||
2197 | case PM_RESUME: | ||
2198 | nsc_ircc_wakeup(self); | ||
2199 | break; | ||
2200 | } | ||
2201 | } | ||
2202 | return 0; | ||
2203 | } | 2385 | } |
2204 | 2386 | ||
2205 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); | 2387 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); |