]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/ide/ide-cs.c
Merge git://1984.lsi.us.es/net-next
[mirror_ubuntu-bionic-kernel.git] / drivers / ide / ide-cs.c
CommitLineData
1da177e4
LT
1/*======================================================================
2
3 A driver for PCMCIA IDE/ATA disk cards
4
1da177e4
LT
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 <dahinds@users.sourceforge.net>. 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.
7b1dec59 29
1da177e4
LT
30======================================================================*/
31
32#include <linux/module.h>
33#include <linux/kernel.h>
34#include <linux/init.h>
1da177e4
LT
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>
1da177e4 41#include <linux/major.h>
2aad5f03 42#include <linux/delay.h>
1da177e4 43#include <asm/io.h>
1da177e4 44
1da177e4
LT
45#include <pcmcia/cistpl.h>
46#include <pcmcia/ds.h>
47#include <pcmcia/cisreg.h>
48#include <pcmcia/ciscode.h>
49
d703b79e
BZ
50#define DRV_NAME "ide-cs"
51
1da177e4
LT
52/*====================================================================*/
53
54/* Module parameters */
55
56MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
57MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
58MODULE_LICENSE("Dual MPL/GPL");
59
1da177e4
LT
60/*====================================================================*/
61
1da177e4 62typedef struct ide_info_t {
fd238232 63 struct pcmcia_device *p_dev;
48c3c107 64 struct ide_host *host;
ded6a1a3 65 int ndev;
1da177e4
LT
66} ide_info_t;
67
fba395ee 68static void ide_release(struct pcmcia_device *);
15b99ac1 69static int ide_config(struct pcmcia_device *);
1da177e4 70
cc3b4866 71static void ide_detach(struct pcmcia_device *p_dev);
1da177e4 72
15b99ac1 73static int ide_probe(struct pcmcia_device *link)
1da177e4
LT
74{
75 ide_info_t *info;
f8cfa618 76
444486a5 77 dev_dbg(&link->dev, "ide_attach()\n");
1da177e4
LT
78
79 /* Create new ide device */
f5e3c2fa 80 info = kzalloc(sizeof(*info), GFP_KERNEL);
f8cfa618
DB
81 if (!info)
82 return -ENOMEM;
fd238232 83
fba395ee 84 info->p_dev = link;
fd238232 85 link->priv = info;
1da177e4 86
00990e7c
DB
87 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
88 CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
f8cfa618 89
15b99ac1 90 return ide_config(link);
1da177e4
LT
91} /* ide_attach */
92
fba395ee 93static void ide_detach(struct pcmcia_device *link)
1da177e4 94{
d703b79e 95 ide_info_t *info = link->priv;
d703b79e 96
444486a5 97 dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
1da177e4 98
e2d40963 99 ide_release(link);
b4635811 100
d703b79e 101 kfree(info);
1da177e4
LT
102} /* ide_detach */
103
ac95beed
BZ
104static const struct ide_port_ops idecs_port_ops = {
105 .quirkproc = ide_undecoded_slave,
106};
107
dccdf527
BZ
108static const struct ide_port_info idecs_port_info = {
109 .port_ops = &idecs_port_ops,
110 .host_flags = IDE_HFLAG_NO_DMA,
255115fb 111 .irq_flags = IRQF_SHARED,
29e52cf7 112 .chipset = ide_pci,
dccdf527
BZ
113};
114
48c3c107 115static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
d703b79e 116 unsigned long irq, struct pcmcia_device *handle)
1da177e4 117{
48c3c107 118 struct ide_host *host;
9e016a71 119 ide_hwif_t *hwif;
6f904d01 120 int i, rc;
9f36d314 121 struct ide_hw hw, *hws[] = { &hw };
9e016a71 122
d703b79e
BZ
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
1da177e4 136 memset(&hw, 0, sizeof(hw));
dcb425f5 137 ide_std_init_ports(&hw, io, ctl);
1da177e4 138 hw.irq = irq;
4349d5cd 139 hw.dev = &handle->dev;
9e016a71 140
dca39830 141 rc = ide_host_add(&idecs_port_info, hws, 1, &host);
6f904d01 142 if (rc)
d703b79e 143 goto out_release;
9e016a71 144
48c3c107 145 hwif = host->ports[0];
9e016a71 146
d703b79e 147 if (hwif->present)
48c3c107 148 return host;
d703b79e 149
792a1a98
BZ
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)
48c3c107 155 return host;
792a1a98
BZ
156 }
157
48c3c107 158 return host;
792a1a98 159
d703b79e
BZ
160out_release:
161 release_region(ctl, 1);
162 release_region(io, 8);
163 return NULL;
1da177e4
LT
164}
165
00990e7c 166static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
0bac660a 167{
00990e7c
DB
168 int *is_kme = priv_data;
169
170 if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
171 pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
172 pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
173 }
174 pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
175 pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
176
177 if (pdev->resource[1]->end) {
178 pdev->resource[0]->end = 8;
179 pdev->resource[1]->end = (*is_kme) ? 2 : 1;
180 } else {
181 if (pdev->resource[0]->end < 16)
8e2fc39d 182 return -ENODEV;
0bac660a 183 }
00990e7c
DB
184
185 return pcmcia_request_io(pdev);
0bac660a
DB
186}
187
15b99ac1 188static int ide_config(struct pcmcia_device *link)
1da177e4 189{
1da177e4 190 ide_info_t *info = link->priv;
444486a5 191 int ret = 0, is_kme = 0;
2f1b9250 192 unsigned long io_base, ctl_base;
48c3c107 193 struct ide_host *host;
1da177e4 194
444486a5 195 dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
1da177e4 196
efd50585
DB
197 is_kme = ((link->manf_id == MANFID_KME) &&
198 ((link->card_id == PRODID_KME_KXLC005_A) ||
199 (link->card_id == PRODID_KME_KXLC005_B)));
1da177e4 200
00990e7c 201 if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
440eed43 202 link->config_flags &= ~CONF_AUTO_CHECK_VCC;
00990e7c 203 if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
0bac660a 204 goto failed; /* No suitable config found */
1da177e4 205 }
9a017a91 206 io_base = link->resource[0]->start;
00990e7c
DB
207 if (link->resource[1]->end)
208 ctl_base = link->resource[1]->start;
209 else
210 ctl_base = link->resource[0]->start + 0x0e;
1da177e4 211
eb14120f 212 if (!link->irq)
444486a5 213 goto failed;
1ac71e5a
DB
214
215 ret = pcmcia_enable_device(link);
444486a5
DB
216 if (ret)
217 goto failed;
1da177e4
LT
218
219 /* disable drive interrupts during IDE probe */
2f1b9250 220 outb(0x02, ctl_base);
1da177e4
LT
221
222 /* special setup for KXLC005 card */
223 if (is_kme)
2f1b9250 224 outb(0x81, ctl_base+1);
1da177e4 225
eb14120f 226 host = idecs_register(io_base, ctl_base, link->irq, link);
9a017a91 227 if (host == NULL && resource_size(link->resource[0]) == 0x20) {
2f1b9250 228 outb(0x02, ctl_base + 0x10);
48c3c107 229 host = idecs_register(io_base + 0x10, ctl_base + 0x10,
eb14120f 230 link->irq, link);
1da177e4
LT
231 }
232
48c3c107 233 if (host == NULL)
1da177e4 234 goto failed;
1da177e4
LT
235
236 info->ndev = 1;
48c3c107 237 info->host = host;
ded6a1a3
DB
238 dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
239 'a' + host->ports[0]->index * 2,
e8405f0f 240 link->vpp / 10, link->vpp % 10);
1da177e4 241
15b99ac1 242 return 0;
1da177e4 243
1da177e4 244failed:
1da177e4 245 ide_release(link);
15b99ac1 246 return -ENODEV;
1da177e4
LT
247} /* ide_config */
248
727c6742 249static void ide_release(struct pcmcia_device *link)
1da177e4
LT
250{
251 ide_info_t *info = link->priv;
48c3c107 252 struct ide_host *host = info->host;
7b1dec59 253
444486a5 254 dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
1da177e4 255
d4ae5415
WS
256 if (info->ndev) {
257 ide_hwif_t *hwif = host->ports[0];
258 unsigned long data_addr, ctl_addr;
259
260 data_addr = hwif->io_ports.data_addr;
261 ctl_addr = hwif->io_ports.ctl_addr;
262
48c3c107 263 ide_host_remove(host);
d4ae5415 264 info->ndev = 0;
48c3c107 265
d4ae5415
WS
266 release_region(ctl_addr, 1);
267 release_region(data_addr, 8);
268 }
1da177e4 269
fba395ee 270 pcmcia_disable_device(link);
1da177e4
LT
271} /* ide_release */
272
98e4c28b 273
25f8f54f 274static const struct pcmcia_device_id ide_ids[] = {
f70b7d40 275 PCMCIA_DEVICE_FUNC_ID(4),
7b1dec59 276 PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
725a6abf 277 PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
ed896167
MD
278 PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
279 PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
f70b7d40 280 PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
795659ef 281 PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
ed896167 282 PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
a49c06bf 283 PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
795659ef 284 PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
d3feb184 285 PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
f70b7d40 286 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
d3feb184 287 PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
7b1dec59 288 PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
f70b7d40 289 PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
ed896167
MD
290 PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0100), /* Viking CFA */
291 PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar, Viking CFA */
f70b7d40
DB
292 PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
293 PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
294 PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
295 PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
296 PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
c9a2bfd1 297 PCMCIA_DEVICE_PROD_ID12("CNF ", "CD-ROM", 0x46d7db81, 0x66536591),
f70b7d40
DB
298 PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
299 PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
300 PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
d277ad0e 301 PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf),
f70b7d40
DB
302 PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
303 PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
304 PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
725a6abf
RP
305 PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
306 PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
7b1dec59 307 PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
264a3412 308 PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
f70b7d40 309 PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
85ea2d3f 310 PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
f25798ed 311 PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
363f7e42 312 PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
f70b7d40
DB
313 PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
314 PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
315 PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
316 PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b),
74e23386 317 PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF300", 0x7ed2ad87, 0x7e9e78ee),
4fa902a9 318 PCMCIA_DEVICE_PROD_ID12("M-Systems", "CF500", 0x7ed2ad87, 0x7a13045c),
2570b746 319 PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
f70b7d40
DB
320 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
321 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
322 PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
4fa902a9
MJ
323 PCMCIA_DEVICE_PROD_ID12("SEAGATE", "ST1", 0x87c1b330, 0xe1f30883),
324 PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d),
325 PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
f70b7d40 326 PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
42935656 327 PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443),
a17bf220 328 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF45", 0x709b1bf1, 0xf68b6f32),
bf4e1829 329 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
aa12b284 330 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
4fa902a9 331 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
85ea2d3f 332 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
f25798ed 333 PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
f70b7d40 334 PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
0517793f 335 PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
f70b7d40 336 PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
d3feb184 337 PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
698e22c4 338 PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
980fc29f 339 PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506),
f70b7d40
DB
340 PCMCIA_DEVICE_NULL,
341};
342MODULE_DEVICE_TABLE(pcmcia, ide_ids);
343
1da177e4
LT
344static struct pcmcia_driver ide_cs_driver = {
345 .owner = THIS_MODULE,
2e9b981a 346 .name = "ide-cs",
15b99ac1 347 .probe = ide_probe,
cc3b4866 348 .remove = ide_detach,
f70b7d40 349 .id_table = ide_ids,
1da177e4
LT
350};
351
352static int __init init_ide_cs(void)
353{
354 return pcmcia_register_driver(&ide_cs_driver);
355}
356
357static void __exit exit_ide_cs(void)
358{
359 pcmcia_unregister_driver(&ide_cs_driver);
1da177e4
LT
360}
361
2b8d4669 362late_initcall(init_ide_cs);
1da177e4 363module_exit(exit_ide_cs);