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/cs_types.h>
53#include <pcmcia/cs.h>
54#include <pcmcia/cistpl.h>
55#include <pcmcia/ds.h>
56
57#ifdef PCMCIA_DEBUG
58static int pc_debug = PCMCIA_DEBUG;
59module_param(pc_debug, int, 0644);
60#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
61static char *version =
62"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)";
63#else
64#define DEBUG(n, args...)
65#endif
66
67
68
69
70
71
72static int host_id = 7;
73static int reconnect = 1;
74static int parity = 1;
75static int synchronous = 1;
76static int reset_delay = 100;
77static int ext_trans = 0;
78
79module_param(host_id, int, 0);
80module_param(reconnect, int, 0);
81module_param(parity, int, 0);
82module_param(synchronous, int, 0);
83module_param(reset_delay, int, 0);
84module_param(ext_trans, int, 0);
85
86MODULE_LICENSE("Dual MPL/GPL");
87
88
89
90typedef struct scsi_info_t {
91 struct pcmcia_device *p_dev;
92 dev_node_t node;
93 struct Scsi_Host *host;
94} scsi_info_t;
95
96static void aha152x_release_cs(struct pcmcia_device *link);
97static void aha152x_detach(struct pcmcia_device *p_dev);
98static int aha152x_config_cs(struct pcmcia_device *link);
99
100static struct pcmcia_device *dev_list;
101
102static int aha152x_probe(struct pcmcia_device *link)
103{
104 scsi_info_t *info;
105
106 DEBUG(0, "aha152x_attach()\n");
107
108
109 info = kzalloc(sizeof(*info), GFP_KERNEL);
110 if (!info) return -ENOMEM;
111 info->p_dev = link;
112 link->priv = info;
113
114 link->io.NumPorts1 = 0x20;
115 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
116 link->io.IOAddrLines = 10;
117 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
118 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
119 link->conf.Attributes = CONF_ENABLE_IRQ;
120 link->conf.IntType = INT_MEMORY_AND_IO;
121 link->conf.Present = PRESENT_OPTION;
122
123 return aha152x_config_cs(link);
124}
125
126
127
128static void aha152x_detach(struct pcmcia_device *link)
129{
130 DEBUG(0, "aha152x_detach(0x%p)\n", link);
131
132 aha152x_release_cs(link);
133
134
135 kfree(link->priv);
136}
137
138
139
140#define CS_CHECK(fn, ret) \
141do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
142
143static int aha152x_config_check(struct pcmcia_device *p_dev,
144 cistpl_cftable_entry_t *cfg,
145 cistpl_cftable_entry_t *dflt,
146 unsigned int vcc,
147 void *priv_data)
148{
149
150 if (cfg->io.win[0].len >= 0x20)
151 p_dev->io.BasePort1 = cfg->io.win[0].base;
152 else if ((cfg->io.nwin > 1) &&
153 (cfg->io.win[1].len >= 0x20))
154 p_dev->io.BasePort1 = cfg->io.win[1].base;
155 if ((cfg->io.nwin > 0) &&
156 (p_dev->io.BasePort1 < 0xffff)) {
157 if (!pcmcia_request_io(p_dev, &p_dev->io))
158 return 0;
159 }
160 return -EINVAL;
161}
162
163static int aha152x_config_cs(struct pcmcia_device *link)
164{
165 scsi_info_t *info = link->priv;
166 struct aha152x_setup s;
167 int last_ret, last_fn;
168 struct Scsi_Host *host;
169
170 DEBUG(0, "aha152x_config(0x%p)\n", link);
171
172 last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
173 if (last_ret) {
174 cs_error(link, RequestIO, last_ret);
175 goto failed;
176 }
177
178 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
179 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
180
181
182 memset(&s, 0, sizeof(s));
183 s.conf = "PCMCIA setup";
184 s.io_port = link->io.BasePort1;
185 s.irq = link->irq.AssignedIRQ;
186 s.scsiid = host_id;
187 s.reconnect = reconnect;
188 s.parity = parity;
189 s.synchronous = synchronous;
190 s.delay = reset_delay;
191 if (ext_trans)
192 s.ext_trans = ext_trans;
193
194 host = aha152x_probe_one(&s);
195 if (host == NULL) {
196 printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
197 goto cs_failed;
198 }
199
200 sprintf(info->node.dev_name, "scsi%d", host->host_no);
201 link->dev_node = &info->node;
202 info->host = host;
203
204 return 0;
205
206cs_failed:
207 cs_error(link, last_fn, last_ret);
208failed:
209 aha152x_release_cs(link);
210 return -ENODEV;
211}
212
213static void aha152x_release_cs(struct pcmcia_device *link)
214{
215 scsi_info_t *info = link->priv;
216
217 aha152x_release(info->host);
218 pcmcia_disable_device(link);
219}
220
221static int aha152x_resume(struct pcmcia_device *link)
222{
223 scsi_info_t *info = link->priv;
224
225 aha152x_host_reset_host(info->host);
226
227 return 0;
228}
229
230static struct pcmcia_device_id aha152x_ids[] = {
231 PCMCIA_DEVICE_PROD_ID123("New Media", "SCSI", "Bus Toaster", 0xcdf7e4cc, 0x35f26476, 0xa8851d6e),
232 PCMCIA_DEVICE_PROD_ID123("NOTEWORTHY", "SCSI", "Bus Toaster", 0xad89c6e8, 0x35f26476, 0xa8851d6e),
233 PCMCIA_DEVICE_PROD_ID12("Adaptec, Inc.", "APA-1460 SCSI Host Adapter", 0x24ba9738, 0x3a3c3d20),
234 PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Multimedia Sound/SCSI", 0x085a850b, 0x80a6535c),
235 PCMCIA_DEVICE_PROD_ID12("NOTEWORTHY", "NWCOMB02 SCSI/AUDIO COMBO CARD", 0xad89c6e8, 0x5f9a615b),
236 PCMCIA_DEVICE_NULL,
237};
238MODULE_DEVICE_TABLE(pcmcia, aha152x_ids);
239
240static struct pcmcia_driver aha152x_cs_driver = {
241 .owner = THIS_MODULE,
242 .drv = {
243 .name = "aha152x_cs",
244 },
245 .probe = aha152x_probe,
246 .remove = aha152x_detach,
247 .id_table = aha152x_ids,
248 .resume = aha152x_resume,
249};
250
251static int __init init_aha152x_cs(void)
252{
253 return pcmcia_register_driver(&aha152x_cs_driver);
254}
255
256static void __exit exit_aha152x_cs(void)
257{
258 pcmcia_unregister_driver(&aha152x_cs_driver);
259 BUG_ON(dev_list != NULL);
260}
261
262module_init(init_aha152x_cs);
263module_exit(exit_aha152x_cs);
264