diff options
author | Pavel Roskin <proski@gnu.org> | 2006-04-07 04:10:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-04-24 16:15:52 -0400 |
commit | b884c872fa1917614b42a39020ffcca7fa9302b1 (patch) | |
tree | 82f5ba67f6b38c96804fb449e018d83fbdce65a1 /drivers/net/wireless/orinoco_tmd.c | |
parent | c6fb2e9abef894efc4870e4c1e3aa4365b830a11 (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.c | 165 |
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 */ | ||
70 | struct 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 | */ |
78 | static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | 73 | static 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) | |||
110 | static int orinoco_tmd_init_one(struct pci_dev *pdev, | 104 | static 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 | ||
218 | static int orinoco_tmd_suspend(struct pci_dev *pdev, pm_message_t state) | 218 | static 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 | |||
251 | static 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 | |||
296 | static 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 | ||
301 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); | 223 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table); |
302 | 224 | ||
303 | static struct pci_driver orinoco_tmd_driver = { | 225 | static 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 | ||
312 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 234 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
@@ -324,7 +246,6 @@ static int __init orinoco_tmd_init(void) | |||
324 | static void __exit orinoco_tmd_exit(void) | 246 | static 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 | ||
330 | module_init(orinoco_tmd_init); | 251 | module_init(orinoco_tmd_init); |