aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_tmd.c
diff options
context:
space:
mode:
authorPavel Roskin <proski@gnu.org>2006-04-07 04:10:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-04-24 16:15:52 -0400
commitb884c872fa1917614b42a39020ffcca7fa9302b1 (patch)
tree82f5ba67f6b38c96804fb449e018d83fbdce65a1 /drivers/net/wireless/orinoco_tmd.c
parentc6fb2e9abef894efc4870e4c1e3aa4365b830a11 (diff)
[PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h
Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and orinoco_nortel) as similar as possible. Use the best implementation of error handling, the best error messages, the best comments. Put common code to orinoco_pci.h. For now, it's suspend and resume functions and function for registering the network device. Signed-off-by: Pavel Roskin <proski@gnu.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco_tmd.c')
-rw-r--r--drivers/net/wireless/orinoco_tmd.c165
1 files changed, 43 insertions, 122 deletions
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index b74807d4141f..438fe545b184 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -1,5 +1,5 @@
1/* orinoco_tmd.c 1/* orinoco_tmd.c
2 * 2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs, 3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a TMD7160. 4 * but are connected to the PCI bus by a TMD7160.
5 * 5 *
@@ -29,14 +29,14 @@
29 29
30 * Caution: this is experimental and probably buggy. For success and 30 * Caution: this is experimental and probably buggy. For success and
31 * failure reports for different cards and adaptors, see 31 * failure reports for different cards and adaptors, see
32 * orinoco_tmd_pci_id_table near the end of the file. If you have a 32 * orinoco_tmd_id_table near the end of the file. If you have a
33 * card we don't have the PCI id for, and looks like it should work, 33 * card we don't have the PCI id for, and looks like it should work,
34 * drop me mail with the id and "it works"/"it doesn't work". 34 * drop me mail with the id and "it works"/"it doesn't work".
35 * 35 *
36 * Note: if everything gets detected fine but it doesn't actually send 36 * Note: if everything gets detected fine but it doesn't actually send
37 * or receive packets, your first port of call should probably be to 37 * or receive packets, your first port of call should probably be to
38 * try newer firmware in the card. Especially if you're doing Ad-Hoc 38 * try newer firmware in the card. Especially if you're doing Ad-Hoc
39 * modes 39 * modes.
40 * 40 *
41 * The actual driving is done by orinoco.c, this is just resource 41 * The actual driving is done by orinoco.c, this is just resource
42 * allocation stuff. 42 * allocation stuff.
@@ -61,32 +61,26 @@
61#include <pcmcia/cisreg.h> 61#include <pcmcia/cisreg.h>
62 62
63#include "orinoco.h" 63#include "orinoco.h"
64#include "orinoco_pci.h"
64 65
65#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ 66#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
66#define COR_RESET (0x80) /* reset bit in the COR register */ 67#define COR_RESET (0x80) /* reset bit in the COR register */
67#define TMD_RESET_TIME (500) /* milliseconds */ 68#define TMD_RESET_TIME (500) /* milliseconds */
68 69
69/* Orinoco TMD specific data */
70struct orinoco_tmd_card {
71 u32 tmd_io;
72};
73
74
75/* 70/*
76 * Do a soft reset of the card using the Configuration Option Register 71 * Do a soft reset of the card using the Configuration Option Register
77 */ 72 */
78static int orinoco_tmd_cor_reset(struct orinoco_private *priv) 73static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
79{ 74{
80 hermes_t *hw = &priv->hw; 75 hermes_t *hw = &priv->hw;
81 struct orinoco_tmd_card *card = priv->card; 76 struct orinoco_pci_card *card = priv->card;
82 u32 addr = card->tmd_io;
83 unsigned long timeout; 77 unsigned long timeout;
84 u16 reg; 78 u16 reg;
85 79
86 outb(COR_VALUE | COR_RESET, addr); 80 iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
87 mdelay(1); 81 mdelay(1);
88 82
89 outb(COR_VALUE, addr); 83 iowrite8(COR_VALUE, card->bridge_io);
90 mdelay(1); 84 mdelay(1);
91 85
92 /* Just in case, wait more until the card is no longer busy */ 86 /* Just in case, wait more until the card is no longer busy */
@@ -97,7 +91,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
97 reg = hermes_read_regn(hw, CMD); 91 reg = hermes_read_regn(hw, CMD);
98 } 92 }
99 93
100 /* Did we timeout ? */ 94 /* Still busy? */
101 if (reg & HERMES_CMD_BUSY) { 95 if (reg & HERMES_CMD_BUSY) {
102 printk(KERN_ERR PFX "Busy timeout\n"); 96 printk(KERN_ERR PFX "Busy timeout\n");
103 return -ETIMEDOUT; 97 return -ETIMEDOUT;
@@ -110,11 +104,11 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
110static int orinoco_tmd_init_one(struct pci_dev *pdev, 104static int orinoco_tmd_init_one(struct pci_dev *pdev,
111 const struct pci_device_id *ent) 105 const struct pci_device_id *ent)
112{ 106{
113 int err = 0; 107 int err;
114 struct orinoco_private *priv = NULL; 108 struct orinoco_private *priv;
115 struct orinoco_tmd_card *card; 109 struct orinoco_pci_card *card;
116 struct net_device *dev = NULL; 110 struct net_device *dev;
117 void __iomem *mem; 111 void __iomem *hermes_io, *bridge_io;
118 112
119 err = pci_enable_device(pdev); 113 err = pci_enable_device(pdev);
120 if (err) { 114 if (err) {
@@ -123,20 +117,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
123 } 117 }
124 118
125 err = pci_request_regions(pdev, DRIVER_NAME); 119 err = pci_request_regions(pdev, DRIVER_NAME);
126 if (err != 0) { 120 if (err) {
127 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 121 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
128 goto fail_resources; 122 goto fail_resources;
129 } 123 }
130 124
131 mem = pci_iomap(pdev, 2, 0); 125 bridge_io = pci_iomap(pdev, 1, 0);
132 if (! mem) { 126 if (!bridge_io) {
133 err = -ENOMEM; 127 printk(KERN_ERR PFX "Cannot map bridge registers\n");
134 goto fail_iomap; 128 err = -EIO;
129 goto fail_map_bridge;
130 }
131
132 hermes_io = pci_iomap(pdev, 2, 0);
133 if (!hermes_io) {
134 printk(KERN_ERR PFX "Cannot map chipset registers\n");
135 err = -EIO;
136 goto fail_map_hermes;
135 } 137 }
136 138
137 /* Allocate network device */ 139 /* Allocate network device */
138 dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); 140 dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
139 if (! dev) { 141 if (!dev) {
140 printk(KERN_ERR PFX "Cannot allocate network device\n"); 142 printk(KERN_ERR PFX "Cannot allocate network device\n");
141 err = -ENOMEM; 143 err = -ENOMEM;
142 goto fail_alloc; 144 goto fail_alloc;
@@ -144,16 +146,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
144 146
145 priv = netdev_priv(dev); 147 priv = netdev_priv(dev);
146 card = priv->card; 148 card = priv->card;
147 card->tmd_io = pci_resource_start(pdev, 1); 149 card->bridge_io = bridge_io;
148 dev->base_addr = pci_resource_start(pdev, 2);
149 SET_MODULE_OWNER(dev); 150 SET_MODULE_OWNER(dev);
150 SET_NETDEV_DEV(dev, &pdev->dev); 151 SET_NETDEV_DEV(dev, &pdev->dev);
151 152
152 hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); 153 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
153
154 printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
155 "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
156 dev->base_addr);
157 154
158 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 155 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
159 dev->name, dev); 156 dev->name, dev);
@@ -162,7 +159,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
162 err = -EBUSY; 159 err = -EBUSY;
163 goto fail_irq; 160 goto fail_irq;
164 } 161 }
165 dev->irq = pdev->irq; 162 orinoco_pci_setup_netdev(dev, pdev, 2);
166 163
167 err = orinoco_tmd_cor_reset(priv); 164 err = orinoco_tmd_cor_reset(priv);
168 if (err) { 165 if (err) {
@@ -188,9 +185,12 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
188 free_orinocodev(dev); 185 free_orinocodev(dev);
189 186
190 fail_alloc: 187 fail_alloc:
191 pci_iounmap(pdev, mem); 188 pci_iounmap(pdev, hermes_io);
192 189
193 fail_iomap: 190 fail_map_hermes:
191 pci_iounmap(pdev, bridge_io);
192
193 fail_map_bridge:
194 pci_release_regions(pdev); 194 pci_release_regions(pdev);
195 195
196 fail_resources: 196 fail_resources:
@@ -203,110 +203,32 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
203{ 203{
204 struct net_device *dev = pci_get_drvdata(pdev); 204 struct net_device *dev = pci_get_drvdata(pdev);
205 struct orinoco_private *priv = dev->priv; 205 struct orinoco_private *priv = dev->priv;
206 206 struct orinoco_pci_card *card = priv->card;
207 BUG_ON(! dev);
208 207
209 unregister_netdev(dev); 208 unregister_netdev(dev);
210 free_irq(dev->irq, dev); 209 free_irq(dev->irq, dev);
211 pci_set_drvdata(pdev, NULL); 210 pci_set_drvdata(pdev, NULL);
212 free_orinocodev(dev); 211 free_orinocodev(dev);
213 pci_iounmap(pdev, priv->hw.iobase); 212 pci_iounmap(pdev, priv->hw.iobase);
213 pci_iounmap(pdev, card->bridge_io);
214 pci_release_regions(pdev); 214 pci_release_regions(pdev);
215 pci_disable_device(pdev); 215 pci_disable_device(pdev);
216} 216}
217 217
218static int orinoco_tmd_suspend(struct pci_dev *pdev, pm_message_t state) 218static struct pci_device_id orinoco_tmd_id_table[] = {
219{
220 struct net_device *dev = pci_get_drvdata(pdev);
221 struct orinoco_private *priv = netdev_priv(dev);
222 unsigned long flags;
223 int err;
224
225 err = orinoco_lock(priv, &flags);
226 if (err) {
227 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
228 dev->name);
229 return err;
230 }
231
232 err = __orinoco_down(dev);
233 if (err)
234 printk(KERN_WARNING "%s: error %d bringing interface down "
235 "for suspend\n", dev->name, err);
236
237 netif_device_detach(dev);
238
239 priv->hw_unavailable++;
240
241 orinoco_unlock(priv, &flags);
242
243 free_irq(pdev->irq, dev);
244 pci_save_state(pdev);
245 pci_disable_device(pdev);
246 pci_set_power_state(pdev, PCI_D3hot);
247
248 return 0;
249}
250
251static int orinoco_tmd_resume(struct pci_dev *pdev)
252{
253 struct net_device *dev = pci_get_drvdata(pdev);
254 struct orinoco_private *priv = netdev_priv(dev);
255 unsigned long flags;
256 int err;
257
258 pci_set_power_state(pdev, 0);
259 pci_enable_device(pdev);
260 pci_restore_state(pdev);
261
262 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
263 dev->name, dev);
264 if (err) {
265 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
266 dev->name);
267 pci_disable_device(pdev);
268 return -EBUSY;
269 }
270
271 err = orinoco_reinit_firmware(dev);
272 if (err) {
273 printk(KERN_ERR "%s: error %d re-initializing firmware "
274 "on resume\n", dev->name, err);
275 return err;
276 }
277
278 spin_lock_irqsave(&priv->lock, flags);
279
280 netif_device_attach(dev);
281
282 priv->hw_unavailable--;
283
284 if (priv->open && (! priv->hw_unavailable)) {
285 err = __orinoco_up(dev);
286 if (err)
287 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
288 dev->name, err);
289 }
290
291 spin_unlock_irqrestore(&priv->lock, flags);
292
293 return 0;
294}
295
296static struct pci_device_id orinoco_tmd_pci_id_table[] = {
297 {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ 219 {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
298 {0,}, 220 {0,},
299}; 221};
300 222
301MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); 223MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
302 224
303static struct pci_driver orinoco_tmd_driver = { 225static struct pci_driver orinoco_tmd_driver = {
304 .name = DRIVER_NAME, 226 .name = DRIVER_NAME,
305 .id_table = orinoco_tmd_pci_id_table, 227 .id_table = orinoco_tmd_id_table,
306 .probe = orinoco_tmd_init_one, 228 .probe = orinoco_tmd_init_one,
307 .remove = __devexit_p(orinoco_tmd_remove_one), 229 .remove = __devexit_p(orinoco_tmd_remove_one),
308 .suspend = orinoco_tmd_suspend, 230 .suspend = orinoco_pci_suspend,
309 .resume = orinoco_tmd_resume, 231 .resume = orinoco_pci_resume,
310}; 232};
311 233
312static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION 234static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -324,7 +246,6 @@ static int __init orinoco_tmd_init(void)
324static void __exit orinoco_tmd_exit(void) 246static void __exit orinoco_tmd_exit(void)
325{ 247{
326 pci_unregister_driver(&orinoco_tmd_driver); 248 pci_unregister_driver(&orinoco_tmd_driver);
327 ssleep(1);
328} 249}
329 250
330module_init(orinoco_tmd_init); 251module_init(orinoco_tmd_init);