1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/kernel.h>
40#include <linux/slab.h>
41#include <linux/string.h>
42#include <linux/ioport.h>
43#include <scsi/scsi.h>
44#include <linux/major.h>
45#include <linux/blkdev.h>
46#include <scsi/scsi_ioctl.h>
47
48#include "scsi.h"
49#include <scsi/scsi_host.h>
50#include "aha152x.h"
51
52#include <pcmcia/cistpl.h>
53#include <pcmcia/ds.h>
54
55
56
57
58
59
60
61static int host_id = 7;
62static int reconnect = 1;
63static int parity = 1;
64static int synchronous = 1;
65static int reset_delay = 100;
66static int ext_trans = 0;
67
68module_param(host_id, int, 0);
69module_param(reconnect, int, 0);
70module_param(parity, int, 0);
71module_param(synchronous, int, 0);
72module_param(reset_delay, int, 0);
73module_param(ext_trans, int, 0);
74
75MODULE_LICENSE("Dual MPL/GPL");
76
77
78
79typedef struct scsi_info_t {
80 struct pcmcia_device *p_dev;
81 struct Scsi_Host *host;
82} scsi_info_t;
83
84static void aha152x_release_cs(struct pcmcia_device *link);
85static void aha152x_detach(struct pcmcia_device *p_dev);
86static int aha152x_config_cs(struct pcmcia_device *link);
87
88static int aha152x_probe(struct pcmcia_device *link)
89{
90 scsi_info_t *info;
91
92 dev_dbg(&link->dev, "aha152x_attach()\n");
93
94
95 info = kzalloc(sizeof(*info), GFP_KERNEL);
96 if (!info) return -ENOMEM;
97 info->p_dev = link;
98 link->priv = info;
99
100 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
101 link->config_regs = PRESENT_OPTION;
102
103 return aha152x_config_cs(link);
104}
105
106
107
108static void aha152x_detach(struct pcmcia_device *link)
109{
110 dev_dbg(&link->dev, "aha152x_detach\n");
111
112 aha152x_release_cs(link);
113
114
115 kfree(link->priv);
116}
117
118
119
120static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
121{
122 p_dev->io_lines = 10;
123
124
125 if ((p_dev->resource[0]->end < 0x20) &&
126 (p_dev->resource[1]->end >= 0x20))
127 p_dev->resource[0]->start = p_dev->resource[1]->start;
128
129 if (p_dev->resource[0]->start >= 0xffff)
130 return -EINVAL;
131
132 p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
133 p_dev->resource[0]->end = 0x20;
134 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
135 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
136
137 return pcmcia_request_io(p_dev);
138}
139
140static int aha152x_config_cs(struct pcmcia_device *link)
141{
142 scsi_info_t *info = link->priv;
143 struct aha152x_setup s;
144 int ret;
145 struct Scsi_Host *host;
146
147 dev_dbg(&link->dev, "aha152x_config\n");
148
149 ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
150 if (ret)
151 goto failed;
152
153 if (!link->irq)
154 goto failed;
155
156 ret = pcmcia_enable_device(link);
157 if (ret)
158 goto failed;
159
160
161 memset(&s, 0, sizeof(s));
162 s.conf = "PCMCIA setup";
163 s.io_port = link->resource[0]->start;
164 s.irq = link->irq;
165 s.scsiid = host_id;
166 s.reconnect = reconnect;
167 s.parity = parity;
168 s.synchronous = synchronous;
169 s.delay = reset_delay;
170 if (ext_trans)
171 s.ext_trans = ext_trans;
172
173 host = aha152x_probe_one(&s);
174 if (host == NULL) {
175 printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
176 goto failed;
177 }
178
179 info->host = host;
180
181 return 0;
182
183failed:
184 aha152x_release_cs(link);
185 return -ENODEV;
186}
187
188static void aha152x_release_cs(struct pcmcia_device *link)
189{
190 scsi_info_t *info = link->priv;
191
192 aha152x_release(info->host);
193 pcmcia_disable_device(link);
194}
195
196static int aha152x_resume(struct pcmcia_device *link)
197{
198 scsi_info_t *info = link->priv;
199
200 aha152x_host_reset_host(info->host);
201
202 return 0;
203}
204
205static const struct pcmcia_device_id aha152x_ids[] = {
206 PCMCIA_DEVICE_PROD_ID123("New Media", "SCSI", "Bus Toaster", 0xcdf7e4cc, 0x35f26476, 0xa8851d6e),
207 PCMCIA_DEVICE_PROD_ID123("NOTEWORTHY", "SCSI", "Bus Toaster", 0xad89c6e8, 0x35f26476, 0xa8851d6e),
208 PCMCIA_DEVICE_PROD_ID12("Adaptec, Inc.", "APA-1460 SCSI Host Adapter", 0x24ba9738, 0x3a3c3d20),
209 PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Multimedia Sound/SCSI", 0x085a850b, 0x80a6535c),
210 PCMCIA_DEVICE_PROD_ID12("NOTEWORTHY", "NWCOMB02 SCSI/AUDIO COMBO CARD", 0xad89c6e8, 0x5f9a615b),
211 PCMCIA_DEVICE_NULL,
212};
213MODULE_DEVICE_TABLE(pcmcia, aha152x_ids);
214
215static struct pcmcia_driver aha152x_cs_driver = {
216 .owner = THIS_MODULE,
217 .name = "aha152x_cs",
218 .probe = aha152x_probe,
219 .remove = aha152x_detach,
220 .id_table = aha152x_ids,
221 .resume = aha152x_resume,
222};
223
224static int __init init_aha152x_cs(void)
225{
226 return pcmcia_register_driver(&aha152x_cs_driver);
227}
228
229static void __exit exit_aha152x_cs(void)
230{
231 pcmcia_unregister_driver(&aha152x_cs_driver);
232}
233
234module_init(init_aha152x_cs);
235module_exit(exit_aha152x_cs);
236