diff options
Diffstat (limited to 'drivers/ide/legacy')
-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) |