diff options
Diffstat (limited to 'drivers/ata/pata_pcmcia.c')
-rw-r--r-- | drivers/ata/pata_pcmcia.c | 168 |
1 files changed, 75 insertions, 93 deletions
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 41b4361bbf6e..02b596b9cf6a 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -148,6 +148,64 @@ static struct ata_port_operations pcmcia_8bit_port_ops = { | |||
148 | #define CS_CHECK(fn, ret) \ | 148 | #define CS_CHECK(fn, ret) \ |
149 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 149 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
150 | 150 | ||
151 | |||
152 | struct pcmcia_config_check { | ||
153 | unsigned long ctl_base; | ||
154 | int skip_vcc; | ||
155 | int is_kme; | ||
156 | }; | ||
157 | |||
158 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, | ||
159 | cistpl_cftable_entry_t *cfg, | ||
160 | cistpl_cftable_entry_t *dflt, | ||
161 | unsigned int vcc, | ||
162 | void *priv_data) | ||
163 | { | ||
164 | struct pcmcia_config_check *stk = priv_data; | ||
165 | |||
166 | /* Check for matching Vcc, unless we're desperate */ | ||
167 | if (!stk->skip_vcc) { | ||
168 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
169 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
170 | return -ENODEV; | ||
171 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
172 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
173 | return -ENODEV; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
178 | pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
179 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
180 | pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
181 | |||
182 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
183 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
184 | pdev->io.BasePort1 = io->win[0].base; | ||
185 | pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
186 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
187 | pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
188 | if (io->nwin == 2) { | ||
189 | pdev->io.NumPorts1 = 8; | ||
190 | pdev->io.BasePort2 = io->win[1].base; | ||
191 | pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1; | ||
192 | if (pcmcia_request_io(pdev, &pdev->io) != 0) | ||
193 | return -ENODEV; | ||
194 | stk->ctl_base = pdev->io.BasePort2; | ||
195 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
196 | pdev->io.NumPorts1 = io->win[0].len; | ||
197 | pdev->io.NumPorts2 = 0; | ||
198 | if (pcmcia_request_io(pdev, &pdev->io) != 0) | ||
199 | return -ENODEV; | ||
200 | stk->ctl_base = pdev->io.BasePort1 + 0x0e; | ||
201 | } else | ||
202 | return -ENODEV; | ||
203 | /* If we've got this far, we're done */ | ||
204 | return 0; | ||
205 | } | ||
206 | return -ENODEV; | ||
207 | } | ||
208 | |||
151 | /** | 209 | /** |
152 | * pcmcia_init_one - attach a PCMCIA interface | 210 | * pcmcia_init_one - attach a PCMCIA interface |
153 | * @pdev: pcmcia device | 211 | * @pdev: pcmcia device |
@@ -161,19 +219,11 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
161 | struct ata_host *host; | 219 | struct ata_host *host; |
162 | struct ata_port *ap; | 220 | struct ata_port *ap; |
163 | struct ata_pcmcia_info *info; | 221 | struct ata_pcmcia_info *info; |
164 | tuple_t tuple; | 222 | struct pcmcia_config_check *stk = NULL; |
165 | struct { | 223 | int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p; |
166 | unsigned short buf[128]; | ||
167 | cisparse_t parse; | ||
168 | config_info_t conf; | ||
169 | cistpl_cftable_entry_t dflt; | ||
170 | } *stk = NULL; | ||
171 | cistpl_cftable_entry_t *cfg; | ||
172 | int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p; | ||
173 | unsigned long io_base, ctl_base; | 224 | unsigned long io_base, ctl_base; |
174 | void __iomem *io_addr, *ctl_addr; | 225 | void __iomem *io_addr, *ctl_addr; |
175 | int n_ports = 1; | 226 | int n_ports = 1; |
176 | |||
177 | struct ata_port_operations *ops = &pcmcia_port_ops; | 227 | struct ata_port_operations *ops = &pcmcia_port_ops; |
178 | 228 | ||
179 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 229 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
@@ -193,96 +243,27 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
193 | pdev->conf.Attributes = CONF_ENABLE_IRQ; | 243 | pdev->conf.Attributes = CONF_ENABLE_IRQ; |
194 | pdev->conf.IntType = INT_MEMORY_AND_IO; | 244 | pdev->conf.IntType = INT_MEMORY_AND_IO; |
195 | 245 | ||
196 | /* Allocate resoure probing structures */ | ||
197 | |||
198 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); | ||
199 | if (!stk) | ||
200 | goto out1; | ||
201 | |||
202 | cfg = &stk->parse.cftable_entry; | ||
203 | |||
204 | /* Tuples we are walking */ | ||
205 | tuple.TupleData = (cisdata_t *)&stk->buf; | ||
206 | tuple.TupleOffset = 0; | ||
207 | tuple.TupleDataMax = 255; | ||
208 | tuple.Attributes = 0; | ||
209 | |||
210 | /* See if we have a manufacturer identifier. Use it to set is_kme for | 246 | /* See if we have a manufacturer identifier. Use it to set is_kme for |
211 | vendor quirks */ | 247 | vendor quirks */ |
212 | is_kme = ((pdev->manf_id == MANFID_KME) && | 248 | is_kme = ((pdev->manf_id == MANFID_KME) && |
213 | ((pdev->card_id == PRODID_KME_KXLC005_A) || | 249 | ((pdev->card_id == PRODID_KME_KXLC005_A) || |
214 | (pdev->card_id == PRODID_KME_KXLC005_B))); | 250 | (pdev->card_id == PRODID_KME_KXLC005_B))); |
215 | 251 | ||
216 | /* Not sure if this is right... look up the current Vcc */ | 252 | /* Allocate resoure probing structures */ |
217 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf)); | ||
218 | /* link->conf.Vcc = stk->conf.Vcc; */ | ||
219 | |||
220 | pass = io_base = ctl_base = 0; | ||
221 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
222 | tuple.Attributes = 0; | ||
223 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); | ||
224 | |||
225 | /* Now munch the resources looking for a suitable set */ | ||
226 | while (1) { | ||
227 | if (pcmcia_get_tuple_data(pdev, &tuple) != 0) | ||
228 | goto next_entry; | ||
229 | if (pcmcia_parse_tuple(pdev, &tuple, &stk->parse) != 0) | ||
230 | goto next_entry; | ||
231 | /* Check for matching Vcc, unless we're desperate */ | ||
232 | if (!pass) { | ||
233 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
234 | if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
235 | goto next_entry; | ||
236 | } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
237 | if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
238 | goto next_entry; | ||
239 | } | ||
240 | } | ||
241 | 253 | ||
242 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 254 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); |
243 | pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 255 | if (!stk) |
244 | else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 256 | goto out1; |
245 | pdev->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 257 | stk->is_kme = is_kme; |
246 | 258 | stk->skip_vcc = io_base = ctl_base = 0; | |
247 | if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { | ||
248 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; | ||
249 | pdev->conf.ConfigIndex = cfg->index; | ||
250 | pdev->io.BasePort1 = io->win[0].base; | ||
251 | pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
252 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
253 | pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
254 | if (io->nwin == 2) { | ||
255 | pdev->io.NumPorts1 = 8; | ||
256 | pdev->io.BasePort2 = io->win[1].base; | ||
257 | pdev->io.NumPorts2 = (is_kme) ? 2 : 1; | ||
258 | if (pcmcia_request_io(pdev, &pdev->io) != 0) | ||
259 | goto next_entry; | ||
260 | io_base = pdev->io.BasePort1; | ||
261 | ctl_base = pdev->io.BasePort2; | ||
262 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
263 | pdev->io.NumPorts1 = io->win[0].len; | ||
264 | pdev->io.NumPorts2 = 0; | ||
265 | if (pcmcia_request_io(pdev, &pdev->io) != 0) | ||
266 | goto next_entry; | ||
267 | io_base = pdev->io.BasePort1; | ||
268 | ctl_base = pdev->io.BasePort1 + 0x0e; | ||
269 | } else | ||
270 | goto next_entry; | ||
271 | /* If we've got this far, we're done */ | ||
272 | break; | ||
273 | } | ||
274 | next_entry: | ||
275 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
276 | memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); | ||
277 | if (pass) { | ||
278 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple)); | ||
279 | } else if (pcmcia_get_next_tuple(pdev, &tuple) != 0) { | ||
280 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); | ||
281 | memset(&stk->dflt, 0, sizeof(stk->dflt)); | ||
282 | pass++; | ||
283 | } | ||
284 | } | ||
285 | 259 | ||
260 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) { | ||
261 | stk->skip_vcc = 1; | ||
262 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) | ||
263 | goto failed; /* No suitable config found */ | ||
264 | } | ||
265 | io_base = pdev->io.BasePort1; | ||
266 | ctl_base = stk->ctl_base; | ||
286 | CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); | 267 | CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); |
287 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); | 268 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); |
288 | 269 | ||
@@ -384,6 +365,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
384 | PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), | 365 | PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), |
385 | PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), | 366 | PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), |
386 | PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ | 367 | PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ |
368 | PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ | ||
387 | PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ | 369 | PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ |
388 | PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ | 370 | PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ |
389 | PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), | 371 | PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), |
@@ -404,9 +386,9 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
404 | PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), | 386 | PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), |
405 | PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), | 387 | PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), |
406 | PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), | 388 | PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), |
407 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), | ||
408 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), | 389 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), |
409 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), | 390 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), |
391 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), | ||
410 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), | 392 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), |
411 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), | 393 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), |
412 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), | 394 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), |