aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/legacy/ide-cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/legacy/ide-cs.c')
-rw-r--r--drivers/ide/legacy/ide-cs.c158
1 files changed, 74 insertions, 84 deletions
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index ee6fc30d5e2b..cb199c815b53 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -219,103 +219,91 @@ out_release:
219#define CS_CHECK(fn, ret) \ 219#define CS_CHECK(fn, ret) \
220do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 220do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
221 221
222struct pcmcia_config_check {
223 unsigned long ctl_base;
224 int skip_vcc;
225 int is_kme;
226};
227
228static int pcmcia_check_one_config(struct pcmcia_device *pdev,
229 cistpl_cftable_entry_t *cfg,
230 cistpl_cftable_entry_t *dflt,
231 unsigned int vcc,
232 void *priv_data)
233{
234 struct pcmcia_config_check *stk = priv_data;
235
236 /* Check for matching Vcc, unless we're desperate */
237 if (!stk->skip_vcc) {
238 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
239 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
240 return -ENODEV;
241 } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
242 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
243 return -ENODEV;
244 }
245 }
246
247 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
248 pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
249 else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
250 pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
251
252 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
253 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
254 pdev->conf.ConfigIndex = cfg->index;
255 pdev->io.BasePort1 = io->win[0].base;
256 pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
257 if (!(io->flags & CISTPL_IO_16BIT))
258 pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
259 if (io->nwin == 2) {
260 pdev->io.NumPorts1 = 8;
261 pdev->io.BasePort2 = io->win[1].base;
262 pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
263 if (pcmcia_request_io(pdev, &pdev->io) != 0)
264 return -ENODEV;
265 stk->ctl_base = pdev->io.BasePort2;
266 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
267 pdev->io.NumPorts1 = io->win[0].len;
268 pdev->io.NumPorts2 = 0;
269 if (pcmcia_request_io(pdev, &pdev->io) != 0)
270 return -ENODEV;
271 stk->ctl_base = pdev->io.BasePort1 + 0x0e;
272 } else
273 return -ENODEV;
274 /* If we've got this far, we're done */
275 return 0;
276 }
277 return -ENODEV;
278}
279
222static int ide_config(struct pcmcia_device *link) 280static int ide_config(struct pcmcia_device *link)
223{ 281{
224 ide_info_t *info = link->priv; 282 ide_info_t *info = link->priv;
225 tuple_t tuple; 283 struct pcmcia_config_check *stk = NULL;
226 struct { 284 int last_ret = 0, last_fn = 0, is_kme = 0;
227 u_short buf[128];
228 cisparse_t parse;
229 config_info_t conf;
230 cistpl_cftable_entry_t dflt;
231 } *stk = NULL;
232 cistpl_cftable_entry_t *cfg;
233 int pass, last_ret = 0, last_fn = 0, is_kme = 0;
234 unsigned long io_base, ctl_base; 285 unsigned long io_base, ctl_base;
235 struct ide_host *host; 286 struct ide_host *host;
236 287
237 DEBUG(0, "ide_config(0x%p)\n", link); 288 DEBUG(0, "ide_config(0x%p)\n", link);
238 289
239 stk = kzalloc(sizeof(*stk), GFP_KERNEL);
240 if (!stk) goto err_mem;
241 cfg = &stk->parse.cftable_entry;
242
243 tuple.TupleData = (cisdata_t *)&stk->buf;
244 tuple.TupleOffset = 0;
245 tuple.TupleDataMax = 255;
246 tuple.Attributes = 0;
247
248 is_kme = ((link->manf_id == MANFID_KME) && 290 is_kme = ((link->manf_id == MANFID_KME) &&
249 ((link->card_id == PRODID_KME_KXLC005_A) || 291 ((link->card_id == PRODID_KME_KXLC005_A) ||
250 (link->card_id == PRODID_KME_KXLC005_B))); 292 (link->card_id == PRODID_KME_KXLC005_B)));
251 293
252 /* Not sure if this is right... look up the current Vcc */ 294 stk = kzalloc(sizeof(*stk), GFP_KERNEL);
253 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); 295 if (!stk)
254 296 goto err_mem;
255 pass = io_base = ctl_base = 0; 297 stk->is_kme = is_kme;
256 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 298 stk->skip_vcc = io_base = ctl_base = 0;
257 tuple.Attributes = 0; 299
258 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 300 if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
259 while (1) { 301 stk->skip_vcc = 1;
260 if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry; 302 if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
261 if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry; 303 goto failed; /* No suitable config found */
262
263 /* Check for matching Vcc, unless we're desperate */
264 if (!pass) {
265 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
266 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
267 goto next_entry;
268 } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
269 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
270 goto next_entry;
271 }
272 }
273
274 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
275 link->conf.Vpp =
276 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
277 else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
278 link->conf.Vpp =
279 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
280
281 if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
282 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
283 link->conf.ConfigIndex = cfg->index;
284 link->io.BasePort1 = io->win[0].base;
285 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
286 if (!(io->flags & CISTPL_IO_16BIT))
287 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
288 if (io->nwin == 2) {
289 link->io.NumPorts1 = 8;
290 link->io.BasePort2 = io->win[1].base;
291 link->io.NumPorts2 = (is_kme) ? 2 : 1;
292 if (pcmcia_request_io(link, &link->io) != 0)
293 goto next_entry;
294 io_base = link->io.BasePort1;
295 ctl_base = link->io.BasePort2;
296 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
297 link->io.NumPorts1 = io->win[0].len;
298 link->io.NumPorts2 = 0;
299 if (pcmcia_request_io(link, &link->io) != 0)
300 goto next_entry;
301 io_base = link->io.BasePort1;
302 ctl_base = link->io.BasePort1 + 0x0e;
303 } else goto next_entry;
304 /* If we've got this far, we're done */
305 break;
306 }
307
308 next_entry:
309 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
310 memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
311 if (pass) {
312 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
313 } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
314 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
315 memset(&stk->dflt, 0, sizeof(stk->dflt));
316 pass++;
317 }
318 } 304 }
305 io_base = link->io.BasePort1;
306 ctl_base = stk->ctl_base;
319 307
320 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); 308 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
321 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); 309 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@@ -403,8 +391,10 @@ static struct pcmcia_device_id ide_ids[] = {
403 PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ 391 PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
404 PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ 392 PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
405 PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), 393 PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
394 PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
406 PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ 395 PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
407 PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ 396 PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
397 PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
408 PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ 398 PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
409 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), 399 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
410 PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ 400 PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */