aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco_cs.c')
-rw-r--r--drivers/net/wireless/orinoco_cs.c163
1 files changed, 69 insertions, 94 deletions
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1c216e015f64..c7b57d9d499d 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -164,6 +164,70 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
164 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ 164 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
165 } while (0) 165 } while (0)
166 166
167static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
168 cistpl_cftable_entry_t *cfg,
169 cistpl_cftable_entry_t *dflt,
170 unsigned int vcc,
171 void *priv_data)
172{
173 if (cfg->index == 0)
174 goto next_entry;
175
176 /* Use power settings for Vcc and Vpp if present */
177 /* Note that the CIS values need to be rescaled */
178 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
179 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
180 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
181 if (!ignore_cis_vcc)
182 goto next_entry;
183 }
184 } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
185 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
186 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
187 if (!ignore_cis_vcc)
188 goto next_entry;
189 }
190 }
191
192 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
193 p_dev->conf.Vpp =
194 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
195 else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
196 p_dev->conf.Vpp =
197 dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
198
199 /* Do we need to allocate an interrupt? */
200 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
201
202 /* IO window settings */
203 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
204 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
205 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
206 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
207 if (!(io->flags & CISTPL_IO_8BIT))
208 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
209 if (!(io->flags & CISTPL_IO_16BIT))
210 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
211 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
212 p_dev->io.BasePort1 = io->win[0].base;
213 p_dev->io.NumPorts1 = io->win[0].len;
214 if (io->nwin > 1) {
215 p_dev->io.Attributes2 = p_dev->io.Attributes1;
216 p_dev->io.BasePort2 = io->win[1].base;
217 p_dev->io.NumPorts2 = io->win[1].len;
218 }
219
220 /* This reserves IO space but doesn't actually enable it */
221 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
222 goto next_entry;
223 }
224 return 0;
225
226next_entry:
227 pcmcia_disable_device(p_dev);
228 return -ENODEV;
229};
230
167static int 231static int
168orinoco_cs_config(struct pcmcia_device *link) 232orinoco_cs_config(struct pcmcia_device *link)
169{ 233{
@@ -172,16 +236,8 @@ orinoco_cs_config(struct pcmcia_device *link)
172 struct orinoco_pccard *card = priv->card; 236 struct orinoco_pccard *card = priv->card;
173 hermes_t *hw = &priv->hw; 237 hermes_t *hw = &priv->hw;
174 int last_fn, last_ret; 238 int last_fn, last_ret;
175 u_char buf[64];
176 config_info_t conf;
177 tuple_t tuple;
178 cisparse_t parse;
179 void __iomem *mem; 239 void __iomem *mem;
180 240
181 /* Look up the current Vcc */
182 CS_CHECK(GetConfigurationInfo,
183 pcmcia_get_configuration_info(link, &conf));
184
185 /* 241 /*
186 * In this loop, we scan the CIS for configuration table 242 * In this loop, we scan the CIS for configuration table
187 * entries, each of which describes a valid card 243 * entries, each of which describes a valid card
@@ -196,94 +252,14 @@ orinoco_cs_config(struct pcmcia_device *link)
196 * and most client drivers will only use the CIS to fill in 252 * and most client drivers will only use the CIS to fill in
197 * implementation-defined details. 253 * implementation-defined details.
198 */ 254 */
199 tuple.Attributes = 0; 255 last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
200 tuple.TupleData = buf; 256 if (last_ret) {
201 tuple.TupleDataMax = sizeof(buf); 257 if (!ignore_cis_vcc)
202 tuple.TupleOffset = 0;
203 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
204 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
205 while (1) {
206 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
207 cistpl_cftable_entry_t dflt = { .index = 0 };
208
209 if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
210 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
211 goto next_entry;
212
213 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
214 dflt = *cfg;
215 if (cfg->index == 0)
216 goto next_entry;
217 link->conf.ConfigIndex = cfg->index;
218
219 /* Use power settings for Vcc and Vpp if present */
220 /* Note that the CIS values need to be rescaled */
221 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
222 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
223 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
224 if (!ignore_cis_vcc)
225 goto next_entry;
226 }
227 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
228 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
229 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
230 if(!ignore_cis_vcc)
231 goto next_entry;
232 }
233 }
234
235 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
236 link->conf.Vpp =
237 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
238 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
239 link->conf.Vpp =
240 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
241
242 /* Do we need to allocate an interrupt? */
243 link->conf.Attributes |= CONF_ENABLE_IRQ;
244
245 /* IO window settings */
246 link->io.NumPorts1 = link->io.NumPorts2 = 0;
247 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
248 cistpl_io_t *io =
249 (cfg->io.nwin) ? &cfg->io : &dflt.io;
250 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
251 if (!(io->flags & CISTPL_IO_8BIT))
252 link->io.Attributes1 =
253 IO_DATA_PATH_WIDTH_16;
254 if (!(io->flags & CISTPL_IO_16BIT))
255 link->io.Attributes1 =
256 IO_DATA_PATH_WIDTH_8;
257 link->io.IOAddrLines =
258 io->flags & CISTPL_IO_LINES_MASK;
259 link->io.BasePort1 = io->win[0].base;
260 link->io.NumPorts1 = io->win[0].len;
261 if (io->nwin > 1) {
262 link->io.Attributes2 =
263 link->io.Attributes1;
264 link->io.BasePort2 = io->win[1].base;
265 link->io.NumPorts2 = io->win[1].len;
266 }
267
268 /* This reserves IO space but doesn't actually enable it */
269 if (pcmcia_request_io(link, &link->io) != 0)
270 goto next_entry;
271 }
272
273
274 /* If we got this far, we're cool! */
275
276 break;
277
278 next_entry:
279 pcmcia_disable_device(link);
280 last_ret = pcmcia_get_next_tuple(link, &tuple);
281 if (last_ret == CS_NO_MORE_ITEMS) {
282 printk(KERN_ERR PFX "GetNextTuple(): No matching " 258 printk(KERN_ERR PFX "GetNextTuple(): No matching "
283 "CIS configuration. Maybe you need the " 259 "CIS configuration. Maybe you need the "
284 "ignore_cis_vcc=1 parameter.\n"); 260 "ignore_cis_vcc=1 parameter.\n");
285 goto cs_failed; 261 cs_error(link, RequestIO, last_ret);
286 } 262 goto failed;
287 } 263 }
288 264
289 /* 265 /*
@@ -334,7 +310,6 @@ orinoco_cs_config(struct pcmcia_device *link)
334 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, 310 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
335 link->irq.AssignedIRQ, link->io.BasePort1, 311 link->irq.AssignedIRQ, link->io.BasePort1,
336 link->io.BasePort1 + link->io.NumPorts1 - 1); 312 link->io.BasePort1 + link->io.NumPorts1 - 1);
337
338 return 0; 313 return 0;
339 314
340 cs_failed: 315 cs_failed: