diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-04-12 16:54:16 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-12 16:54:16 -0400 |
| commit | 875999c5539999f61a45620aae0c3e5fb1d2b035 (patch) | |
| tree | 4535032a8a10f5782c0aef6a620b1a624ea9f863 /drivers/ide/legacy/ide-cs.c | |
| parent | 79072f38909e3d9883317238887460c39ddcc4cb (diff) | |
| parent | 26ec634c31a11a003040e10b4d650495158632fd (diff) | |
Merge branch 'upstream'
Diffstat (limited to 'drivers/ide/legacy/ide-cs.c')
| -rw-r--r-- | drivers/ide/legacy/ide-cs.c | 127 |
1 files changed, 41 insertions, 86 deletions
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 6213bd3caee5..4961f1e764a7 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c | |||
| @@ -81,14 +81,14 @@ static const char ide_major[] = { | |||
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | typedef struct ide_info_t { | 83 | typedef struct ide_info_t { |
| 84 | dev_link_t link; | 84 | struct pcmcia_device *p_dev; |
| 85 | int ndev; | 85 | int ndev; |
| 86 | dev_node_t node; | 86 | dev_node_t node; |
| 87 | int hd; | 87 | int hd; |
| 88 | } ide_info_t; | 88 | } ide_info_t; |
| 89 | 89 | ||
| 90 | static void ide_release(dev_link_t *); | 90 | static void ide_release(struct pcmcia_device *); |
| 91 | static void ide_config(dev_link_t *); | 91 | static int ide_config(struct pcmcia_device *); |
| 92 | 92 | ||
| 93 | static void ide_detach(struct pcmcia_device *p_dev); | 93 | static void ide_detach(struct pcmcia_device *p_dev); |
| 94 | 94 | ||
| @@ -103,10 +103,9 @@ static void ide_detach(struct pcmcia_device *p_dev); | |||
| 103 | 103 | ||
| 104 | ======================================================================*/ | 104 | ======================================================================*/ |
| 105 | 105 | ||
| 106 | static int ide_attach(struct pcmcia_device *p_dev) | 106 | static int ide_probe(struct pcmcia_device *link) |
| 107 | { | 107 | { |
| 108 | ide_info_t *info; | 108 | ide_info_t *info; |
| 109 | dev_link_t *link; | ||
| 110 | 109 | ||
| 111 | DEBUG(0, "ide_attach()\n"); | 110 | DEBUG(0, "ide_attach()\n"); |
| 112 | 111 | ||
| @@ -114,7 +113,9 @@ static int ide_attach(struct pcmcia_device *p_dev) | |||
| 114 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 113 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
| 115 | if (!info) | 114 | if (!info) |
| 116 | return -ENOMEM; | 115 | return -ENOMEM; |
| 117 | link = &info->link; link->priv = info; | 116 | |
| 117 | info->p_dev = link; | ||
| 118 | link->priv = info; | ||
| 118 | 119 | ||
| 119 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 120 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
| 120 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | 121 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; |
| @@ -122,16 +123,9 @@ static int ide_attach(struct pcmcia_device *p_dev) | |||
| 122 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 123 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
| 123 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 124 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
| 124 | link->conf.Attributes = CONF_ENABLE_IRQ; | 125 | link->conf.Attributes = CONF_ENABLE_IRQ; |
| 125 | link->conf.Vcc = 50; | ||
| 126 | link->conf.IntType = INT_MEMORY_AND_IO; | 126 | link->conf.IntType = INT_MEMORY_AND_IO; |
| 127 | 127 | ||
| 128 | link->handle = p_dev; | 128 | return ide_config(link); |
| 129 | p_dev->instance = link; | ||
| 130 | |||
| 131 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
| 132 | ide_config(link); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } /* ide_attach */ | 129 | } /* ide_attach */ |
| 136 | 130 | ||
| 137 | /*====================================================================== | 131 | /*====================================================================== |
| @@ -143,14 +137,11 @@ static int ide_attach(struct pcmcia_device *p_dev) | |||
| 143 | 137 | ||
| 144 | ======================================================================*/ | 138 | ======================================================================*/ |
| 145 | 139 | ||
| 146 | static void ide_detach(struct pcmcia_device *p_dev) | 140 | static void ide_detach(struct pcmcia_device *link) |
| 147 | { | 141 | { |
| 148 | dev_link_t *link = dev_to_instance(p_dev); | ||
| 149 | |||
| 150 | DEBUG(0, "ide_detach(0x%p)\n", link); | 142 | DEBUG(0, "ide_detach(0x%p)\n", link); |
| 151 | 143 | ||
| 152 | if (link->state & DEV_CONFIG) | 144 | ide_release(link); |
| 153 | ide_release(link); | ||
| 154 | 145 | ||
| 155 | kfree(link->priv); | 146 | kfree(link->priv); |
| 156 | } /* ide_detach */ | 147 | } /* ide_detach */ |
| @@ -177,9 +168,8 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq | |||
| 177 | #define CS_CHECK(fn, ret) \ | 168 | #define CS_CHECK(fn, ret) \ |
| 178 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 169 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
| 179 | 170 | ||
| 180 | static void ide_config(dev_link_t *link) | 171 | static int ide_config(struct pcmcia_device *link) |
| 181 | { | 172 | { |
| 182 | client_handle_t handle = link->handle; | ||
| 183 | ide_info_t *info = link->priv; | 173 | ide_info_t *info = link->priv; |
| 184 | tuple_t tuple; | 174 | tuple_t tuple; |
| 185 | struct { | 175 | struct { |
| @@ -203,34 +193,30 @@ static void ide_config(dev_link_t *link) | |||
| 203 | tuple.TupleDataMax = 255; | 193 | tuple.TupleDataMax = 255; |
| 204 | tuple.Attributes = 0; | 194 | tuple.Attributes = 0; |
| 205 | tuple.DesiredTuple = CISTPL_CONFIG; | 195 | tuple.DesiredTuple = CISTPL_CONFIG; |
| 206 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 196 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
| 207 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 197 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
| 208 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); | 198 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse)); |
| 209 | link->conf.ConfigBase = stk->parse.config.base; | 199 | link->conf.ConfigBase = stk->parse.config.base; |
| 210 | link->conf.Present = stk->parse.config.rmask[0]; | 200 | link->conf.Present = stk->parse.config.rmask[0]; |
| 211 | 201 | ||
| 212 | tuple.DesiredTuple = CISTPL_MANFID; | 202 | tuple.DesiredTuple = CISTPL_MANFID; |
| 213 | if (!pcmcia_get_first_tuple(handle, &tuple) && | 203 | if (!pcmcia_get_first_tuple(link, &tuple) && |
| 214 | !pcmcia_get_tuple_data(handle, &tuple) && | 204 | !pcmcia_get_tuple_data(link, &tuple) && |
| 215 | !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) | 205 | !pcmcia_parse_tuple(link, &tuple, &stk->parse)) |
| 216 | is_kme = ((stk->parse.manfid.manf == MANFID_KME) && | 206 | is_kme = ((stk->parse.manfid.manf == MANFID_KME) && |
| 217 | ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || | 207 | ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || |
| 218 | (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); | 208 | (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); |
| 219 | 209 | ||
| 220 | /* Configure card */ | ||
| 221 | link->state |= DEV_CONFIG; | ||
| 222 | |||
| 223 | /* Not sure if this is right... look up the current Vcc */ | 210 | /* Not sure if this is right... look up the current Vcc */ |
| 224 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); | 211 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); |
| 225 | link->conf.Vcc = stk->conf.Vcc; | ||
| 226 | 212 | ||
| 227 | pass = io_base = ctl_base = 0; | 213 | pass = io_base = ctl_base = 0; |
| 228 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 214 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
| 229 | tuple.Attributes = 0; | 215 | tuple.Attributes = 0; |
| 230 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 216 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
| 231 | while (1) { | 217 | while (1) { |
| 232 | if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; | 218 | if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry; |
| 233 | if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; | 219 | if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry; |
| 234 | 220 | ||
| 235 | /* Check for matching Vcc, unless we're desperate */ | 221 | /* Check for matching Vcc, unless we're desperate */ |
| 236 | if (!pass) { | 222 | if (!pass) { |
| @@ -244,10 +230,10 @@ static void ide_config(dev_link_t *link) | |||
| 244 | } | 230 | } |
| 245 | 231 | ||
| 246 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 232 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
| 247 | link->conf.Vpp1 = link->conf.Vpp2 = | 233 | link->conf.Vpp = |
| 248 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 234 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
| 249 | else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 235 | else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) |
| 250 | link->conf.Vpp1 = link->conf.Vpp2 = | 236 | link->conf.Vpp = |
| 251 | stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 237 | stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; |
| 252 | 238 | ||
| 253 | if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { | 239 | if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { |
| @@ -261,14 +247,14 @@ static void ide_config(dev_link_t *link) | |||
| 261 | link->io.NumPorts1 = 8; | 247 | link->io.NumPorts1 = 8; |
| 262 | link->io.BasePort2 = io->win[1].base; | 248 | link->io.BasePort2 = io->win[1].base; |
| 263 | link->io.NumPorts2 = (is_kme) ? 2 : 1; | 249 | link->io.NumPorts2 = (is_kme) ? 2 : 1; |
| 264 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 250 | if (pcmcia_request_io(link, &link->io) != 0) |
| 265 | goto next_entry; | 251 | goto next_entry; |
| 266 | io_base = link->io.BasePort1; | 252 | io_base = link->io.BasePort1; |
| 267 | ctl_base = link->io.BasePort2; | 253 | ctl_base = link->io.BasePort2; |
| 268 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | 254 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { |
| 269 | link->io.NumPorts1 = io->win[0].len; | 255 | link->io.NumPorts1 = io->win[0].len; |
| 270 | link->io.NumPorts2 = 0; | 256 | link->io.NumPorts2 = 0; |
| 271 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 257 | if (pcmcia_request_io(link, &link->io) != 0) |
| 272 | goto next_entry; | 258 | goto next_entry; |
| 273 | io_base = link->io.BasePort1; | 259 | io_base = link->io.BasePort1; |
| 274 | ctl_base = link->io.BasePort1 + 0x0e; | 260 | ctl_base = link->io.BasePort1 + 0x0e; |
| @@ -281,16 +267,16 @@ static void ide_config(dev_link_t *link) | |||
| 281 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 267 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
| 282 | memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); | 268 | memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); |
| 283 | if (pass) { | 269 | if (pass) { |
| 284 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 270 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
| 285 | } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { | 271 | } else if (pcmcia_get_next_tuple(link, &tuple) != 0) { |
| 286 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 272 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
| 287 | memset(&stk->dflt, 0, sizeof(stk->dflt)); | 273 | memset(&stk->dflt, 0, sizeof(stk->dflt)); |
| 288 | pass++; | 274 | pass++; |
| 289 | } | 275 | } |
| 290 | } | 276 | } |
| 291 | 277 | ||
| 292 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 278 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
| 293 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 279 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
| 294 | 280 | ||
| 295 | /* disable drive interrupts during IDE probe */ | 281 | /* disable drive interrupts during IDE probe */ |
| 296 | outb(0x02, ctl_base); | 282 | outb(0x02, ctl_base); |
| @@ -301,12 +287,12 @@ static void ide_config(dev_link_t *link) | |||
| 301 | 287 | ||
| 302 | /* retry registration in case device is still spinning up */ | 288 | /* retry registration in case device is still spinning up */ |
| 303 | for (hd = -1, i = 0; i < 10; i++) { | 289 | for (hd = -1, i = 0; i < 10; i++) { |
| 304 | hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle); | 290 | hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); |
| 305 | if (hd >= 0) break; | 291 | if (hd >= 0) break; |
| 306 | if (link->io.NumPorts1 == 0x20) { | 292 | if (link->io.NumPorts1 == 0x20) { |
| 307 | outb(0x02, ctl_base + 0x10); | 293 | outb(0x02, ctl_base + 0x10); |
| 308 | hd = idecs_register(io_base + 0x10, ctl_base + 0x10, | 294 | hd = idecs_register(io_base + 0x10, ctl_base + 0x10, |
| 309 | link->irq.AssignedIRQ, handle); | 295 | link->irq.AssignedIRQ, link); |
| 310 | if (hd >= 0) { | 296 | if (hd >= 0) { |
| 311 | io_base += 0x10; | 297 | io_base += 0x10; |
| 312 | ctl_base += 0x10; | 298 | ctl_base += 0x10; |
| @@ -328,25 +314,23 @@ static void ide_config(dev_link_t *link) | |||
| 328 | info->node.major = ide_major[hd]; | 314 | info->node.major = ide_major[hd]; |
| 329 | info->node.minor = 0; | 315 | info->node.minor = 0; |
| 330 | info->hd = hd; | 316 | info->hd = hd; |
| 331 | link->dev = &info->node; | 317 | link->dev_node = &info->node; |
| 332 | printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", | 318 | printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", |
| 333 | info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, | 319 | info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); |
| 334 | link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); | ||
| 335 | 320 | ||
| 336 | link->state &= ~DEV_CONFIG_PENDING; | ||
| 337 | kfree(stk); | 321 | kfree(stk); |
| 338 | return; | 322 | return 0; |
| 339 | 323 | ||
| 340 | err_mem: | 324 | err_mem: |
| 341 | printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); | 325 | printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); |
| 342 | goto failed; | 326 | goto failed; |
| 343 | 327 | ||
| 344 | cs_failed: | 328 | cs_failed: |
| 345 | cs_error(link->handle, last_fn, last_ret); | 329 | cs_error(link, last_fn, last_ret); |
| 346 | failed: | 330 | failed: |
| 347 | kfree(stk); | 331 | kfree(stk); |
| 348 | ide_release(link); | 332 | ide_release(link); |
| 349 | link->state &= ~DEV_CONFIG_PENDING; | 333 | return -ENODEV; |
| 350 | } /* ide_config */ | 334 | } /* ide_config */ |
| 351 | 335 | ||
| 352 | /*====================================================================== | 336 | /*====================================================================== |
| @@ -357,7 +341,7 @@ failed: | |||
| 357 | 341 | ||
| 358 | ======================================================================*/ | 342 | ======================================================================*/ |
| 359 | 343 | ||
| 360 | void ide_release(dev_link_t *link) | 344 | void ide_release(struct pcmcia_device *link) |
| 361 | { | 345 | { |
| 362 | ide_info_t *info = link->priv; | 346 | ide_info_t *info = link->priv; |
| 363 | 347 | ||
| @@ -369,37 +353,10 @@ void ide_release(dev_link_t *link) | |||
| 369 | ide_unregister(info->hd); | 353 | ide_unregister(info->hd); |
| 370 | } | 354 | } |
| 371 | info->ndev = 0; | 355 | info->ndev = 0; |
| 372 | link->dev = NULL; | ||
| 373 | |||
| 374 | pcmcia_release_configuration(link->handle); | ||
| 375 | pcmcia_release_io(link->handle, &link->io); | ||
| 376 | pcmcia_release_irq(link->handle, &link->irq); | ||
| 377 | |||
| 378 | link->state &= ~DEV_CONFIG; | ||
| 379 | 356 | ||
| 357 | pcmcia_disable_device(link); | ||
| 380 | } /* ide_release */ | 358 | } /* ide_release */ |
| 381 | 359 | ||
| 382 | static int ide_suspend(struct pcmcia_device *dev) | ||
| 383 | { | ||
| 384 | dev_link_t *link = dev_to_instance(dev); | ||
| 385 | |||
| 386 | link->state |= DEV_SUSPEND; | ||
| 387 | if (link->state & DEV_CONFIG) | ||
| 388 | pcmcia_release_configuration(link->handle); | ||
| 389 | |||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | static int ide_resume(struct pcmcia_device *dev) | ||
| 394 | { | ||
| 395 | dev_link_t *link = dev_to_instance(dev); | ||
| 396 | |||
| 397 | link->state &= ~DEV_SUSPEND; | ||
| 398 | if (DEV_OK(link)) | ||
| 399 | pcmcia_request_configuration(link->handle, &link->conf); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | 360 | ||
| 404 | /*====================================================================== | 361 | /*====================================================================== |
| 405 | 362 | ||
| @@ -459,11 +416,9 @@ static struct pcmcia_driver ide_cs_driver = { | |||
| 459 | .drv = { | 416 | .drv = { |
| 460 | .name = "ide-cs", | 417 | .name = "ide-cs", |
| 461 | }, | 418 | }, |
| 462 | .probe = ide_attach, | 419 | .probe = ide_probe, |
| 463 | .remove = ide_detach, | 420 | .remove = ide_detach, |
| 464 | .id_table = ide_ids, | 421 | .id_table = ide_ids, |
| 465 | .suspend = ide_suspend, | ||
| 466 | .resume = ide_resume, | ||
| 467 | }; | 422 | }; |
| 468 | 423 | ||
| 469 | static int __init init_ide_cs(void) | 424 | static int __init init_ide_cs(void) |
