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.c127
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
83typedef struct ide_info_t { 83typedef 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
90static void ide_release(dev_link_t *); 90static void ide_release(struct pcmcia_device *);
91static void ide_config(dev_link_t *); 91static int ide_config(struct pcmcia_device *);
92 92
93static void ide_detach(struct pcmcia_device *p_dev); 93static 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
106static int ide_attach(struct pcmcia_device *p_dev) 106static 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
146static void ide_detach(struct pcmcia_device *p_dev) 140static 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) \
178do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 169do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
179 170
180static void ide_config(dev_link_t *link) 171static 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
340err_mem: 324err_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
344cs_failed: 328cs_failed:
345 cs_error(link->handle, last_fn, last_ret); 329 cs_error(link, last_fn, last_ret);
346failed: 330failed:
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
360void ide_release(dev_link_t *link) 344void 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
382static 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
393static 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
469static int __init init_ide_cs(void) 424static int __init init_ide_cs(void)