diff options
Diffstat (limited to 'drivers/ide/ide-cs.c')
-rw-r--r-- | drivers/ide/ide-cs.c | 158 |
1 files changed, 30 insertions, 128 deletions
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 2a4cb9c18f01..d2f3db3cf3ed 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
45 | 45 | ||
46 | #include <pcmcia/cs.h> | ||
47 | #include <pcmcia/cistpl.h> | 46 | #include <pcmcia/cistpl.h> |
48 | #include <pcmcia/ds.h> | 47 | #include <pcmcia/ds.h> |
49 | #include <pcmcia/cisreg.h> | 48 | #include <pcmcia/cisreg.h> |
@@ -72,17 +71,6 @@ static int ide_config(struct pcmcia_device *); | |||
72 | 71 | ||
73 | static void ide_detach(struct pcmcia_device *p_dev); | 72 | static void ide_detach(struct pcmcia_device *p_dev); |
74 | 73 | ||
75 | |||
76 | |||
77 | |||
78 | /*====================================================================== | ||
79 | |||
80 | ide_attach() creates an "instance" of the driver, allocating | ||
81 | local data structures for one device. The device is registered | ||
82 | with Card Services. | ||
83 | |||
84 | ======================================================================*/ | ||
85 | |||
86 | static int ide_probe(struct pcmcia_device *link) | 74 | static int ide_probe(struct pcmcia_device *link) |
87 | { | 75 | { |
88 | ide_info_t *info; | 76 | ide_info_t *info; |
@@ -97,23 +85,12 @@ static int ide_probe(struct pcmcia_device *link) | |||
97 | info->p_dev = link; | 85 | info->p_dev = link; |
98 | link->priv = info; | 86 | link->priv = info; |
99 | 87 | ||
100 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 88 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO | |
101 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | 89 | CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; |
102 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
103 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
104 | 90 | ||
105 | return ide_config(link); | 91 | return ide_config(link); |
106 | } /* ide_attach */ | 92 | } /* ide_attach */ |
107 | 93 | ||
108 | /*====================================================================== | ||
109 | |||
110 | This deletes a driver "instance". The device is de-registered | ||
111 | with Card Services. If it has been released, all local data | ||
112 | structures are freed. Otherwise, the structures will be freed | ||
113 | when the device is released. | ||
114 | |||
115 | ======================================================================*/ | ||
116 | |||
117 | static void ide_detach(struct pcmcia_device *link) | 94 | static void ide_detach(struct pcmcia_device *link) |
118 | { | 95 | { |
119 | ide_info_t *info = link->priv; | 96 | ide_info_t *info = link->priv; |
@@ -187,79 +164,31 @@ out_release: | |||
187 | return NULL; | 164 | return NULL; |
188 | } | 165 | } |
189 | 166 | ||
190 | /*====================================================================== | 167 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) |
191 | |||
192 | ide_config() is scheduled to run after a CARD_INSERTION event | ||
193 | is received, to configure the PCMCIA socket, and to make the | ||
194 | ide device available to the system. | ||
195 | |||
196 | ======================================================================*/ | ||
197 | |||
198 | struct pcmcia_config_check { | ||
199 | unsigned long ctl_base; | ||
200 | int skip_vcc; | ||
201 | int is_kme; | ||
202 | }; | ||
203 | |||
204 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, | ||
205 | cistpl_cftable_entry_t *cfg, | ||
206 | cistpl_cftable_entry_t *dflt, | ||
207 | unsigned int vcc, | ||
208 | void *priv_data) | ||
209 | { | 168 | { |
210 | struct pcmcia_config_check *stk = priv_data; | 169 | int *is_kme = priv_data; |
211 | |||
212 | /* Check for matching Vcc, unless we're desperate */ | ||
213 | if (!stk->skip_vcc) { | ||
214 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
215 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
216 | return -ENODEV; | ||
217 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
218 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | } | ||
222 | 170 | ||
223 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 171 | if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { |
224 | pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 172 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
225 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 173 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
226 | pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 174 | } |
227 | 175 | pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | |
228 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | 176 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
229 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | 177 | |
230 | pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 178 | if (pdev->resource[1]->end) { |
231 | 179 | pdev->resource[0]->end = 8; | |
232 | pdev->conf.ConfigIndex = cfg->index; | 180 | pdev->resource[1]->end = (*is_kme) ? 2 : 1; |
233 | pdev->resource[0]->start = io->win[0].base; | 181 | } else { |
234 | if (!(io->flags & CISTPL_IO_16BIT)) { | 182 | if (pdev->resource[0]->end < 16) |
235 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
236 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
237 | } | ||
238 | if (io->nwin == 2) { | ||
239 | pdev->resource[0]->end = 8; | ||
240 | pdev->resource[1]->start = io->win[1].base; | ||
241 | pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; | ||
242 | if (pcmcia_request_io(pdev) != 0) | ||
243 | return -ENODEV; | ||
244 | stk->ctl_base = pdev->resource[1]->start; | ||
245 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
246 | pdev->resource[0]->end = io->win[0].len; | ||
247 | pdev->resource[1]->end = 0; | ||
248 | if (pcmcia_request_io(pdev) != 0) | ||
249 | return -ENODEV; | ||
250 | stk->ctl_base = pdev->resource[0]->start + 0x0e; | ||
251 | } else | ||
252 | return -ENODEV; | 183 | return -ENODEV; |
253 | /* If we've got this far, we're done */ | ||
254 | return 0; | ||
255 | } | 184 | } |
256 | return -ENODEV; | 185 | |
186 | return pcmcia_request_io(pdev); | ||
257 | } | 187 | } |
258 | 188 | ||
259 | static int ide_config(struct pcmcia_device *link) | 189 | static int ide_config(struct pcmcia_device *link) |
260 | { | 190 | { |
261 | ide_info_t *info = link->priv; | 191 | ide_info_t *info = link->priv; |
262 | struct pcmcia_config_check *stk = NULL; | ||
263 | int ret = 0, is_kme = 0; | 192 | int ret = 0, is_kme = 0; |
264 | unsigned long io_base, ctl_base; | 193 | unsigned long io_base, ctl_base; |
265 | struct ide_host *host; | 194 | struct ide_host *host; |
@@ -270,23 +199,21 @@ static int ide_config(struct pcmcia_device *link) | |||
270 | ((link->card_id == PRODID_KME_KXLC005_A) || | 199 | ((link->card_id == PRODID_KME_KXLC005_A) || |
271 | (link->card_id == PRODID_KME_KXLC005_B))); | 200 | (link->card_id == PRODID_KME_KXLC005_B))); |
272 | 201 | ||
273 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); | 202 | if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) { |
274 | if (!stk) | 203 | link->config_flags &= ~CONF_AUTO_CHECK_VCC; |
275 | goto err_mem; | 204 | if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) |
276 | stk->is_kme = is_kme; | ||
277 | stk->skip_vcc = io_base = ctl_base = 0; | ||
278 | |||
279 | if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) { | ||
280 | stk->skip_vcc = 1; | ||
281 | if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) | ||
282 | goto failed; /* No suitable config found */ | 205 | goto failed; /* No suitable config found */ |
283 | } | 206 | } |
284 | io_base = link->resource[0]->start; | 207 | io_base = link->resource[0]->start; |
285 | ctl_base = stk->ctl_base; | 208 | if (link->resource[1]->end) |
209 | ctl_base = link->resource[1]->start; | ||
210 | else | ||
211 | ctl_base = link->resource[0]->start + 0x0e; | ||
286 | 212 | ||
287 | if (!link->irq) | 213 | if (!link->irq) |
288 | goto failed; | 214 | goto failed; |
289 | ret = pcmcia_request_configuration(link, &link->conf); | 215 | |
216 | ret = pcmcia_enable_device(link); | ||
290 | if (ret) | 217 | if (ret) |
291 | goto failed; | 218 | goto failed; |
292 | 219 | ||
@@ -311,29 +238,15 @@ static int ide_config(struct pcmcia_device *link) | |||
311 | info->host = host; | 238 | info->host = host; |
312 | dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n", | 239 | dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n", |
313 | 'a' + host->ports[0]->index * 2, | 240 | 'a' + host->ports[0]->index * 2, |
314 | link->conf.Vpp / 10, link->conf.Vpp % 10); | 241 | link->vpp / 10, link->vpp % 10); |
315 | 242 | ||
316 | kfree(stk); | ||
317 | return 0; | 243 | return 0; |
318 | 244 | ||
319 | err_mem: | ||
320 | printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); | ||
321 | goto failed; | ||
322 | |||
323 | failed: | 245 | failed: |
324 | kfree(stk); | ||
325 | ide_release(link); | 246 | ide_release(link); |
326 | return -ENODEV; | 247 | return -ENODEV; |
327 | } /* ide_config */ | 248 | } /* ide_config */ |
328 | 249 | ||
329 | /*====================================================================== | ||
330 | |||
331 | After a card is removed, ide_release() will unregister the net | ||
332 | device, and release the PCMCIA configuration. If the device is | ||
333 | still open, this will be postponed until it is closed. | ||
334 | |||
335 | ======================================================================*/ | ||
336 | |||
337 | static void ide_release(struct pcmcia_device *link) | 250 | static void ide_release(struct pcmcia_device *link) |
338 | { | 251 | { |
339 | ide_info_t *info = link->priv; | 252 | ide_info_t *info = link->priv; |
@@ -359,16 +272,7 @@ static void ide_release(struct pcmcia_device *link) | |||
359 | } /* ide_release */ | 272 | } /* ide_release */ |
360 | 273 | ||
361 | 274 | ||
362 | /*====================================================================== | 275 | static const struct pcmcia_device_id ide_ids[] = { |
363 | |||
364 | The card status event handler. Mostly, this schedules other | ||
365 | stuff to run after an event is received. A CARD_REMOVAL event | ||
366 | also sets some flags to discourage the ide drivers from | ||
367 | talking to the ports. | ||
368 | |||
369 | ======================================================================*/ | ||
370 | |||
371 | static struct pcmcia_device_id ide_ids[] = { | ||
372 | PCMCIA_DEVICE_FUNC_ID(4), | 276 | PCMCIA_DEVICE_FUNC_ID(4), |
373 | PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ | 277 | PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ |
374 | PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ | 278 | PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ |
@@ -440,9 +344,7 @@ MODULE_DEVICE_TABLE(pcmcia, ide_ids); | |||
440 | 344 | ||
441 | static struct pcmcia_driver ide_cs_driver = { | 345 | static struct pcmcia_driver ide_cs_driver = { |
442 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
443 | .drv = { | 347 | .name = "ide-cs", |
444 | .name = "ide-cs", | ||
445 | }, | ||
446 | .probe = ide_probe, | 348 | .probe = ide_probe, |
447 | .remove = ide_detach, | 349 | .remove = ide_detach, |
448 | .id_table = ide_ids, | 350 | .id_table = ide_ids, |