Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ide-cs.c
Go to the documentation of this file.
1 /*======================================================================
2 
3  A driver for PCMCIA IDE/ATA disk cards
4 
5  The contents of this file are subject to the Mozilla Public
6  License Version 1.1 (the "License"); you may not use this file
7  except in compliance with the License. You may obtain a copy of
8  the License at http://www.mozilla.org/MPL/
9 
10  Software distributed under the License is distributed on an "AS
11  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12  implied. See the License for the specific language governing
13  rights and limitations under the License.
14 
15  The initial developer of the original code is David A. Hinds
16  <[email protected]>. Portions created by David A. Hinds
17  are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
18 
19  Alternatively, the contents of this file may be used under the
20  terms of the GNU General Public License version 2 (the "GPL"), in
21  which case the provisions of the GPL are applicable instead of the
22  above. If you wish to allow the use of your version of this file
23  only under the terms of the GPL and not to allow others to use
24  your version of this file under the MPL, indicate your decision
25  by deleting the provisions above and replace them with the notice
26  and other provisions required by the GPL. If you do not delete
27  the provisions above, a recipient may use your version of this
28  file under either the MPL or the GPL.
29 
30 ======================================================================*/
31 
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/init.h>
35 #include <linux/ptrace.h>
36 #include <linux/slab.h>
37 #include <linux/string.h>
38 #include <linux/timer.h>
39 #include <linux/ioport.h>
40 #include <linux/ide.h>
41 #include <linux/major.h>
42 #include <linux/delay.h>
43 #include <asm/io.h>
44 
45 #include <pcmcia/cistpl.h>
46 #include <pcmcia/ds.h>
47 #include <pcmcia/cisreg.h>
48 #include <pcmcia/ciscode.h>
49 
50 #define DRV_NAME "ide-cs"
51 
52 /*====================================================================*/
53 
54 /* Module parameters */
55 
56 MODULE_AUTHOR("David Hinds <[email protected]>");
57 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
58 MODULE_LICENSE("Dual MPL/GPL");
59 
60 /*====================================================================*/
61 
62 typedef struct ide_info_t {
63  struct pcmcia_device *p_dev;
64  struct ide_host *host;
65  int ndev;
66 } ide_info_t;
67 
68 static void ide_release(struct pcmcia_device *);
69 static int ide_config(struct pcmcia_device *);
70 
71 static void ide_detach(struct pcmcia_device *p_dev);
72 
73 static int ide_probe(struct pcmcia_device *link)
74 {
76 
77  dev_dbg(&link->dev, "ide_attach()\n");
78 
79  /* Create new ide device */
80  info = kzalloc(sizeof(*info), GFP_KERNEL);
81  if (!info)
82  return -ENOMEM;
83 
84  info->p_dev = link;
85  link->priv = info;
86 
87  link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
88  CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
89 
90  return ide_config(link);
91 } /* ide_attach */
92 
93 static void ide_detach(struct pcmcia_device *link)
94 {
95  ide_info_t *info = link->priv;
96 
97  dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
98 
99  ide_release(link);
100 
101  kfree(info);
102 } /* ide_detach */
103 
104 static const struct ide_port_ops idecs_port_ops = {
105  .quirkproc = ide_undecoded_slave,
106 };
107 
108 static const struct ide_port_info idecs_port_info = {
109  .port_ops = &idecs_port_ops,
110  .host_flags = IDE_HFLAG_NO_DMA,
111  .irq_flags = IRQF_SHARED,
112  .chipset = ide_pci,
113 };
114 
115 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
116  unsigned long irq, struct pcmcia_device *handle)
117 {
118  struct ide_host *host;
119  ide_hwif_t *hwif;
120  int i, rc;
121  struct ide_hw hw, *hws[] = { &hw };
122 
123  if (!request_region(io, 8, DRV_NAME)) {
124  printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
125  DRV_NAME, io, io + 7);
126  return NULL;
127  }
128 
129  if (!request_region(ctl, 1, DRV_NAME)) {
130  printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
131  DRV_NAME, ctl);
132  release_region(io, 8);
133  return NULL;
134  }
135 
136  memset(&hw, 0, sizeof(hw));
137  ide_std_init_ports(&hw, io, ctl);
138  hw.irq = irq;
139  hw.dev = &handle->dev;
140 
141  rc = ide_host_add(&idecs_port_info, hws, 1, &host);
142  if (rc)
143  goto out_release;
144 
145  hwif = host->ports[0];
146 
147  if (hwif->present)
148  return host;
149 
150  /* retry registration in case device is still spinning up */
151  for (i = 0; i < 10; i++) {
152  msleep(100);
153  ide_port_scan(hwif);
154  if (hwif->present)
155  return host;
156  }
157 
158  return host;
159 
160 out_release:
161  release_region(ctl, 1);
162  release_region(io, 8);
163  return NULL;
164 }
165 
166 static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
167 {
168  int *is_kme = priv_data;
169 
170  if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH)
171  != IO_DATA_PATH_WIDTH_8) {
172  pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
173  pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
174  }
175  pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
176  pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
177 
178  if (pdev->resource[1]->end) {
179  pdev->resource[0]->end = 8;
180  pdev->resource[1]->end = (*is_kme) ? 2 : 1;
181  } else {
182  if (pdev->resource[0]->end < 16)
183  return -ENODEV;
184  }
185 
186  return pcmcia_request_io(pdev);
187 }
188 
189 static int ide_config(struct pcmcia_device *link)
190 {
191  ide_info_t *info = link->priv;
192  int ret = 0, is_kme = 0;
193  unsigned long io_base, ctl_base;
194  struct ide_host *host;
195 
196  dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
197 
198  is_kme = ((link->manf_id == MANFID_KME) &&
199  ((link->card_id == PRODID_KME_KXLC005_A) ||
200  (link->card_id == PRODID_KME_KXLC005_B)));
201 
202  if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
203  link->config_flags &= ~CONF_AUTO_CHECK_VCC;
204  if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
205  goto failed; /* No suitable config found */
206  }
207  io_base = link->resource[0]->start;
208  if (link->resource[1]->end)
209  ctl_base = link->resource[1]->start;
210  else
211  ctl_base = link->resource[0]->start + 0x0e;
212 
213  if (!link->irq)
214  goto failed;
215 
216  ret = pcmcia_enable_device(link);
217  if (ret)
218  goto failed;
219 
220  /* disable drive interrupts during IDE probe */
221  outb(0x02, ctl_base);
222 
223  /* special setup for KXLC005 card */
224  if (is_kme)
225  outb(0x81, ctl_base+1);
226 
227  host = idecs_register(io_base, ctl_base, link->irq, link);
228  if (host == NULL && resource_size(link->resource[0]) == 0x20) {
229  outb(0x02, ctl_base + 0x10);
230  host = idecs_register(io_base + 0x10, ctl_base + 0x10,
231  link->irq, link);
232  }
233 
234  if (host == NULL)
235  goto failed;
236 
237  info->ndev = 1;
238  info->host = host;
239  dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
240  'a' + host->ports[0]->index * 2,
241  link->vpp / 10, link->vpp % 10);
242 
243  return 0;
244 
245 failed:
246  ide_release(link);
247  return -ENODEV;
248 } /* ide_config */
249 
250 static void ide_release(struct pcmcia_device *link)
251 {
252  ide_info_t *info = link->priv;
253  struct ide_host *host = info->host;
254 
255  dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
256 
257  if (info->ndev) {
258  ide_hwif_t *hwif = host->ports[0];
259  unsigned long data_addr, ctl_addr;
260 
261  data_addr = hwif->io_ports.data_addr;
262  ctl_addr = hwif->io_ports.ctl_addr;
263 
264  ide_host_remove(host);
265  info->ndev = 0;
266 
267  release_region(ctl_addr, 1);
268  release_region(data_addr, 8);
269  }
270 
271  pcmcia_disable_device(link);
272 } /* ide_release */
273 
274 
275 static const struct pcmcia_device_id ide_ids[] = {
276  PCMCIA_DEVICE_FUNC_ID(4),
277  PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
278  PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
279  PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
280  PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
281  PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
282  PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
283  PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
284  PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
285  PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
286  PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
287  PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
288  PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
289  PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
290  PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
291  PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */
292  PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */
293  PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
294  PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
295  PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
296  PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
297  PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
298  PCMCIA_DEVICE_PROD_ID12("CNF ", "CD-ROM", 0x46d7db81, 0x66536591),
299  PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
300  PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
301  PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
302  PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
303  PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
304  PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
305  PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
306  PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
307  PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
308  PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
309  PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
310  PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
311  PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
312  PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
313  PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
314  PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
315  PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
316  PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
317  PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b),
318  PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
319  PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
320  PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
321  PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
322  PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
323  PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
324  PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
325  PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
326  PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
327  PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
328  PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443),
329  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
330  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
331  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
332  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
333  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
334  PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
335  PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
336  PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
337  PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
338  PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
339  PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
340  PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
341  PCMCIA_DEVICE_NULL,
342 };
343 MODULE_DEVICE_TABLE(pcmcia, ide_ids);
344 
345 static struct pcmcia_driver ide_cs_driver = {
346  .owner = THIS_MODULE,
347  .name = "ide-cs",
348  .probe = ide_probe,
349  .remove = ide_detach,
350  .id_table = ide_ids,
351 };
352 
353 static int __init init_ide_cs(void)
354 {
355  return pcmcia_register_driver(&ide_cs_driver);
356 }
357 
358 static void __exit exit_ide_cs(void)
359 {
360  pcmcia_unregister_driver(&ide_cs_driver);
361 }
362 
363 late_initcall(init_ide_cs);
364 module_exit(exit_ide_cs);