Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/ide/ide-cs.c
15109 views
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
#include <asm/system.h>
45
46
#include <pcmcia/cistpl.h>
47
#include <pcmcia/ds.h>
48
#include <pcmcia/cisreg.h>
49
#include <pcmcia/ciscode.h>
50
51
#define DRV_NAME "ide-cs"
52
53
/*====================================================================*/
54
55
/* Module parameters */
56
57
MODULE_AUTHOR("David Hinds <[email protected]>");
58
MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
59
MODULE_LICENSE("Dual MPL/GPL");
60
61
/*====================================================================*/
62
63
typedef struct ide_info_t {
64
struct pcmcia_device *p_dev;
65
struct ide_host *host;
66
int ndev;
67
} ide_info_t;
68
69
static void ide_release(struct pcmcia_device *);
70
static int ide_config(struct pcmcia_device *);
71
72
static void ide_detach(struct pcmcia_device *p_dev);
73
74
static int ide_probe(struct pcmcia_device *link)
75
{
76
ide_info_t *info;
77
78
dev_dbg(&link->dev, "ide_attach()\n");
79
80
/* Create new ide device */
81
info = kzalloc(sizeof(*info), GFP_KERNEL);
82
if (!info)
83
return -ENOMEM;
84
85
info->p_dev = link;
86
link->priv = info;
87
88
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
89
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
90
91
return ide_config(link);
92
} /* ide_attach */
93
94
static void ide_detach(struct pcmcia_device *link)
95
{
96
ide_info_t *info = link->priv;
97
98
dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
99
100
ide_release(link);
101
102
kfree(info);
103
} /* ide_detach */
104
105
static const struct ide_port_ops idecs_port_ops = {
106
.quirkproc = ide_undecoded_slave,
107
};
108
109
static const struct ide_port_info idecs_port_info = {
110
.port_ops = &idecs_port_ops,
111
.host_flags = IDE_HFLAG_NO_DMA,
112
.irq_flags = IRQF_SHARED,
113
.chipset = ide_pci,
114
};
115
116
static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
117
unsigned long irq, struct pcmcia_device *handle)
118
{
119
struct ide_host *host;
120
ide_hwif_t *hwif;
121
int i, rc;
122
struct ide_hw hw, *hws[] = { &hw };
123
124
if (!request_region(io, 8, DRV_NAME)) {
125
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
126
DRV_NAME, io, io + 7);
127
return NULL;
128
}
129
130
if (!request_region(ctl, 1, DRV_NAME)) {
131
printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
132
DRV_NAME, ctl);
133
release_region(io, 8);
134
return NULL;
135
}
136
137
memset(&hw, 0, sizeof(hw));
138
ide_std_init_ports(&hw, io, ctl);
139
hw.irq = irq;
140
hw.dev = &handle->dev;
141
142
rc = ide_host_add(&idecs_port_info, hws, 1, &host);
143
if (rc)
144
goto out_release;
145
146
hwif = host->ports[0];
147
148
if (hwif->present)
149
return host;
150
151
/* retry registration in case device is still spinning up */
152
for (i = 0; i < 10; i++) {
153
msleep(100);
154
ide_port_scan(hwif);
155
if (hwif->present)
156
return host;
157
}
158
159
return host;
160
161
out_release:
162
release_region(ctl, 1);
163
release_region(io, 8);
164
return NULL;
165
}
166
167
static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
168
{
169
int *is_kme = priv_data;
170
171
if (!(pdev->resource[0]->flags & 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);
365
366