diff options
Diffstat (limited to 'drivers/ide/legacy/ide-cs.c')
-rw-r--r-- | drivers/ide/legacy/ide-cs.c | 158 |
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) \ |
220 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 220 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
221 | 221 | ||
222 | struct pcmcia_config_check { | ||
223 | unsigned long ctl_base; | ||
224 | int skip_vcc; | ||
225 | int is_kme; | ||
226 | }; | ||
227 | |||
228 | static 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 | |||
222 | static int ide_config(struct pcmcia_device *link) | 280 | static 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 */ |