aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pcmcia
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/scsi/pcmcia
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/scsi/pcmcia')
-rw-r--r--drivers/scsi/pcmcia/Kconfig82
-rw-r--r--drivers/scsi/pcmcia/Makefile13
-rw-r--r--drivers/scsi/pcmcia/aha152x_core.c3
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c343
-rw-r--r--drivers/scsi/pcmcia/fdomain_core.c2
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c323
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c2198
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h472
-rw-r--r--drivers/scsi/pcmcia/nsp_debug.c215
-rw-r--r--drivers/scsi/pcmcia/nsp_io.h274
-rw-r--r--drivers/scsi/pcmcia/nsp_message.c78
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c425
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c1022
13 files changed, 5450 insertions, 0 deletions
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
new file mode 100644
index 000000000000..df52190f4d94
--- /dev/null
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -0,0 +1,82 @@
1#
2# PCMCIA SCSI adapter configuration
3#
4
5menu "PCMCIA SCSI adapter support"
6 depends on SCSI!=n && PCMCIA!=n && MODULES
7
8config PCMCIA_AHA152X
9 tristate "Adaptec AHA152X PCMCIA support"
10 depends on m && !64BIT
11 help
12 Say Y here if you intend to attach this type of PCMCIA SCSI host
13 adapter to your computer.
14
15 To compile this driver as a module, choose M here: the
16 module will be called aha152x_cs.
17
18config PCMCIA_FDOMAIN
19 tristate "Future Domain PCMCIA support"
20 depends on m
21 help
22 Say Y here if you intend to attach this type of PCMCIA SCSI host
23 adapter to your computer.
24
25 To compile this driver as a module, choose M here: the
26 module will be called fdomain_cs.
27
28config PCMCIA_NINJA_SCSI
29 tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
30 depends on m && !64BIT
31 help
32 If you intend to attach this type of PCMCIA SCSI host adapter to
33 your computer, say Y here and read
34 <file:Documentation/scsi/NinjaSCSI.txt>.
35
36 Supported cards:
37
38 NinjaSCSI-3: (version string: "WBT","NinjaSCSI-3","R1.0")
39 IO-DATA PCSC-FP
40 ALPHA DATA AD-PCS201
41 CyQ've SFC-201
42 LOGITECH LPM-SCSI2E
43 Pioneer PCR-PR24's card
44 I-O DATA CDPS-PX24's card (PCSC-F)
45 Panasonic KXL-RW10AN CD-RW's card
46 etc.
47
48 NinjaSCSI-32Bit (in 16bit mode):
49 [Workbit (version string: "WORKBIT","UltraNinja-16","1")]
50 Jazz SCP050
51 [I-O DATA (OEM) (version string: "IO DATA","CBSC16 ","1")]
52 I-O DATA CBSC-II
53 [Kyusyu Matsushita Kotobuki (OEM)
54 (version string: "KME ","SCSI-CARD-001","1")]
55 KME KXL-820AN's card
56 HP M820e CDRW's card
57 etc.
58
59 To compile this driver as a module, choose M here: the
60 module will be called nsp_cs.
61
62config PCMCIA_QLOGIC
63 tristate "Qlogic PCMCIA support"
64 depends on m
65 help
66 Say Y here if you intend to attach this type of PCMCIA SCSI host
67 adapter to your computer.
68
69 To compile this driver as a module, choose M here: the
70 module will be called qlogic_cs.
71
72config PCMCIA_SYM53C500
73 tristate "Symbios 53c500 PCMCIA support"
74 depends on m
75 help
76 Say Y here if you have a New Media Bus Toaster or other PCMCIA
77 SCSI adapter based on the Symbios 53c500 controller.
78
79 To compile this driver as a module, choose M here: the
80 module will be called sym53c500_cs.
81
82endmenu
diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile
new file mode 100644
index 000000000000..eca379059db6
--- /dev/null
+++ b/drivers/scsi/pcmcia/Makefile
@@ -0,0 +1,13 @@
1
2EXTRA_CFLAGS += -Idrivers/scsi
3
4# 16-bit client drivers
5obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs.o
6obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o
7obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o
8obj-$(CONFIG_PCMCIA_NINJA_SCSI) += nsp_cs.o
9obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o
10
11aha152x_cs-objs := aha152x_stub.o aha152x_core.o
12fdomain_cs-objs := fdomain_stub.o fdomain_core.o
13qlogic_cs-objs := qlogic_stub.o
diff --git a/drivers/scsi/pcmcia/aha152x_core.c b/drivers/scsi/pcmcia/aha152x_core.c
new file mode 100644
index 000000000000..dba3716511c5
--- /dev/null
+++ b/drivers/scsi/pcmcia/aha152x_core.c
@@ -0,0 +1,3 @@
1#define PCMCIA 1
2#define AHA152X_STAT 1
3#include "aha152x.c"
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
new file mode 100644
index 000000000000..e60b4c0a8427
--- /dev/null
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -0,0 +1,343 @@
1/*======================================================================
2
3 A driver for Adaptec AHA152X-compatible PCMCIA SCSI cards.
4
5 This driver supports the Adaptec AHA-1460, the New Media Bus
6 Toaster, and the New Media Toast & Jam.
7
8 aha152x_cs.c 1.54 2000/06/12 21:27:25
9
10 The contents of this file are subject to the Mozilla Public
11 License Version 1.1 (the "License"); you may not use this file
12 except in compliance with the License. You may obtain a copy of
13 the License at http://www.mozilla.org/MPL/
14
15 Software distributed under the License is distributed on an "AS
16 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 implied. See the License for the specific language governing
18 rights and limitations under the License.
19
20 The initial developer of the original code is David A. Hinds
21 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
22 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
23
24 Alternatively, the contents of this file may be used under the
25 terms of the GNU General Public License version 2 (the "GPL"), in which
26 case the provisions of the GPL are applicable instead of the
27 above. If you wish to allow the use of your version of this file
28 only under the terms of the GPL and not to allow others to use
29 your version of this file under the MPL, indicate your decision
30 by deleting the provisions above and replace them with the notice
31 and other provisions required by the GPL. If you do not delete
32 the provisions above, a recipient may use your version of this
33 file under either the MPL or the GPL.
34
35======================================================================*/
36
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/kernel.h>
40#include <linux/sched.h>
41#include <linux/slab.h>
42#include <linux/string.h>
43#include <linux/ioport.h>
44#include <scsi/scsi.h>
45#include <linux/major.h>
46#include <linux/blkdev.h>
47#include <scsi/scsi_ioctl.h>
48
49#include "scsi.h"
50#include <scsi/scsi_host.h>
51#include "aha152x.h"
52
53#include <pcmcia/version.h>
54#include <pcmcia/cs_types.h>
55#include <pcmcia/cs.h>
56#include <pcmcia/cistpl.h>
57#include <pcmcia/ds.h>
58
59#ifdef PCMCIA_DEBUG
60static int pc_debug = PCMCIA_DEBUG;
61module_param(pc_debug, int, 0644);
62#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
63static char *version =
64"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)";
65#else
66#define DEBUG(n, args...)
67#endif
68
69/*====================================================================*/
70
71/* Parameters that can be set with 'insmod' */
72
73/* SCSI bus setup options */
74static int host_id = 7;
75static int reconnect = 1;
76static int parity = 1;
77static int synchronous = 1;
78static int reset_delay = 100;
79static int ext_trans = 0;
80
81module_param(host_id, int, 0);
82module_param(reconnect, int, 0);
83module_param(parity, int, 0);
84module_param(synchronous, int, 0);
85module_param(reset_delay, int, 0);
86module_param(ext_trans, int, 0);
87
88MODULE_LICENSE("Dual MPL/GPL");
89
90/*====================================================================*/
91
92typedef struct scsi_info_t {
93 dev_link_t link;
94 dev_node_t node;
95 struct Scsi_Host *host;
96} scsi_info_t;
97
98static void aha152x_release_cs(dev_link_t *link);
99static int aha152x_event(event_t event, int priority,
100 event_callback_args_t *args);
101
102static dev_link_t *aha152x_attach(void);
103static void aha152x_detach(dev_link_t *);
104
105static dev_link_t *dev_list;
106static dev_info_t dev_info = "aha152x_cs";
107
108static dev_link_t *aha152x_attach(void)
109{
110 scsi_info_t *info;
111 client_reg_t client_reg;
112 dev_link_t *link;
113 int ret;
114
115 DEBUG(0, "aha152x_attach()\n");
116
117 /* Create new SCSI device */
118 info = kmalloc(sizeof(*info), GFP_KERNEL);
119 if (!info) return NULL;
120 memset(info, 0, sizeof(*info));
121 link = &info->link; link->priv = info;
122
123 link->io.NumPorts1 = 0x20;
124 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
125 link->io.IOAddrLines = 10;
126 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
127 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
128 link->conf.Attributes = CONF_ENABLE_IRQ;
129 link->conf.Vcc = 50;
130 link->conf.IntType = INT_MEMORY_AND_IO;
131 link->conf.Present = PRESENT_OPTION;
132
133 /* Register with Card Services */
134 link->next = dev_list;
135 dev_list = link;
136 client_reg.dev_info = &dev_info;
137 client_reg.event_handler = &aha152x_event;
138 client_reg.EventMask =
139 CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
140 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
141 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
142 client_reg.Version = 0x0210;
143 client_reg.event_callback_args.client_data = link;
144 ret = pcmcia_register_client(&link->handle, &client_reg);
145 if (ret != 0) {
146 cs_error(link->handle, RegisterClient, ret);
147 aha152x_detach(link);
148 return NULL;
149 }
150
151 return link;
152} /* aha152x_attach */
153
154/*====================================================================*/
155
156static void aha152x_detach(dev_link_t *link)
157{
158 dev_link_t **linkp;
159
160 DEBUG(0, "aha152x_detach(0x%p)\n", link);
161
162 /* Locate device structure */
163 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
164 if (*linkp == link) break;
165 if (*linkp == NULL)
166 return;
167
168 if (link->state & DEV_CONFIG)
169 aha152x_release_cs(link);
170
171 if (link->handle)
172 pcmcia_deregister_client(link->handle);
173
174 /* Unlink device structure, free bits */
175 *linkp = link->next;
176 kfree(link->priv);
177
178} /* aha152x_detach */
179
180/*====================================================================*/
181
182#define CS_CHECK(fn, ret) \
183do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
184
185static void aha152x_config_cs(dev_link_t *link)
186{
187 client_handle_t handle = link->handle;
188 scsi_info_t *info = link->priv;
189 struct aha152x_setup s;
190 tuple_t tuple;
191 cisparse_t parse;
192 int i, last_ret, last_fn;
193 u_char tuple_data[64];
194 struct Scsi_Host *host;
195
196 DEBUG(0, "aha152x_config(0x%p)\n", link);
197
198 tuple.DesiredTuple = CISTPL_CONFIG;
199 tuple.TupleData = tuple_data;
200 tuple.TupleDataMax = 64;
201 tuple.TupleOffset = 0;
202 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
203 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
204 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
205 link->conf.ConfigBase = parse.config.base;
206
207 /* Configure card */
208 link->state |= DEV_CONFIG;
209
210 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
211 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
212 while (1) {
213 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
214 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
215 goto next_entry;
216 /* For New Media T&J, look for a SCSI window */
217 if (parse.cftable_entry.io.win[0].len >= 0x20)
218 link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
219 else if ((parse.cftable_entry.io.nwin > 1) &&
220 (parse.cftable_entry.io.win[1].len >= 0x20))
221 link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
222 if ((parse.cftable_entry.io.nwin > 0) &&
223 (link->io.BasePort1 < 0xffff)) {
224 link->conf.ConfigIndex = parse.cftable_entry.index;
225 i = pcmcia_request_io(handle, &link->io);
226 if (i == CS_SUCCESS) break;
227 }
228 next_entry:
229 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
230 }
231
232 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
233 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
234
235 /* Set configuration options for the aha152x driver */
236 memset(&s, 0, sizeof(s));
237 s.conf = "PCMCIA setup";
238 s.io_port = link->io.BasePort1;
239 s.irq = link->irq.AssignedIRQ;
240 s.scsiid = host_id;
241 s.reconnect = reconnect;
242 s.parity = parity;
243 s.synchronous = synchronous;
244 s.delay = reset_delay;
245 if (ext_trans)
246 s.ext_trans = ext_trans;
247
248 host = aha152x_probe_one(&s);
249 if (host == NULL) {
250 printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
251 goto cs_failed;
252 }
253
254 sprintf(info->node.dev_name, "scsi%d", host->host_no);
255 link->dev = &info->node;
256 info->host = host;
257
258 link->state &= ~DEV_CONFIG_PENDING;
259 return;
260
261cs_failed:
262 cs_error(link->handle, last_fn, last_ret);
263 aha152x_release_cs(link);
264 return;
265}
266
267static void aha152x_release_cs(dev_link_t *link)
268{
269 scsi_info_t *info = link->priv;
270
271 aha152x_release(info->host);
272 link->dev = NULL;
273
274 pcmcia_release_configuration(link->handle);
275 pcmcia_release_io(link->handle, &link->io);
276 pcmcia_release_irq(link->handle, &link->irq);
277
278 link->state &= ~DEV_CONFIG;
279}
280
281static int aha152x_event(event_t event, int priority,
282 event_callback_args_t *args)
283{
284 dev_link_t *link = args->client_data;
285 scsi_info_t *info = link->priv;
286
287 DEBUG(0, "aha152x_event(0x%06x)\n", event);
288
289 switch (event) {
290 case CS_EVENT_CARD_REMOVAL:
291 link->state &= ~DEV_PRESENT;
292 if (link->state & DEV_CONFIG)
293 aha152x_release_cs(link);
294 break;
295 case CS_EVENT_CARD_INSERTION:
296 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
297 aha152x_config_cs(link);
298 break;
299 case CS_EVENT_PM_SUSPEND:
300 link->state |= DEV_SUSPEND;
301 /* Fall through... */
302 case CS_EVENT_RESET_PHYSICAL:
303 if (link->state & DEV_CONFIG)
304 pcmcia_release_configuration(link->handle);
305 break;
306 case CS_EVENT_PM_RESUME:
307 link->state &= ~DEV_SUSPEND;
308 /* Fall through... */
309 case CS_EVENT_CARD_RESET:
310 if (link->state & DEV_CONFIG) {
311 Scsi_Cmnd tmp;
312 pcmcia_request_configuration(link->handle, &link->conf);
313 tmp.device->host = info->host;
314 aha152x_host_reset(&tmp);
315 }
316 break;
317 }
318 return 0;
319}
320
321static struct pcmcia_driver aha152x_cs_driver = {
322 .owner = THIS_MODULE,
323 .drv = {
324 .name = "aha152x_cs",
325 },
326 .attach = aha152x_attach,
327 .detach = aha152x_detach,
328};
329
330static int __init init_aha152x_cs(void)
331{
332 return pcmcia_register_driver(&aha152x_cs_driver);
333}
334
335static void __exit exit_aha152x_cs(void)
336{
337 pcmcia_unregister_driver(&aha152x_cs_driver);
338 BUG_ON(dev_list != NULL);
339}
340
341module_init(init_aha152x_cs);
342module_exit(exit_aha152x_cs);
343
diff --git a/drivers/scsi/pcmcia/fdomain_core.c b/drivers/scsi/pcmcia/fdomain_core.c
new file mode 100644
index 000000000000..a48913791868
--- /dev/null
+++ b/drivers/scsi/pcmcia/fdomain_core.c
@@ -0,0 +1,2 @@
1#define PCMCIA 1
2#include "fdomain.c"
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
new file mode 100644
index 000000000000..3df7bc72e354
--- /dev/null
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -0,0 +1,323 @@
1/*======================================================================
2
3 A driver for Future Domain-compatible PCMCIA SCSI cards
4
5 fdomain_cs.c 1.47 2001/10/13 00:08:52
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in
23 which case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/kernel.h>
37#include <linux/sched.h>
38#include <linux/slab.h>
39#include <linux/string.h>
40#include <linux/ioport.h>
41#include <scsi/scsi.h>
42#include <linux/major.h>
43#include <linux/blkdev.h>
44#include <scsi/scsi_ioctl.h>
45
46#include "scsi.h"
47#include <scsi/scsi_host.h>
48#include "fdomain.h"
49
50#include <pcmcia/version.h>
51#include <pcmcia/cs_types.h>
52#include <pcmcia/cs.h>
53#include <pcmcia/cistpl.h>
54#include <pcmcia/ds.h>
55
56/*====================================================================*/
57
58/* Module parameters */
59
60MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
61MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
62MODULE_LICENSE("Dual MPL/GPL");
63
64#ifdef PCMCIA_DEBUG
65static int pc_debug = PCMCIA_DEBUG;
66module_param(pc_debug, int, 0);
67#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
68static char *version =
69"fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
70#else
71#define DEBUG(n, args...)
72#endif
73
74/*====================================================================*/
75
76typedef struct scsi_info_t {
77 dev_link_t link;
78 dev_node_t node;
79 struct Scsi_Host *host;
80} scsi_info_t;
81
82
83static void fdomain_release(dev_link_t *link);
84static int fdomain_event(event_t event, int priority,
85 event_callback_args_t *args);
86
87static dev_link_t *fdomain_attach(void);
88static void fdomain_detach(dev_link_t *);
89
90
91static dev_link_t *dev_list = NULL;
92
93static dev_info_t dev_info = "fdomain_cs";
94
95static dev_link_t *fdomain_attach(void)
96{
97 scsi_info_t *info;
98 client_reg_t client_reg;
99 dev_link_t *link;
100 int ret;
101
102 DEBUG(0, "fdomain_attach()\n");
103
104 /* Create new SCSI device */
105 info = kmalloc(sizeof(*info), GFP_KERNEL);
106 if (!info) return NULL;
107 memset(info, 0, sizeof(*info));
108 link = &info->link; link->priv = info;
109 link->io.NumPorts1 = 0x10;
110 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
111 link->io.IOAddrLines = 10;
112 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
113 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
114 link->conf.Attributes = CONF_ENABLE_IRQ;
115 link->conf.Vcc = 50;
116 link->conf.IntType = INT_MEMORY_AND_IO;
117 link->conf.Present = PRESENT_OPTION;
118
119 /* Register with Card Services */
120 link->next = dev_list;
121 dev_list = link;
122 client_reg.dev_info = &dev_info;
123 client_reg.event_handler = &fdomain_event;
124 client_reg.EventMask =
125 CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
126 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
127 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
128 client_reg.Version = 0x0210;
129 client_reg.event_callback_args.client_data = link;
130 ret = pcmcia_register_client(&link->handle, &client_reg);
131 if (ret != 0) {
132 cs_error(link->handle, RegisterClient, ret);
133 fdomain_detach(link);
134 return NULL;
135 }
136
137 return link;
138} /* fdomain_attach */
139
140/*====================================================================*/
141
142static void fdomain_detach(dev_link_t *link)
143{
144 dev_link_t **linkp;
145
146 DEBUG(0, "fdomain_detach(0x%p)\n", link);
147
148 /* Locate device structure */
149 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
150 if (*linkp == link) break;
151 if (*linkp == NULL)
152 return;
153
154 if (link->state & DEV_CONFIG)
155 fdomain_release(link);
156
157 if (link->handle)
158 pcmcia_deregister_client(link->handle);
159
160 /* Unlink device structure, free bits */
161 *linkp = link->next;
162 kfree(link->priv);
163
164} /* fdomain_detach */
165
166/*====================================================================*/
167
168#define CS_CHECK(fn, ret) \
169do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
170
171static void fdomain_config(dev_link_t *link)
172{
173 client_handle_t handle = link->handle;
174 scsi_info_t *info = link->priv;
175 tuple_t tuple;
176 cisparse_t parse;
177 int i, last_ret, last_fn;
178 u_char tuple_data[64];
179 char str[16];
180 struct Scsi_Host *host;
181
182 DEBUG(0, "fdomain_config(0x%p)\n", link);
183
184 tuple.DesiredTuple = CISTPL_CONFIG;
185 tuple.TupleData = tuple_data;
186 tuple.TupleDataMax = 64;
187 tuple.TupleOffset = 0;
188 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
189 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
190 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
191 link->conf.ConfigBase = parse.config.base;
192
193 /* Configure card */
194 link->state |= DEV_CONFIG;
195
196 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
197 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
198 while (1) {
199 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
200 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
201 goto next_entry;
202 link->conf.ConfigIndex = parse.cftable_entry.index;
203 link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
204 i = pcmcia_request_io(handle, &link->io);
205 if (i == CS_SUCCESS) break;
206 next_entry:
207 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
208 }
209
210 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
211 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
212
213 /* A bad hack... */
214 release_region(link->io.BasePort1, link->io.NumPorts1);
215
216 /* Set configuration options for the fdomain driver */
217 sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
218 fdomain_setup(str);
219
220 host = __fdomain_16x0_detect(&fdomain_driver_template);
221 if (!host) {
222 printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
223 goto cs_failed;
224 }
225
226 scsi_add_host(host, NULL); /* XXX handle failure */
227 scsi_scan_host(host);
228
229 sprintf(info->node.dev_name, "scsi%d", host->host_no);
230 link->dev = &info->node;
231 info->host = host;
232
233 link->state &= ~DEV_CONFIG_PENDING;
234 return;
235
236cs_failed:
237 cs_error(link->handle, last_fn, last_ret);
238 fdomain_release(link);
239 return;
240
241} /* fdomain_config */
242
243/*====================================================================*/
244
245static void fdomain_release(dev_link_t *link)
246{
247 scsi_info_t *info = link->priv;
248
249 DEBUG(0, "fdomain_release(0x%p)\n", link);
250
251 scsi_remove_host(info->host);
252 link->dev = NULL;
253
254 pcmcia_release_configuration(link->handle);
255 pcmcia_release_io(link->handle, &link->io);
256 pcmcia_release_irq(link->handle, &link->irq);
257
258 scsi_unregister(info->host);
259
260 link->state &= ~DEV_CONFIG;
261}
262
263/*====================================================================*/
264
265static int fdomain_event(event_t event, int priority,
266 event_callback_args_t *args)
267{
268 dev_link_t *link = args->client_data;
269
270 DEBUG(1, "fdomain_event(0x%06x)\n", event);
271
272 switch (event) {
273 case CS_EVENT_CARD_REMOVAL:
274 link->state &= ~DEV_PRESENT;
275 if (link->state & DEV_CONFIG)
276 fdomain_release(link);
277 break;
278 case CS_EVENT_CARD_INSERTION:
279 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
280 fdomain_config(link);
281 break;
282 case CS_EVENT_PM_SUSPEND:
283 link->state |= DEV_SUSPEND;
284 /* Fall through... */
285 case CS_EVENT_RESET_PHYSICAL:
286 if (link->state & DEV_CONFIG)
287 pcmcia_release_configuration(link->handle);
288 break;
289 case CS_EVENT_PM_RESUME:
290 link->state &= ~DEV_SUSPEND;
291 /* Fall through... */
292 case CS_EVENT_CARD_RESET:
293 if (link->state & DEV_CONFIG) {
294 pcmcia_request_configuration(link->handle, &link->conf);
295 fdomain_16x0_bus_reset(NULL);
296 }
297 break;
298 }
299 return 0;
300} /* fdomain_event */
301
302static struct pcmcia_driver fdomain_cs_driver = {
303 .owner = THIS_MODULE,
304 .drv = {
305 .name = "fdomain_cs",
306 },
307 .attach = fdomain_attach,
308 .detach = fdomain_detach,
309};
310
311static int __init init_fdomain_cs(void)
312{
313 return pcmcia_register_driver(&fdomain_cs_driver);
314}
315
316static void __exit exit_fdomain_cs(void)
317{
318 pcmcia_unregister_driver(&fdomain_cs_driver);
319 BUG_ON(dev_list != NULL);
320}
321
322module_init(init_fdomain_cs);
323module_exit(exit_fdomain_cs);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
new file mode 100644
index 000000000000..496c412c8854
--- /dev/null
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -0,0 +1,2198 @@
1/*======================================================================
2
3 NinjaSCSI-3 / NinjaSCSI-32Bi PCMCIA SCSI host adapter card driver
4 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
5
6 Ver.2.8 Support 32bit MMIO mode
7 Support Synchronous Data Transfer Request (SDTR) mode
8 Ver.2.0 Support 32bit PIO mode
9 Ver.1.1.2 Fix for scatter list buffer exceeds
10 Ver.1.1 Support scatter list
11 Ver.0.1 Initial version
12
13 This software may be used and distributed according to the terms of
14 the GNU General Public License.
15
16======================================================================*/
17
18/***********************************************************************
19 This driver is for these PCcards.
20
21 I-O DATA PCSC-F (Workbit NinjaSCSI-3)
22 "WBT", "NinjaSCSI-3", "R1.0"
23 I-O DATA CBSC-II (Workbit NinjaSCSI-32Bi in 16bit mode)
24 "IO DATA", "CBSC16 ", "1"
25
26***********************************************************************/
27
28/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */
29
30#include <linux/version.h>
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/init.h>
34#include <linux/sched.h>
35#include <linux/slab.h>
36#include <linux/string.h>
37#include <linux/timer.h>
38#include <linux/ioport.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <linux/major.h>
42#include <linux/blkdev.h>
43#include <linux/stat.h>
44
45#include <asm/io.h>
46#include <asm/irq.h>
47
48#include <../drivers/scsi/scsi.h>
49#include <scsi/scsi_host.h>
50
51#include <scsi/scsi.h>
52#include <scsi/scsi_ioctl.h>
53
54#include <pcmcia/version.h>
55#include <pcmcia/cs_types.h>
56#include <pcmcia/cs.h>
57#include <pcmcia/cistpl.h>
58#include <pcmcia/cisreg.h>
59#include <pcmcia/ds.h>
60
61#include "nsp_cs.h"
62
63MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
64MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $");
65MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
66#ifdef MODULE_LICENSE
67MODULE_LICENSE("GPL");
68#endif
69
70#include "nsp_io.h"
71
72/*====================================================================*/
73/* Parameters that can be set with 'insmod' */
74
75static int nsp_burst_mode = BURST_MEM32;
76module_param(nsp_burst_mode, int, 0);
77MODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))");
78
79/* Release IO ports after configuration? */
80static int free_ports = 0;
81module_param(free_ports, bool, 0);
82MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");
83
84/* /usr/src/linux/drivers/scsi/hosts.h */
85static Scsi_Host_Template nsp_driver_template = {
86 .proc_name = "nsp_cs",
87 .proc_info = nsp_proc_info,
88 .name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
89#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
90 .detect = nsp_detect_old,
91 .release = nsp_release_old,
92#endif
93 .info = nsp_info,
94 .queuecommand = nsp_queuecommand,
95/* .eh_strategy_handler = nsp_eh_strategy,*/
96/* .eh_abort_handler = nsp_eh_abort,*/
97/* .eh_device_reset_handler = nsp_eh_device_reset,*/
98 .eh_bus_reset_handler = nsp_eh_bus_reset,
99 .eh_host_reset_handler = nsp_eh_host_reset,
100 .can_queue = 1,
101 .this_id = NSP_INITIATOR_ID,
102 .sg_tablesize = SG_ALL,
103 .cmd_per_lun = 1,
104 .use_clustering = DISABLE_CLUSTERING,
105#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
106 .use_new_eh_code = 1,
107#endif
108};
109
110static dev_link_t *dev_list = NULL;
111static dev_info_t dev_info = {"nsp_cs"};
112
113static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
114
115
116
117/*
118 * debug, error print
119 */
120#ifndef NSP_DEBUG
121# define NSP_DEBUG_MASK 0x000000
122# define nsp_msg(type, args...) nsp_cs_message("", 0, (type), args)
123# define nsp_dbg(mask, args...) /* */
124#else
125# define NSP_DEBUG_MASK 0xffffff
126# define nsp_msg(type, args...) \
127 nsp_cs_message (__FUNCTION__, __LINE__, (type), args)
128# define nsp_dbg(mask, args...) \
129 nsp_cs_dmessage(__FUNCTION__, __LINE__, (mask), args)
130#endif
131
132#define NSP_DEBUG_QUEUECOMMAND BIT(0)
133#define NSP_DEBUG_REGISTER BIT(1)
134#define NSP_DEBUG_AUTOSCSI BIT(2)
135#define NSP_DEBUG_INTR BIT(3)
136#define NSP_DEBUG_SGLIST BIT(4)
137#define NSP_DEBUG_BUSFREE BIT(5)
138#define NSP_DEBUG_CDB_CONTENTS BIT(6)
139#define NSP_DEBUG_RESELECTION BIT(7)
140#define NSP_DEBUG_MSGINOCCUR BIT(8)
141#define NSP_DEBUG_EEPROM BIT(9)
142#define NSP_DEBUG_MSGOUTOCCUR BIT(10)
143#define NSP_DEBUG_BUSRESET BIT(11)
144#define NSP_DEBUG_RESTART BIT(12)
145#define NSP_DEBUG_SYNC BIT(13)
146#define NSP_DEBUG_WAIT BIT(14)
147#define NSP_DEBUG_TARGETFLAG BIT(15)
148#define NSP_DEBUG_PROC BIT(16)
149#define NSP_DEBUG_INIT BIT(17)
150#define NSP_DEBUG_DATA_IO BIT(18)
151#define NSP_SPECIAL_PRINT_REGISTER BIT(20)
152
153#define NSP_DEBUG_BUF_LEN 150
154
155static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...)
156{
157 va_list args;
158 char buf[NSP_DEBUG_BUF_LEN];
159
160 va_start(args, fmt);
161 vsnprintf(buf, sizeof(buf), fmt, args);
162 va_end(args);
163
164#ifndef NSP_DEBUG
165 printk("%snsp_cs: %s\n", type, buf);
166#else
167 printk("%snsp_cs: %s (%d): %s\n", type, func, line, buf);
168#endif
169}
170
171#ifdef NSP_DEBUG
172static void nsp_cs_dmessage(const char *func, int line, int mask, char *fmt, ...)
173{
174 va_list args;
175 char buf[NSP_DEBUG_BUF_LEN];
176
177 va_start(args, fmt);
178 vsnprintf(buf, sizeof(buf), fmt, args);
179 va_end(args);
180
181 if (mask & NSP_DEBUG_MASK) {
182 printk("nsp_cs-debug: 0x%x %s (%d): %s\n", mask, func, line, buf);
183 }
184}
185#endif
186
187/***********************************************************/
188
189/*====================================================
190 * Clenaup parameters and call done() functions.
191 * You must be set SCpnt->result before call this function.
192 */
193static void nsp_scsi_done(Scsi_Cmnd *SCpnt)
194{
195 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
196
197 data->CurrentSC = NULL;
198
199 SCpnt->scsi_done(SCpnt);
200}
201
202static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
203{
204#ifdef NSP_DEBUG
205 /*unsigned int host_id = SCpnt->device->host->this_id;*/
206 /*unsigned int base = SCpnt->device->host->io_port;*/
207 unsigned char target = SCpnt->device->id;
208#endif
209 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
210
211 nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "SCpnt=0x%p target=%d lun=%d buff=0x%p bufflen=%d use_sg=%d",
212 SCpnt, target, SCpnt->device->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg);
213 //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);
214
215 SCpnt->scsi_done = done;
216
217 if (data->CurrentSC != NULL) {
218 nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
219 SCpnt->result = DID_BAD_TARGET << 16;
220 nsp_scsi_done(SCpnt);
221 return 0;
222 }
223
224#if 0
225 /* XXX: pcmcia-cs generates SCSI command with "scsi_info" utility.
226 This makes kernel crash when suspending... */
227 if (data->ScsiInfo->stop != 0) {
228 nsp_msg(KERN_INFO, "suspending device. reject command.");
229 SCpnt->result = DID_BAD_TARGET << 16;
230 nsp_scsi_done(SCpnt);
231 return SCSI_MLQUEUE_HOST_BUSY;
232 }
233#endif
234
235 show_command(SCpnt);
236
237 data->CurrentSC = SCpnt;
238
239 SCpnt->SCp.Status = CHECK_CONDITION;
240 SCpnt->SCp.Message = 0;
241 SCpnt->SCp.have_data_in = IO_UNKNOWN;
242 SCpnt->SCp.sent_command = 0;
243 SCpnt->SCp.phase = PH_UNDETERMINED;
244 SCpnt->resid = SCpnt->request_bufflen;
245
246 /* setup scratch area
247 SCp.ptr : buffer pointer
248 SCp.this_residual : buffer length
249 SCp.buffer : next buffer
250 SCp.buffers_residual : left buffers in list
251 SCp.phase : current state of the command */
252 if (SCpnt->use_sg) {
253 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
254 SCpnt->SCp.ptr = BUFFER_ADDR;
255 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
256 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
257 } else {
258 SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
259 SCpnt->SCp.this_residual = SCpnt->request_bufflen;
260 SCpnt->SCp.buffer = NULL;
261 SCpnt->SCp.buffers_residual = 0;
262 }
263
264 if (nsphw_start_selection(SCpnt) == FALSE) {
265 nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
266 SCpnt->result = DID_BUS_BUSY << 16;
267 nsp_scsi_done(SCpnt);
268 return 0;
269 }
270
271
272 //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "out");
273#ifdef NSP_DEBUG
274 data->CmdId++;
275#endif
276 return 0;
277}
278
279/*
280 * setup PIO FIFO transfer mode and enable/disable to data out
281 */
282static void nsp_setup_fifo(nsp_hw_data *data, int enabled)
283{
284 unsigned int base = data->BaseAddress;
285 unsigned char transfer_mode_reg;
286
287 //nsp_dbg(NSP_DEBUG_DATA_IO, "enabled=%d", enabled);
288
289 if (enabled != FALSE) {
290 transfer_mode_reg = TRANSFER_GO | BRAIND;
291 } else {
292 transfer_mode_reg = 0;
293 }
294
295 transfer_mode_reg |= data->TransferMode;
296
297 nsp_index_write(base, TRANSFERMODE, transfer_mode_reg);
298}
299
300static void nsphw_init_sync(nsp_hw_data *data)
301{
302 sync_data tmp_sync = { .SyncNegotiation = SYNC_NOT_YET,
303 .SyncPeriod = 0,
304 .SyncOffset = 0
305 };
306 int i;
307
308 /* setup sync data */
309 for ( i = 0; i < ARRAY_SIZE(data->Sync); i++ ) {
310 data->Sync[i] = tmp_sync;
311 }
312}
313
314/*
315 * Initialize Ninja hardware
316 */
317static int nsphw_init(nsp_hw_data *data)
318{
319 unsigned int base = data->BaseAddress;
320
321 nsp_dbg(NSP_DEBUG_INIT, "in base=0x%x", base);
322
323 data->ScsiClockDiv = CLOCK_40M | FAST_20;
324 data->CurrentSC = NULL;
325 data->FifoCount = 0;
326 data->TransferMode = MODE_IO8;
327
328 nsphw_init_sync(data);
329
330 /* block all interrupts */
331 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);
332
333 /* setup SCSI interface */
334 nsp_write(base, IFSELECT, IF_IFSEL);
335
336 nsp_index_write(base, SCSIIRQMODE, 0);
337
338 nsp_index_write(base, TRANSFERMODE, MODE_IO8);
339 nsp_index_write(base, CLOCKDIV, data->ScsiClockDiv);
340
341 nsp_index_write(base, PARITYCTRL, 0);
342 nsp_index_write(base, POINTERCLR, POINTER_CLEAR |
343 ACK_COUNTER_CLEAR |
344 REQ_COUNTER_CLEAR |
345 HOST_COUNTER_CLEAR);
346
347 /* setup fifo asic */
348 nsp_write(base, IFSELECT, IF_REGSEL);
349 nsp_index_write(base, TERMPWRCTRL, 0);
350 if ((nsp_index_read(base, OTHERCONTROL) & TPWR_SENSE) == 0) {
351 nsp_msg(KERN_INFO, "terminator power on");
352 nsp_index_write(base, TERMPWRCTRL, POWER_ON);
353 }
354
355 nsp_index_write(base, TIMERCOUNT, 0);
356 nsp_index_write(base, TIMERCOUNT, 0); /* requires 2 times!! */
357
358 nsp_index_write(base, SYNCREG, 0);
359 nsp_index_write(base, ACKWIDTH, 0);
360
361 /* enable interrupts and ack them */
362 nsp_index_write(base, SCSIIRQMODE, SCSI_PHASE_CHANGE_EI |
363 RESELECT_EI |
364 SCSI_RESET_IRQ_EI );
365 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);
366
367 nsp_setup_fifo(data, FALSE);
368
369 return TRUE;
370}
371
372/*
373 * Start selection phase
374 */
375static int nsphw_start_selection(Scsi_Cmnd *SCpnt)
376{
377 unsigned int host_id = SCpnt->device->host->this_id;
378 unsigned int base = SCpnt->device->host->io_port;
379 unsigned char target = SCpnt->device->id;
380 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
381 int time_out;
382 unsigned char phase, arbit;
383
384 //nsp_dbg(NSP_DEBUG_RESELECTION, "in");
385
386 phase = nsp_index_read(base, SCSIBUSMON);
387 if(phase != BUSMON_BUS_FREE) {
388 //nsp_dbg(NSP_DEBUG_RESELECTION, "bus busy");
389 return FALSE;
390 }
391
392 /* start arbitration */
393 //nsp_dbg(NSP_DEBUG_RESELECTION, "start arbit");
394 SCpnt->SCp.phase = PH_ARBSTART;
395 nsp_index_write(base, SETARBIT, ARBIT_GO);
396
397 time_out = 1000;
398 do {
399 /* XXX: what a stupid chip! */
400 arbit = nsp_index_read(base, ARBITSTATUS);
401 //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit=%d, wait_count=%d", arbit, wait_count);
402 udelay(1); /* hold 1.2us */
403 } while((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 &&
404 (time_out-- != 0));
405
406 if (!(arbit & ARBIT_WIN)) {
407 //nsp_dbg(NSP_DEBUG_RESELECTION, "arbit fail");
408 nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR);
409 return FALSE;
410 }
411
412 /* assert select line */
413 //nsp_dbg(NSP_DEBUG_RESELECTION, "assert SEL line");
414 SCpnt->SCp.phase = PH_SELSTART;
415 udelay(3); /* wait 2.4us */
416 nsp_index_write(base, SCSIDATALATCH, BIT(host_id) | BIT(target));
417 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_ATN);
418 udelay(2); /* wait >1.2us */
419 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_BSY | SCSI_DATAOUT_ENB | SCSI_ATN);
420 nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR);
421 /*udelay(1);*/ /* wait >90ns */
422 nsp_index_write(base, SCSIBUSCTRL, SCSI_SEL | SCSI_DATAOUT_ENB | SCSI_ATN);
423
424 /* check selection timeout */
425 nsp_start_timer(SCpnt, 1000/51);
426 data->SelectionTimeOut = 1;
427
428 return TRUE;
429}
430
431struct nsp_sync_table {
432 unsigned int min_period;
433 unsigned int max_period;
434 unsigned int chip_period;
435 unsigned int ack_width;
436};
437
438static struct nsp_sync_table nsp_sync_table_40M[] = {
439 {0x0c, 0x0c, 0x1, 0}, /* 20MB 50ns*/
440 {0x19, 0x19, 0x3, 1}, /* 10MB 100ns*/
441 {0x1a, 0x25, 0x5, 2}, /* 7.5MB 150ns*/
442 {0x26, 0x32, 0x7, 3}, /* 5MB 200ns*/
443 { 0, 0, 0, 0},
444};
445
446static struct nsp_sync_table nsp_sync_table_20M[] = {
447 {0x19, 0x19, 0x1, 0}, /* 10MB 100ns*/
448 {0x1a, 0x25, 0x2, 0}, /* 7.5MB 150ns*/
449 {0x26, 0x32, 0x3, 1}, /* 5MB 200ns*/
450 { 0, 0, 0, 0},
451};
452
453/*
454 * setup synchronous data transfer mode
455 */
456static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt)
457{
458 unsigned char target = SCpnt->device->id;
459// unsigned char lun = SCpnt->device->lun;
460 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
461 sync_data *sync = &(data->Sync[target]);
462 struct nsp_sync_table *sync_table;
463 unsigned int period, offset;
464 int i;
465
466
467 nsp_dbg(NSP_DEBUG_SYNC, "in");
468
469 period = sync->SyncPeriod;
470 offset = sync->SyncOffset;
471
472 nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset);
473
474 if ((data->ScsiClockDiv & (BIT(0)|BIT(1))) == CLOCK_20M) {
475 sync_table = nsp_sync_table_20M;
476 } else {
477 sync_table = nsp_sync_table_40M;
478 }
479
480 for ( i = 0; sync_table->max_period != 0; i++, sync_table++) {
481 if ( period >= sync_table->min_period &&
482 period <= sync_table->max_period ) {
483 break;
484 }
485 }
486
487 if (period != 0 && sync_table->max_period == 0) {
488 /*
489 * No proper period/offset found
490 */
491 nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset");
492
493 sync->SyncPeriod = 0;
494 sync->SyncOffset = 0;
495 sync->SyncRegister = 0;
496 sync->AckWidth = 0;
497
498 return FALSE;
499 }
500
501 sync->SyncRegister = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) |
502 (offset & SYNCREG_OFFSET_MASK);
503 sync->AckWidth = sync_table->ack_width;
504
505 nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth);
506
507 return TRUE;
508}
509
510
511/*
512 * start ninja hardware timer
513 */
514static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time)
515{
516 unsigned int base = SCpnt->device->host->io_port;
517 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
518
519 //nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time);
520 data->TimerCount = time;
521 nsp_index_write(base, TIMERCOUNT, time);
522}
523
524/*
525 * wait for bus phase change
526 */
527static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
528{
529 unsigned int base = SCpnt->device->host->io_port;
530 unsigned char reg;
531 int time_out;
532
533 //nsp_dbg(NSP_DEBUG_INTR, "in");
534
535 time_out = 100;
536
537 do {
538 reg = nsp_index_read(base, SCSIBUSMON);
539 if (reg == 0xff) {
540 break;
541 }
542 } while ((time_out-- != 0) && (reg & mask) != 0);
543
544 if (time_out == 0) {
545 nsp_msg(KERN_DEBUG, " %s signal off timeut", str);
546 }
547
548 return 0;
549}
550
551/*
552 * expect Ninja Irq
553 */
554static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
555 unsigned char current_phase,
556 unsigned char mask)
557{
558 unsigned int base = SCpnt->device->host->io_port;
559 int time_out;
560 unsigned char phase, i_src;
561
562 //nsp_dbg(NSP_DEBUG_INTR, "current_phase=0x%x, mask=0x%x", current_phase, mask);
563
564 time_out = 100;
565 do {
566 phase = nsp_index_read(base, SCSIBUSMON);
567 if (phase == 0xff) {
568 //nsp_dbg(NSP_DEBUG_INTR, "ret -1");
569 return -1;
570 }
571 i_src = nsp_read(base, IRQSTATUS);
572 if (i_src & IRQSTATUS_SCSI) {
573 //nsp_dbg(NSP_DEBUG_INTR, "ret 0 found scsi signal");
574 return 0;
575 }
576 if ((phase & mask) != 0 && (phase & BUSMON_PHASE_MASK) == current_phase) {
577 //nsp_dbg(NSP_DEBUG_INTR, "ret 1 phase=0x%x", phase);
578 return 1;
579 }
580 } while(time_out-- != 0);
581
582 //nsp_dbg(NSP_DEBUG_INTR, "timeout");
583 return -1;
584}
585
586/*
587 * transfer SCSI message
588 */
589static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase)
590{
591 unsigned int base = SCpnt->device->host->io_port;
592 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
593 char *buf = data->MsgBuffer;
594 int len = min(MSGBUF_SIZE, data->MsgLen);
595 int ptr;
596 int ret;
597
598 //nsp_dbg(NSP_DEBUG_DATA_IO, "in");
599 for (ptr = 0; len > 0; len--, ptr++) {
600
601 ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);
602 if (ret <= 0) {
603 nsp_dbg(NSP_DEBUG_DATA_IO, "xfer quit");
604 return 0;
605 }
606
607 /* if last byte, negate ATN */
608 if (len == 1 && SCpnt->SCp.phase == PH_MSG_OUT) {
609 nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | ACKENB);
610 }
611
612 /* read & write message */
613 if (phase & BUSMON_IO) {
614 nsp_dbg(NSP_DEBUG_DATA_IO, "read msg");
615 buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK);
616 } else {
617 nsp_dbg(NSP_DEBUG_DATA_IO, "write msg");
618 nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]);
619 }
620 nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>");
621
622 }
623 return len;
624}
625
626/*
627 * get extra SCSI data from fifo
628 */
629static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt)
630{
631 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
632 unsigned int count;
633
634 //nsp_dbg(NSP_DEBUG_DATA_IO, "in");
635
636 if (SCpnt->SCp.have_data_in != IO_IN) {
637 return 0;
638 }
639
640 count = nsp_fifo_count(SCpnt);
641 if (data->FifoCount == count) {
642 //nsp_dbg(NSP_DEBUG_DATA_IO, "not use bypass quirk");
643 return 0;
644 }
645
646 /*
647 * XXX: NSP_QUIRK
648 * data phase skip only occures in case of SCSI_LOW_READ
649 */
650 nsp_dbg(NSP_DEBUG_DATA_IO, "use bypass quirk");
651 SCpnt->SCp.phase = PH_DATA;
652 nsp_pio_read(SCpnt);
653 nsp_setup_fifo(data, FALSE);
654
655 return 0;
656}
657
658/*
659 * accept reselection
660 */
661static int nsp_reselected(Scsi_Cmnd *SCpnt)
662{
663 unsigned int base = SCpnt->device->host->io_port;
664 unsigned int host_id = SCpnt->device->host->this_id;
665 //nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
666 unsigned char bus_reg;
667 unsigned char id_reg, tmp;
668 int target;
669
670 nsp_dbg(NSP_DEBUG_RESELECTION, "in");
671
672 id_reg = nsp_index_read(base, RESELECTID);
673 tmp = id_reg & (~BIT(host_id));
674 target = 0;
675 while(tmp != 0) {
676 if (tmp & BIT(0)) {
677 break;
678 }
679 tmp >>= 1;
680 target++;
681 }
682
683 if (SCpnt->device->id != target) {
684 nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target);
685 }
686
687 nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");
688
689 nsp_nexus(SCpnt);
690 bus_reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN);
691 nsp_index_write(base, SCSIBUSCTRL, bus_reg);
692 nsp_index_write(base, SCSIBUSCTRL, bus_reg | AUTODIRECTION | ACKENB);
693
694 return TRUE;
695}
696
697/*
698 * count how many data transferd
699 */
700static int nsp_fifo_count(Scsi_Cmnd *SCpnt)
701{
702 unsigned int base = SCpnt->device->host->io_port;
703 unsigned int count;
704 unsigned int l, m, h, dummy;
705
706 nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER);
707
708 l = nsp_index_read(base, TRANSFERCOUNT);
709 m = nsp_index_read(base, TRANSFERCOUNT);
710 h = nsp_index_read(base, TRANSFERCOUNT);
711 dummy = nsp_index_read(base, TRANSFERCOUNT); /* required this! */
712
713 count = (h << 16) | (m << 8) | (l << 0);
714
715 //nsp_dbg(NSP_DEBUG_DATA_IO, "count=0x%x", count);
716
717 return count;
718}
719
720/* fifo size */
721#define RFIFO_CRIT 64
722#define WFIFO_CRIT 64
723
724/*
725 * read data in DATA IN phase
726 */
727static void nsp_pio_read(Scsi_Cmnd *SCpnt)
728{
729 unsigned int base = SCpnt->device->host->io_port;
730 unsigned long mmio_base = SCpnt->device->host->base;
731 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
732 long time_out;
733 int ocount, res;
734 unsigned char stat, fifo_stat;
735
736 ocount = data->FifoCount;
737
738 nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d",
739 SCpnt, SCpnt->resid, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);
740
741 time_out = 1000;
742
743 while ((time_out-- != 0) &&
744 (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0 ) ) {
745
746 stat = nsp_index_read(base, SCSIBUSMON);
747 stat &= BUSMON_PHASE_MASK;
748
749
750 res = nsp_fifo_count(SCpnt) - ocount;
751 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res);
752 if (res == 0) { /* if some data avilable ? */
753 if (stat == BUSPHASE_DATA_IN) { /* phase changed? */
754 //nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", SCpnt->SCp.this_residual);
755 continue;
756 } else {
757 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x", stat);
758 break;
759 }
760 }
761
762 fifo_stat = nsp_read(base, FIFOSTATUS);
763 if ((fifo_stat & FIFOSTATUS_FULL_EMPTY) == 0 &&
764 stat == BUSPHASE_DATA_IN) {
765 continue;
766 }
767
768 res = min(res, SCpnt->SCp.this_residual);
769
770 switch (data->TransferMode) {
771 case MODE_IO32:
772 res &= ~(BIT(1)|BIT(0)); /* align 4 */
773 nsp_fifo32_read(base, SCpnt->SCp.ptr, res >> 2);
774 break;
775 case MODE_IO8:
776 nsp_fifo8_read (base, SCpnt->SCp.ptr, res );
777 break;
778
779 case MODE_MEM32:
780 res &= ~(BIT(1)|BIT(0)); /* align 4 */
781 nsp_mmio_fifo32_read(mmio_base, SCpnt->SCp.ptr, res >> 2);
782 break;
783
784 default:
785 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown read mode");
786 return;
787 }
788
789 SCpnt->resid -= res;
790 SCpnt->SCp.ptr += res;
791 SCpnt->SCp.this_residual -= res;
792 ocount += res;
793 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this_residual=0x%x ocount=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount);
794
795 /* go to next scatter list if available */
796 if (SCpnt->SCp.this_residual == 0 &&
797 SCpnt->SCp.buffers_residual != 0 ) {
798 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next timeout=%d", time_out);
799 SCpnt->SCp.buffers_residual--;
800 SCpnt->SCp.buffer++;
801 SCpnt->SCp.ptr = BUFFER_ADDR;
802 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
803 time_out = 1000;
804
805 //nsp_dbg(NSP_DEBUG_DATA_IO, "page: 0x%p, off: 0x%x", SCpnt->SCp.buffer->page, SCpnt->SCp.buffer->offset);
806 }
807 }
808
809 data->FifoCount = ocount;
810
811 if (time_out == 0) {
812 nsp_msg(KERN_DEBUG, "pio read timeout resid=%d this_residual=%d buffers_residual=%d",
813 SCpnt->resid, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);
814 }
815 nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount);
816 nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
817}
818
819/*
820 * write data in DATA OUT phase
821 */
822static void nsp_pio_write(Scsi_Cmnd *SCpnt)
823{
824 unsigned int base = SCpnt->device->host->io_port;
825 unsigned long mmio_base = SCpnt->device->host->base;
826 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
827 int time_out;
828 int ocount, res;
829 unsigned char stat;
830
831 ocount = data->FifoCount;
832
833 nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x",
834 data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, SCpnt->resid);
835
836 time_out = 1000;
837
838 while ((time_out-- != 0) &&
839 (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0)) {
840 stat = nsp_index_read(base, SCSIBUSMON);
841 stat &= BUSMON_PHASE_MASK;
842
843 if (stat != BUSPHASE_DATA_OUT) {
844 res = ocount - nsp_fifo_count(SCpnt);
845
846 nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res);
847 /* Put back pointer */
848 SCpnt->resid += res;
849 SCpnt->SCp.ptr -= res;
850 SCpnt->SCp.this_residual += res;
851 ocount -= res;
852
853 break;
854 }
855
856 res = ocount - nsp_fifo_count(SCpnt);
857 if (res > 0) { /* write all data? */
858 nsp_dbg(NSP_DEBUG_DATA_IO, "wait for all data out. ocount=0x%x res=%d", ocount, res);
859 continue;
860 }
861
862 res = min(SCpnt->SCp.this_residual, WFIFO_CRIT);
863
864 //nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, res);
865 switch (data->TransferMode) {
866 case MODE_IO32:
867 res &= ~(BIT(1)|BIT(0)); /* align 4 */
868 nsp_fifo32_write(base, SCpnt->SCp.ptr, res >> 2);
869 break;
870 case MODE_IO8:
871 nsp_fifo8_write (base, SCpnt->SCp.ptr, res );
872 break;
873
874 case MODE_MEM32:
875 res &= ~(BIT(1)|BIT(0)); /* align 4 */
876 nsp_mmio_fifo32_write(mmio_base, SCpnt->SCp.ptr, res >> 2);
877 break;
878
879 default:
880 nsp_dbg(NSP_DEBUG_DATA_IO, "unknown write mode");
881 break;
882 }
883
884 SCpnt->resid -= res;
885 SCpnt->SCp.ptr += res;
886 SCpnt->SCp.this_residual -= res;
887 ocount += res;
888
889 /* go to next scatter list if available */
890 if (SCpnt->SCp.this_residual == 0 &&
891 SCpnt->SCp.buffers_residual != 0 ) {
892 //nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next");
893 SCpnt->SCp.buffers_residual--;
894 SCpnt->SCp.buffer++;
895 SCpnt->SCp.ptr = BUFFER_ADDR;
896 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
897 time_out = 1000;
898 }
899 }
900
901 data->FifoCount = ocount;
902
903 if (time_out == 0) {
904 nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x", SCpnt->resid);
905 }
906 nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount);
907 nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
908}
909#undef RFIFO_CRIT
910#undef WFIFO_CRIT
911
912/*
913 * setup synchronous/asynchronous data transfer mode
914 */
915static int nsp_nexus(Scsi_Cmnd *SCpnt)
916{
917 unsigned int base = SCpnt->device->host->io_port;
918 unsigned char target = SCpnt->device->id;
919// unsigned char lun = SCpnt->device->lun;
920 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
921 sync_data *sync = &(data->Sync[target]);
922
923 //nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p", SCpnt);
924
925 /* setup synch transfer registers */
926 nsp_index_write(base, SYNCREG, sync->SyncRegister);
927 nsp_index_write(base, ACKWIDTH, sync->AckWidth);
928
929 if (SCpnt->use_sg == 0 ||
930 SCpnt->resid % 4 != 0 ||
931 SCpnt->resid <= PAGE_SIZE ) {
932 data->TransferMode = MODE_IO8;
933 } else if (nsp_burst_mode == BURST_MEM32) {
934 data->TransferMode = MODE_MEM32;
935 } else if (nsp_burst_mode == BURST_IO32) {
936 data->TransferMode = MODE_IO32;
937 } else {
938 data->TransferMode = MODE_IO8;
939 }
940
941 /* setup pdma fifo */
942 nsp_setup_fifo(data, TRUE);
943
944 /* clear ack counter */
945 data->FifoCount = 0;
946 nsp_index_write(base, POINTERCLR, POINTER_CLEAR |
947 ACK_COUNTER_CLEAR |
948 REQ_COUNTER_CLEAR |
949 HOST_COUNTER_CLEAR);
950
951 return 0;
952}
953
954#include "nsp_message.c"
955/*
956 * interrupt handler
957 */
958static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs)
959{
960 unsigned int base;
961 unsigned char irq_status, irq_phase, phase;
962 Scsi_Cmnd *tmpSC;
963 unsigned char target, lun;
964 unsigned int *sync_neg;
965 int i, tmp;
966 nsp_hw_data *data;
967
968
969 //nsp_dbg(NSP_DEBUG_INTR, "dev_id=0x%p", dev_id);
970 //nsp_dbg(NSP_DEBUG_INTR, "host=0x%p", ((scsi_info_t *)dev_id)->host);
971
972 if ( dev_id != NULL &&
973 ((scsi_info_t *)dev_id)->host != NULL ) {
974 scsi_info_t *info = (scsi_info_t *)dev_id;
975
976 data = (nsp_hw_data *)info->host->hostdata;
977 } else {
978 nsp_dbg(NSP_DEBUG_INTR, "host data wrong");
979 return IRQ_NONE;
980 }
981
982 //nsp_dbg(NSP_DEBUG_INTR, "&nsp_data_base=0x%p, dev_id=0x%p", &nsp_data_base, dev_id);
983
984 base = data->BaseAddress;
985 //nsp_dbg(NSP_DEBUG_INTR, "base=0x%x", base);
986
987 /*
988 * interrupt check
989 */
990 nsp_write(base, IRQCONTROL, IRQCONTROL_IRQDISABLE);
991 irq_status = nsp_read(base, IRQSTATUS);
992 //nsp_dbg(NSP_DEBUG_INTR, "irq_status=0x%x", irq_status);
993 if ((irq_status == 0xff) || ((irq_status & IRQSTATUS_MASK) == 0)) {
994 nsp_write(base, IRQCONTROL, 0);
995 //nsp_dbg(NSP_DEBUG_INTR, "no irq/shared irq");
996 return IRQ_NONE;
997 }
998
999 /* XXX: IMPORTANT
1000 * Do not read an irq_phase register if no scsi phase interrupt.
1001 * Unless, you should lose a scsi phase interrupt.
1002 */
1003 phase = nsp_index_read(base, SCSIBUSMON);
1004 if((irq_status & IRQSTATUS_SCSI) != 0) {
1005 irq_phase = nsp_index_read(base, IRQPHASESENCE);
1006 } else {
1007 irq_phase = 0;
1008 }
1009
1010 //nsp_dbg(NSP_DEBUG_INTR, "irq_phase=0x%x", irq_phase);
1011
1012 /*
1013 * timer interrupt handler (scsi vs timer interrupts)
1014 */
1015 //nsp_dbg(NSP_DEBUG_INTR, "timercount=%d", data->TimerCount);
1016 if (data->TimerCount != 0) {
1017 //nsp_dbg(NSP_DEBUG_INTR, "stop timer");
1018 nsp_index_write(base, TIMERCOUNT, 0);
1019 nsp_index_write(base, TIMERCOUNT, 0);
1020 data->TimerCount = 0;
1021 }
1022
1023 if ((irq_status & IRQSTATUS_MASK) == IRQSTATUS_TIMER &&
1024 data->SelectionTimeOut == 0) {
1025 //nsp_dbg(NSP_DEBUG_INTR, "timer start");
1026 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR);
1027 return IRQ_HANDLED;
1028 }
1029
1030 nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);
1031
1032 if ((irq_status & IRQSTATUS_SCSI) &&
1033 (irq_phase & SCSI_RESET_IRQ)) {
1034 nsp_msg(KERN_ERR, "bus reset (power off?)");
1035
1036 nsphw_init(data);
1037 nsp_bus_reset(data);
1038
1039 if(data->CurrentSC != NULL) {
1040 tmpSC = data->CurrentSC;
1041 tmpSC->result = (DID_RESET << 16) |
1042 ((tmpSC->SCp.Message & 0xff) << 8) |
1043 ((tmpSC->SCp.Status & 0xff) << 0);
1044 nsp_scsi_done(tmpSC);
1045 }
1046 return IRQ_HANDLED;
1047 }
1048
1049 if (data->CurrentSC == NULL) {
1050 nsp_msg(KERN_ERR, "CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x this can't be happen. reset everything", irq_status, phase, irq_phase);
1051 nsphw_init(data);
1052 nsp_bus_reset(data);
1053 return IRQ_HANDLED;
1054 }
1055
1056 tmpSC = data->CurrentSC;
1057 target = tmpSC->device->id;
1058 lun = tmpSC->device->lun;
1059 sync_neg = &(data->Sync[target].SyncNegotiation);
1060
1061 /*
1062 * parse hardware SCSI irq reasons register
1063 */
1064 if (irq_status & IRQSTATUS_SCSI) {
1065 if (irq_phase & RESELECT_IRQ) {
1066 nsp_dbg(NSP_DEBUG_INTR, "reselect");
1067 nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR);
1068 if (nsp_reselected(tmpSC) != FALSE) {
1069 return IRQ_HANDLED;
1070 }
1071 }
1072
1073 if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) {
1074 return IRQ_HANDLED;
1075 }
1076 }
1077
1078 //show_phase(tmpSC);
1079
1080 switch(tmpSC->SCp.phase) {
1081 case PH_SELSTART:
1082 // *sync_neg = SYNC_NOT_YET;
1083 if ((phase & BUSMON_BSY) == 0) {
1084 //nsp_dbg(NSP_DEBUG_INTR, "selection count=%d", data->SelectionTimeOut);
1085 if (data->SelectionTimeOut >= NSP_SELTIMEOUT) {
1086 nsp_dbg(NSP_DEBUG_INTR, "selection time out");
1087 data->SelectionTimeOut = 0;
1088 nsp_index_write(base, SCSIBUSCTRL, 0);
1089
1090 tmpSC->result = DID_TIME_OUT << 16;
1091 nsp_scsi_done(tmpSC);
1092
1093 return IRQ_HANDLED;
1094 }
1095 data->SelectionTimeOut += 1;
1096 nsp_start_timer(tmpSC, 1000/51);
1097 return IRQ_HANDLED;
1098 }
1099
1100 /* attention assert */
1101 //nsp_dbg(NSP_DEBUG_INTR, "attention assert");
1102 data->SelectionTimeOut = 0;
1103 tmpSC->SCp.phase = PH_SELECTED;
1104 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN);
1105 udelay(1);
1106 nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB);
1107 return IRQ_HANDLED;
1108
1109 break;
1110
1111 case PH_RESELECT:
1112 //nsp_dbg(NSP_DEBUG_INTR, "phase reselect");
1113 // *sync_neg = SYNC_NOT_YET;
1114 if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) {
1115
1116 tmpSC->result = DID_ABORT << 16;
1117 nsp_scsi_done(tmpSC);
1118 return IRQ_HANDLED;
1119 }
1120 /* fall thru */
1121 default:
1122 if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {
1123 return IRQ_HANDLED;
1124 }
1125 break;
1126 }
1127
1128 /*
1129 * SCSI sequencer
1130 */
1131 //nsp_dbg(NSP_DEBUG_INTR, "start scsi seq");
1132
1133 /* normal disconnect */
1134 if (((tmpSC->SCp.phase == PH_MSG_IN) || (tmpSC->SCp.phase == PH_MSG_OUT)) &&
1135 (irq_phase & LATCHED_BUS_FREE) != 0 ) {
1136 nsp_dbg(NSP_DEBUG_INTR, "normal disconnect irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);
1137
1138 //*sync_neg = SYNC_NOT_YET;
1139
1140 if ((tmpSC->SCp.Message == MSG_COMMAND_COMPLETE)) { /* all command complete and return status */
1141 tmpSC->result = (DID_OK << 16) |
1142 ((tmpSC->SCp.Message & 0xff) << 8) |
1143 ((tmpSC->SCp.Status & 0xff) << 0);
1144 nsp_dbg(NSP_DEBUG_INTR, "command complete result=0x%x", tmpSC->result);
1145 nsp_scsi_done(tmpSC);
1146
1147 return IRQ_HANDLED;
1148 }
1149
1150 return IRQ_HANDLED;
1151 }
1152
1153
1154 /* check unexpected bus free state */
1155 if (phase == 0) {
1156 nsp_msg(KERN_DEBUG, "unexpected bus free. irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);
1157
1158 *sync_neg = SYNC_NG;
1159 tmpSC->result = DID_ERROR << 16;
1160 nsp_scsi_done(tmpSC);
1161 return IRQ_HANDLED;
1162 }
1163
1164 switch (phase & BUSMON_PHASE_MASK) {
1165 case BUSPHASE_COMMAND:
1166 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_COMMAND");
1167 if ((phase & BUSMON_REQ) == 0) {
1168 nsp_dbg(NSP_DEBUG_INTR, "REQ == 0");
1169 return IRQ_HANDLED;
1170 }
1171
1172 tmpSC->SCp.phase = PH_COMMAND;
1173
1174 nsp_nexus(tmpSC);
1175
1176 /* write scsi command */
1177 nsp_dbg(NSP_DEBUG_INTR, "cmd_len=%d", tmpSC->cmd_len);
1178 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER);
1179 for (i = 0; i < tmpSC->cmd_len; i++) {
1180 nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[i]);
1181 }
1182 nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO);
1183 break;
1184
1185 case BUSPHASE_DATA_OUT:
1186 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_OUT");
1187
1188 tmpSC->SCp.phase = PH_DATA;
1189 tmpSC->SCp.have_data_in = IO_OUT;
1190
1191 nsp_pio_write(tmpSC);
1192
1193 break;
1194
1195 case BUSPHASE_DATA_IN:
1196 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_IN");
1197
1198 tmpSC->SCp.phase = PH_DATA;
1199 tmpSC->SCp.have_data_in = IO_IN;
1200
1201 nsp_pio_read(tmpSC);
1202
1203 break;
1204
1205 case BUSPHASE_STATUS:
1206 nsp_dataphase_bypass(tmpSC);
1207 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_STATUS");
1208
1209 tmpSC->SCp.phase = PH_STATUS;
1210
1211 tmpSC->SCp.Status = nsp_index_read(base, SCSIDATAWITHACK);
1212 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x status=0x%x", tmpSC->SCp.Message, tmpSC->SCp.Status);
1213
1214 break;
1215
1216 case BUSPHASE_MESSAGE_OUT:
1217 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_OUT");
1218 if ((phase & BUSMON_REQ) == 0) {
1219 goto timer_out;
1220 }
1221
1222 tmpSC->SCp.phase = PH_MSG_OUT;
1223
1224 //*sync_neg = SYNC_NOT_YET;
1225
1226 data->MsgLen = i = 0;
1227 data->MsgBuffer[i] = IDENTIFY(TRUE, lun); i++;
1228
1229 if (*sync_neg == SYNC_NOT_YET) {
1230 data->Sync[target].SyncPeriod = 0;
1231 data->Sync[target].SyncOffset = 0;
1232
1233 /**/
1234 data->MsgBuffer[i] = MSG_EXTENDED; i++;
1235 data->MsgBuffer[i] = 3; i++;
1236 data->MsgBuffer[i] = MSG_EXT_SDTR; i++;
1237 data->MsgBuffer[i] = 0x0c; i++;
1238 data->MsgBuffer[i] = 15; i++;
1239 /**/
1240 }
1241 data->MsgLen = i;
1242
1243 nsp_analyze_sdtr(tmpSC);
1244 show_message(data);
1245 nsp_message_out(tmpSC);
1246 break;
1247
1248 case BUSPHASE_MESSAGE_IN:
1249 nsp_dataphase_bypass(tmpSC);
1250 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_IN");
1251 if ((phase & BUSMON_REQ) == 0) {
1252 goto timer_out;
1253 }
1254
1255 tmpSC->SCp.phase = PH_MSG_IN;
1256 nsp_message_in(tmpSC);
1257
1258 /**/
1259 if (*sync_neg == SYNC_NOT_YET) {
1260 //nsp_dbg(NSP_DEBUG_INTR, "sync target=%d,lun=%d",target,lun);
1261
1262 if (data->MsgLen >= 5 &&
1263 data->MsgBuffer[0] == MSG_EXTENDED &&
1264 data->MsgBuffer[1] == 3 &&
1265 data->MsgBuffer[2] == MSG_EXT_SDTR ) {
1266 data->Sync[target].SyncPeriod = data->MsgBuffer[3];
1267 data->Sync[target].SyncOffset = data->MsgBuffer[4];
1268 //nsp_dbg(NSP_DEBUG_INTR, "sync ok, %d %d", data->MsgBuffer[3], data->MsgBuffer[4]);
1269 *sync_neg = SYNC_OK;
1270 } else {
1271 data->Sync[target].SyncPeriod = 0;
1272 data->Sync[target].SyncOffset = 0;
1273 *sync_neg = SYNC_NG;
1274 }
1275 nsp_analyze_sdtr(tmpSC);
1276 }
1277 /**/
1278
1279 /* search last messeage byte */
1280 tmp = -1;
1281 for (i = 0; i < data->MsgLen; i++) {
1282 tmp = data->MsgBuffer[i];
1283 if (data->MsgBuffer[i] == MSG_EXTENDED) {
1284 i += (1 + data->MsgBuffer[i+1]);
1285 }
1286 }
1287 tmpSC->SCp.Message = tmp;
1288
1289 nsp_dbg(NSP_DEBUG_INTR, "message=0x%x len=%d", tmpSC->SCp.Message, data->MsgLen);
1290 show_message(data);
1291
1292 break;
1293
1294 case BUSPHASE_SELECT:
1295 default:
1296 nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE other");
1297
1298 break;
1299 }
1300
1301 //nsp_dbg(NSP_DEBUG_INTR, "out");
1302 return IRQ_HANDLED;
1303
1304timer_out:
1305 nsp_start_timer(tmpSC, 1000/102);
1306 return IRQ_HANDLED;
1307}
1308
1309#ifdef NSP_DEBUG
1310#include "nsp_debug.c"
1311#endif /* NSP_DEBUG */
1312
1313/*----------------------------------------------------------------*/
1314/* look for ninja3 card and init if found */
1315/*----------------------------------------------------------------*/
1316static struct Scsi_Host *nsp_detect(Scsi_Host_Template *sht)
1317{
1318 struct Scsi_Host *host; /* registered host structure */
1319 nsp_hw_data *data_b = &nsp_data_base, *data;
1320
1321 nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);
1322#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1323 host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));
1324#else
1325 host = scsi_register(sht, sizeof(nsp_hw_data));
1326#endif
1327 if (host == NULL) {
1328 nsp_dbg(NSP_DEBUG_INIT, "host failed");
1329 return NULL;
1330 }
1331
1332 memcpy(host->hostdata, data_b, sizeof(nsp_hw_data));
1333 data = (nsp_hw_data *)host->hostdata;
1334 data->ScsiInfo->host = host;
1335#ifdef NSP_DEBUG
1336 data->CmdId = 0;
1337#endif
1338
1339 nsp_dbg(NSP_DEBUG_INIT, "irq=%d,%d", data_b->IrqNumber, ((nsp_hw_data *)host->hostdata)->IrqNumber);
1340
1341 host->unique_id = data->BaseAddress;
1342 host->io_port = data->BaseAddress;
1343 host->n_io_port = data->NumAddress;
1344 host->irq = data->IrqNumber;
1345 host->base = data->MmioAddress;
1346
1347 spin_lock_init(&(data->Lock));
1348
1349 snprintf(data->nspinfo,
1350 sizeof(data->nspinfo),
1351 "NinjaSCSI-3/32Bi Driver $Revision: 1.23 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d",
1352 host->io_port, host->io_port + host->n_io_port - 1,
1353 host->base,
1354 host->irq);
1355 sht->name = data->nspinfo;
1356
1357 nsp_dbg(NSP_DEBUG_INIT, "end");
1358
1359
1360 return host; /* detect done. */
1361}
1362
1363#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
1364static int nsp_detect_old(Scsi_Host_Template *sht)
1365{
1366 if (nsp_detect(sht) == NULL) {
1367 return 0;
1368 } else {
1369 //MOD_INC_USE_COUNT;
1370 return 1;
1371 }
1372}
1373
1374
1375static int nsp_release_old(struct Scsi_Host *shpnt)
1376{
1377 //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
1378
1379 /* PCMCIA Card Service dose same things below. */
1380 /* So we do nothing. */
1381 //if (shpnt->irq) {
1382 // free_irq(shpnt->irq, data->ScsiInfo);
1383 //}
1384 //if (shpnt->io_port) {
1385 // release_region(shpnt->io_port, shpnt->n_io_port);
1386 //}
1387
1388 //MOD_DEC_USE_COUNT;
1389
1390 return 0;
1391}
1392#endif
1393
1394/*----------------------------------------------------------------*/
1395/* return info string */
1396/*----------------------------------------------------------------*/
1397static const char *nsp_info(struct Scsi_Host *shpnt)
1398{
1399 nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
1400
1401 return data->nspinfo;
1402}
1403
1404#undef SPRINTF
1405#define SPRINTF(args...) \
1406 do { \
1407 if(length > (pos - buffer)) { \
1408 pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
1409 nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\
1410 } \
1411 } while(0)
1412static int
1413nsp_proc_info(
1414#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1415 struct Scsi_Host *host,
1416#endif
1417 char *buffer,
1418 char **start,
1419 off_t offset,
1420 int length,
1421#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1422 int hostno,
1423#endif
1424 int inout)
1425{
1426 int id;
1427 char *pos = buffer;
1428 int thislength;
1429 int speed;
1430 unsigned long flags;
1431 nsp_hw_data *data;
1432#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1433 struct Scsi_Host *host;
1434#else
1435 int hostno;
1436#endif
1437 if (inout) {
1438 return -EINVAL;
1439 }
1440
1441#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
1442 hostno = host->host_no;
1443#else
1444 /* search this HBA host */
1445 host = scsi_host_hn_get(hostno);
1446 if (host == NULL) {
1447 return -ESRCH;
1448 }
1449#endif
1450 data = (nsp_hw_data *)host->hostdata;
1451
1452
1453 SPRINTF("NinjaSCSI status\n\n");
1454 SPRINTF("Driver version: $Revision: 1.23 $\n");
1455 SPRINTF("SCSI host No.: %d\n", hostno);
1456 SPRINTF("IRQ: %d\n", host->irq);
1457 SPRINTF("IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);
1458 SPRINTF("MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1);
1459 SPRINTF("sg_tablesize: %d\n", host->sg_tablesize);
1460
1461 SPRINTF("burst transfer mode: ");
1462 switch (nsp_burst_mode) {
1463 case BURST_IO8:
1464 SPRINTF("io8");
1465 break;
1466 case BURST_IO32:
1467 SPRINTF("io32");
1468 break;
1469 case BURST_MEM32:
1470 SPRINTF("mem32");
1471 break;
1472 default:
1473 SPRINTF("???");
1474 break;
1475 }
1476 SPRINTF("\n");
1477
1478
1479 spin_lock_irqsave(&(data->Lock), flags);
1480 SPRINTF("CurrentSC: 0x%p\n\n", data->CurrentSC);
1481 spin_unlock_irqrestore(&(data->Lock), flags);
1482
1483 SPRINTF("SDTR status\n");
1484 for(id = 0; id < ARRAY_SIZE(data->Sync); id++) {
1485
1486 SPRINTF("id %d: ", id);
1487
1488 if (id == host->this_id) {
1489 SPRINTF("----- NinjaSCSI-3 host adapter\n");
1490 continue;
1491 }
1492
1493 switch(data->Sync[id].SyncNegotiation) {
1494 case SYNC_OK:
1495 SPRINTF(" sync");
1496 break;
1497 case SYNC_NG:
1498 SPRINTF("async");
1499 break;
1500 case SYNC_NOT_YET:
1501 SPRINTF(" none");
1502 break;
1503 default:
1504 SPRINTF("?????");
1505 break;
1506 }
1507
1508 if (data->Sync[id].SyncPeriod != 0) {
1509 speed = 1000000 / (data->Sync[id].SyncPeriod * 4);
1510
1511 SPRINTF(" transfer %d.%dMB/s, offset %d",
1512 speed / 1000,
1513 speed % 1000,
1514 data->Sync[id].SyncOffset
1515 );
1516 }
1517 SPRINTF("\n");
1518 }
1519
1520 thislength = pos - (buffer + offset);
1521
1522 if(thislength < 0) {
1523 *start = NULL;
1524 return 0;
1525 }
1526
1527
1528 thislength = min(thislength, length);
1529 *start = buffer + offset;
1530
1531 return thislength;
1532}
1533#undef SPRINTF
1534
1535/*---------------------------------------------------------------*/
1536/* error handler */
1537/*---------------------------------------------------------------*/
1538
1539/*static int nsp_eh_strategy(struct Scsi_Host *Shost)
1540{
1541 return FAILED;
1542}*/
1543
1544/*
1545static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
1546{
1547 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);
1548
1549 return nsp_eh_bus_reset(SCpnt);
1550}*/
1551
1552/*
1553static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt)
1554{
1555 nsp_dbg(NSP_DEBUG_BUSRESET, "%s: SCpnt=0x%p", SCpnt);
1556
1557 return FAILED;
1558}*/
1559
1560static int nsp_bus_reset(nsp_hw_data *data)
1561{
1562 unsigned int base = data->BaseAddress;
1563 int i;
1564
1565 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);
1566
1567 nsp_index_write(base, SCSIBUSCTRL, SCSI_RST);
1568 mdelay(100); /* 100ms */
1569 nsp_index_write(base, SCSIBUSCTRL, 0);
1570 for(i = 0; i < 5; i++) {
1571 nsp_index_read(base, IRQPHASESENCE); /* dummy read */
1572 }
1573
1574 nsphw_init_sync(data);
1575
1576 nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);
1577
1578 return SUCCESS;
1579}
1580
1581static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt)
1582{
1583 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
1584
1585 nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);
1586
1587 return nsp_bus_reset(data);
1588}
1589
1590static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
1591{
1592 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
1593
1594 nsp_dbg(NSP_DEBUG_BUSRESET, "in");
1595
1596 nsphw_init(data);
1597
1598 return SUCCESS;
1599}
1600
1601
1602/**********************************************************************
1603 PCMCIA functions
1604**********************************************************************/
1605
1606/*======================================================================
1607 nsp_cs_attach() creates an "instance" of the driver, allocating
1608 local data structures for one device. The device is registered
1609 with Card Services.
1610
1611 The dev_link structure is initialized, but we don't actually
1612 configure the card at this point -- we wait until we receive a
1613 card insertion event.
1614======================================================================*/
1615static dev_link_t *nsp_cs_attach(void)
1616{
1617 scsi_info_t *info;
1618 client_reg_t client_reg;
1619 dev_link_t *link;
1620 int ret;
1621 nsp_hw_data *data = &nsp_data_base;
1622
1623 nsp_dbg(NSP_DEBUG_INIT, "in");
1624
1625 /* Create new SCSI device */
1626 info = kmalloc(sizeof(*info), GFP_KERNEL);
1627 if (info == NULL) { return NULL; }
1628 memset(info, 0, sizeof(*info));
1629 link = &info->link;
1630 link->priv = info;
1631 data->ScsiInfo = info;
1632
1633 nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
1634
1635 /* The io structure describes IO port mapping */
1636 link->io.NumPorts1 = 0x10;
1637 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
1638 link->io.IOAddrLines = 10; /* not used */
1639
1640 /* Interrupt setup */
1641 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
1642 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
1643
1644 /* Interrupt handler */
1645 link->irq.Handler = &nspintr;
1646 link->irq.Instance = info;
1647 link->irq.Attributes |= (SA_SHIRQ | SA_SAMPLE_RANDOM);
1648
1649 /* General socket configuration */
1650 link->conf.Attributes = CONF_ENABLE_IRQ;
1651 link->conf.Vcc = 50;
1652 link->conf.IntType = INT_MEMORY_AND_IO;
1653 link->conf.Present = PRESENT_OPTION;
1654
1655
1656 /* Register with Card Services */
1657 link->next = dev_list;
1658 dev_list = link;
1659 client_reg.dev_info = &dev_info;
1660 client_reg.EventMask =
1661 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
1662 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
1663 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME ;
1664 client_reg.event_handler = &nsp_cs_event;
1665 client_reg.Version = 0x0210;
1666 client_reg.event_callback_args.client_data = link;
1667 ret = pcmcia_register_client(&link->handle, &client_reg);
1668 if (ret != CS_SUCCESS) {
1669 cs_error(link->handle, RegisterClient, ret);
1670 nsp_cs_detach(link);
1671 return NULL;
1672 }
1673
1674
1675 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
1676 return link;
1677} /* nsp_cs_attach */
1678
1679
1680/*======================================================================
1681 This deletes a driver "instance". The device is de-registered
1682 with Card Services. If it has been released, all local data
1683 structures are freed. Otherwise, the structures will be freed
1684 when the device is released.
1685======================================================================*/
1686static void nsp_cs_detach(dev_link_t *link)
1687{
1688 dev_link_t **linkp;
1689
1690 nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
1691
1692 /* Locate device structure */
1693 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
1694 if (*linkp == link) {
1695 break;
1696 }
1697 }
1698 if (*linkp == NULL) {
1699 return;
1700 }
1701
1702 if (link->state & DEV_CONFIG)
1703 nsp_cs_release(link);
1704
1705 /* Break the link with Card Services */
1706 if (link->handle) {
1707 pcmcia_deregister_client(link->handle);
1708 }
1709
1710 /* Unlink device structure, free bits */
1711 *linkp = link->next;
1712 kfree(link->priv);
1713 link->priv = NULL;
1714
1715} /* nsp_cs_detach */
1716
1717
1718/*======================================================================
1719 nsp_cs_config() is scheduled to run after a CARD_INSERTION event
1720 is received, to configure the PCMCIA socket, and to make the
1721 ethernet device available to the system.
1722======================================================================*/
1723#define CS_CHECK(fn, ret) \
1724do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
1725/*====================================================================*/
1726static void nsp_cs_config(dev_link_t *link)
1727{
1728 client_handle_t handle = link->handle;
1729 scsi_info_t *info = link->priv;
1730 tuple_t tuple;
1731 cisparse_t parse;
1732 int last_ret, last_fn;
1733 unsigned char tuple_data[64];
1734 config_info_t conf;
1735 win_req_t req;
1736 memreq_t map;
1737 cistpl_cftable_entry_t dflt = { 0 };
1738 struct Scsi_Host *host;
1739 nsp_hw_data *data = &nsp_data_base;
1740#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
1741 Scsi_Device *dev;
1742 dev_node_t **tail, *node;
1743#endif
1744
1745 nsp_dbg(NSP_DEBUG_INIT, "in");
1746
1747 tuple.DesiredTuple = CISTPL_CONFIG;
1748 tuple.Attributes = 0;
1749 tuple.TupleData = tuple_data;
1750 tuple.TupleDataMax = sizeof(tuple_data);
1751 tuple.TupleOffset = 0;
1752 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
1753 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
1754 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
1755 link->conf.ConfigBase = parse.config.base;
1756 link->conf.Present = parse.config.rmask[0];
1757
1758 /* Configure card */
1759 link->state |= DEV_CONFIG;
1760
1761 /* Look up the current Vcc */
1762 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
1763 link->conf.Vcc = conf.Vcc;
1764
1765 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
1766 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
1767 while (1) {
1768 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
1769
1770 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
1771 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
1772 goto next_entry;
1773
1774 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
1775 if (cfg->index == 0) { goto next_entry; }
1776 link->conf.ConfigIndex = cfg->index;
1777
1778 /* Does this card need audio output? */
1779 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
1780 link->conf.Attributes |= CONF_ENABLE_SPKR;
1781 link->conf.Status = CCSR_AUDIO_ENA;
1782 }
1783
1784 /* Use power settings for Vcc and Vpp if present */
1785 /* Note that the CIS values need to be rescaled */
1786 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
1787 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
1788 goto next_entry;
1789 }
1790 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
1791 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
1792 goto next_entry;
1793 }
1794 }
1795
1796 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
1797 link->conf.Vpp1 = link->conf.Vpp2 =
1798 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
1799 } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
1800 link->conf.Vpp1 = link->conf.Vpp2 =
1801 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
1802 }
1803
1804 /* Do we need to allocate an interrupt? */
1805 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
1806 link->conf.Attributes |= CONF_ENABLE_IRQ;
1807 }
1808
1809 /* IO window settings */
1810 link->io.NumPorts1 = link->io.NumPorts2 = 0;
1811 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
1812 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
1813 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
1814 if (!(io->flags & CISTPL_IO_8BIT))
1815 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
1816 if (!(io->flags & CISTPL_IO_16BIT))
1817 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
1818 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
1819 link->io.BasePort1 = io->win[0].base;
1820 link->io.NumPorts1 = io->win[0].len;
1821 if (io->nwin > 1) {
1822 link->io.Attributes2 = link->io.Attributes1;
1823 link->io.BasePort2 = io->win[1].base;
1824 link->io.NumPorts2 = io->win[1].len;
1825 }
1826 /* This reserves IO space but doesn't actually enable it */
1827 if (pcmcia_request_io(link->handle, &link->io) != 0)
1828 goto next_entry;
1829 }
1830
1831 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
1832 cistpl_mem_t *mem =
1833 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
1834 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
1835 req.Attributes |= WIN_ENABLE;
1836 req.Base = mem->win[0].host_addr;
1837 req.Size = mem->win[0].len;
1838 if (req.Size < 0x1000) {
1839 req.Size = 0x1000;
1840 }
1841 req.AccessSpeed = 0;
1842 if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
1843 goto next_entry;
1844 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
1845 if (pcmcia_map_mem_page(link->win, &map) != 0)
1846 goto next_entry;
1847
1848 data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
1849 data->MmioLength = req.Size;
1850 }
1851 /* If we got this far, we're cool! */
1852 break;
1853
1854 next_entry:
1855 nsp_dbg(NSP_DEBUG_INIT, "next");
1856
1857 if (link->io.NumPorts1) {
1858 pcmcia_release_io(link->handle, &link->io);
1859 }
1860 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
1861 }
1862
1863 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
1864 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
1865 }
1866 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
1867
1868 if (free_ports) {
1869 if (link->io.BasePort1) {
1870 release_region(link->io.BasePort1, link->io.NumPorts1);
1871 }
1872 if (link->io.BasePort2) {
1873 release_region(link->io.BasePort2, link->io.NumPorts2);
1874 }
1875 }
1876
1877 /* Set port and IRQ */
1878 data->BaseAddress = link->io.BasePort1;
1879 data->NumAddress = link->io.NumPorts1;
1880 data->IrqNumber = link->irq.AssignedIRQ;
1881
1882 nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d",
1883 data->BaseAddress, data->NumAddress, data->IrqNumber);
1884
1885 if(nsphw_init(data) == FALSE) {
1886 goto cs_failed;
1887 }
1888
1889#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2))
1890 host = nsp_detect(&nsp_driver_template);
1891#else
1892 scsi_register_host(&nsp_driver_template);
1893 for (host = scsi_host_get_next(NULL); host != NULL;
1894 host = scsi_host_get_next(host)) {
1895 if (host->hostt == &nsp_driver_template) {
1896 break;
1897 }
1898 }
1899#endif
1900
1901 if (host == NULL) {
1902 nsp_dbg(NSP_DEBUG_INIT, "detect failed");
1903 goto cs_failed;
1904 }
1905
1906
1907#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
1908 scsi_add_host (host, NULL);
1909 scsi_scan_host(host);
1910
1911 snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
1912 link->dev = &info->node;
1913 info->host = host;
1914
1915#else
1916 nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
1917 tail = &link->dev;
1918 info->ndev = 0;
1919
1920 nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
1921
1922 for (dev = host->host_queue; dev != NULL; dev = dev->next) {
1923 unsigned long id;
1924 id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) +
1925 ((dev->channel & 0x0f) << 8) +
1926 ((dev->host->host_no & 0x0f) << 12);
1927 node = &info->node[info->ndev];
1928 node->minor = 0;
1929 switch (dev->type) {
1930 case TYPE_TAPE:
1931 node->major = SCSI_TAPE_MAJOR;
1932 snprintf(node->dev_name, sizeof(node->dev_name), "st#%04lx", id);
1933 break;
1934 case TYPE_DISK:
1935 case TYPE_MOD:
1936 node->major = SCSI_DISK0_MAJOR;
1937 snprintf(node->dev_name, sizeof(node->dev_name), "sd#%04lx", id);
1938 break;
1939 case TYPE_ROM:
1940 case TYPE_WORM:
1941 node->major = SCSI_CDROM_MAJOR;
1942 snprintf(node->dev_name, sizeof(node->dev_name), "sr#%04lx", id);
1943 break;
1944 default:
1945 node->major = SCSI_GENERIC_MAJOR;
1946 snprintf(node->dev_name, sizeof(node->dev_name), "sg#%04lx", id);
1947 break;
1948 }
1949 *tail = node; tail = &node->next;
1950 info->ndev++;
1951 info->host = dev->host;
1952 }
1953
1954 *tail = NULL;
1955 if (info->ndev == 0) {
1956 nsp_msg(KERN_INFO, "no SCSI devices found");
1957 }
1958 nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
1959#endif
1960
1961 /* Finally, report what we've done */
1962 printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",
1963 link->conf.ConfigIndex,
1964 link->conf.Vcc/10, link->conf.Vcc%10);
1965 if (link->conf.Vpp1) {
1966 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
1967 }
1968 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
1969 printk(", irq %d", link->irq.AssignedIRQ);
1970 }
1971 if (link->io.NumPorts1) {
1972 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
1973 link->io.BasePort1+link->io.NumPorts1-1);
1974 }
1975 if (link->io.NumPorts2)
1976 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
1977 link->io.BasePort2+link->io.NumPorts2-1);
1978 if (link->win)
1979 printk(", mem 0x%06lx-0x%06lx", req.Base,
1980 req.Base+req.Size-1);
1981 printk("\n");
1982
1983 link->state &= ~DEV_CONFIG_PENDING;
1984 return;
1985
1986 cs_failed:
1987 nsp_dbg(NSP_DEBUG_INIT, "config fail");
1988 cs_error(link->handle, last_fn, last_ret);
1989 nsp_cs_release(link);
1990
1991 return;
1992} /* nsp_cs_config */
1993#undef CS_CHECK
1994
1995
1996/*======================================================================
1997 After a card is removed, nsp_cs_release() will unregister the net
1998 device, and release the PCMCIA configuration. If the device is
1999 still open, this will be postponed until it is closed.
2000======================================================================*/
2001static void nsp_cs_release(dev_link_t *link)
2002{
2003 scsi_info_t *info = link->priv;
2004 nsp_hw_data *data = NULL;
2005
2006 if (info->host == NULL) {
2007 nsp_msg(KERN_DEBUG, "unexpected card release call.");
2008 } else {
2009 data = (nsp_hw_data *)info->host->hostdata;
2010 }
2011
2012 nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
2013
2014 /* Unlink the device chain */
2015#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
2016 if (info->host != NULL) {
2017 scsi_remove_host(info->host);
2018 }
2019#else
2020 scsi_unregister_host(&nsp_driver_template);
2021#endif
2022 link->dev = NULL;
2023
2024 if (link->win) {
2025 if (data != NULL) {
2026 iounmap((void *)(data->MmioAddress));
2027 }
2028 pcmcia_release_window(link->win);
2029 }
2030 pcmcia_release_configuration(link->handle);
2031 if (link->io.NumPorts1) {
2032 pcmcia_release_io(link->handle, &link->io);
2033 }
2034 if (link->irq.AssignedIRQ) {
2035 pcmcia_release_irq(link->handle, &link->irq);
2036 }
2037 link->state &= ~DEV_CONFIG;
2038#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
2039 if (info->host != NULL) {
2040 scsi_host_put(info->host);
2041 }
2042#endif
2043} /* nsp_cs_release */
2044
2045/*======================================================================
2046
2047 The card status event handler. Mostly, this schedules other
2048 stuff to run after an event is received. A CARD_REMOVAL event
2049 also sets some flags to discourage the net drivers from trying
2050 to talk to the card any more.
2051
2052 When a CARD_REMOVAL event is received, we immediately set a flag
2053 to block future accesses to this device. All the functions that
2054 actually access the device should check this flag to make sure
2055 the card is still present.
2056
2057======================================================================*/
2058static int nsp_cs_event(event_t event,
2059 int priority,
2060 event_callback_args_t *args)
2061{
2062 dev_link_t *link = args->client_data;
2063 scsi_info_t *info = link->priv;
2064 nsp_hw_data *data;
2065
2066 nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event);
2067
2068 switch (event) {
2069 case CS_EVENT_CARD_REMOVAL:
2070 nsp_dbg(NSP_DEBUG_INIT, "event: remove");
2071 link->state &= ~DEV_PRESENT;
2072 if (link->state & DEV_CONFIG) {
2073 ((scsi_info_t *)link->priv)->stop = 1;
2074 nsp_cs_release(link);
2075 }
2076 break;
2077
2078 case CS_EVENT_CARD_INSERTION:
2079 nsp_dbg(NSP_DEBUG_INIT, "event: insert");
2080 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
2081#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
2082 info->bus = args->bus;
2083#endif
2084 nsp_cs_config(link);
2085 break;
2086
2087 case CS_EVENT_PM_SUSPEND:
2088 nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
2089 link->state |= DEV_SUSPEND;
2090 /* Fall through... */
2091 case CS_EVENT_RESET_PHYSICAL:
2092 /* Mark the device as stopped, to block IO until later */
2093 nsp_dbg(NSP_DEBUG_INIT, "event: reset physical");
2094
2095 if (info->host != NULL) {
2096 nsp_msg(KERN_INFO, "clear SDTR status");
2097
2098 data = (nsp_hw_data *)info->host->hostdata;
2099
2100 nsphw_init_sync(data);
2101 }
2102
2103 info->stop = 1;
2104 if (link->state & DEV_CONFIG) {
2105 pcmcia_release_configuration(link->handle);
2106 }
2107 break;
2108
2109 case CS_EVENT_PM_RESUME:
2110 nsp_dbg(NSP_DEBUG_INIT, "event: resume");
2111 link->state &= ~DEV_SUSPEND;
2112 /* Fall through... */
2113 case CS_EVENT_CARD_RESET:
2114 nsp_dbg(NSP_DEBUG_INIT, "event: reset");
2115 if (link->state & DEV_CONFIG) {
2116 pcmcia_request_configuration(link->handle, &link->conf);
2117 }
2118 info->stop = 0;
2119
2120 if (info->host != NULL) {
2121 nsp_msg(KERN_INFO, "reset host and bus");
2122
2123 data = (nsp_hw_data *)info->host->hostdata;
2124
2125 nsphw_init (data);
2126 nsp_bus_reset(data);
2127 }
2128
2129 break;
2130
2131 default:
2132 nsp_dbg(NSP_DEBUG_INIT, "event: unknown");
2133 break;
2134 }
2135 nsp_dbg(NSP_DEBUG_INIT, "end");
2136 return 0;
2137} /* nsp_cs_event */
2138
2139/*======================================================================*
2140 * module entry point
2141 *====================================================================*/
2142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
2143static struct pcmcia_driver nsp_driver = {
2144 .owner = THIS_MODULE,
2145 .drv = {
2146 .name = "nsp_cs",
2147 },
2148 .attach = nsp_cs_attach,
2149 .detach = nsp_cs_detach,
2150};
2151#endif
2152
2153static int __init nsp_cs_init(void)
2154{
2155#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
2156 nsp_msg(KERN_INFO, "loading...");
2157
2158 return pcmcia_register_driver(&nsp_driver);
2159#else
2160 servinfo_t serv;
2161
2162 nsp_msg(KERN_INFO, "loading...");
2163 pcmcia_get_card_services_info(&serv);
2164 if (serv.Revision != CS_RELEASE_CODE) {
2165 nsp_msg(KERN_DEBUG, "Card Services release does not match!");
2166 return -EINVAL;
2167 }
2168 register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
2169
2170 nsp_dbg(NSP_DEBUG_INIT, "out");
2171 return 0;
2172#endif
2173}
2174
2175static void __exit nsp_cs_exit(void)
2176{
2177 nsp_msg(KERN_INFO, "unloading...");
2178
2179#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
2180 pcmcia_unregister_driver(&nsp_driver);
2181 BUG_ON(dev_list != NULL);
2182#else
2183 unregister_pcmcia_driver(&dev_info);
2184 /* XXX: this really needs to move into generic code.. */
2185 while (dev_list != NULL) {
2186 if (dev_list->state & DEV_CONFIG) {
2187 nsp_cs_release(dev_list);
2188 }
2189 nsp_cs_detach(dev_list);
2190 }
2191#endif
2192}
2193
2194
2195module_init(nsp_cs_init)
2196module_exit(nsp_cs_exit)
2197
2198/* end */
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
new file mode 100644
index 000000000000..c201b52e063a
--- /dev/null
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -0,0 +1,472 @@
1/*=======================================================/
2 Header file for nsp_cs.c
3 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
4
5 Ver.1.0 : Cut unused lines.
6 Ver 0.1 : Initial version.
7
8 This software may be used and distributed according to the terms of
9 the GNU General Public License.
10
11=========================================================*/
12
13/* $Id: nsp_cs.h,v 1.19 2003/08/18 11:09:19 elca Exp $ */
14
15#ifndef __nsp_cs__
16#define __nsp_cs__
17
18/* for debugging */
19//#define NSP_DEBUG 9
20
21/*
22#define static
23#define inline
24*/
25
26/************************************
27 * Some useful macros...
28 */
29#define BIT(x) (1L << (x))
30
31/* SCSI initiator must be ID 7 */
32#define NSP_INITIATOR_ID 7
33
34#define NSP_SELTIMEOUT 200
35
36/***************************************************************************
37 * register definitions
38 ***************************************************************************/
39/*========================================================================
40 * base register
41 ========================================================================*/
42#define IRQCONTROL 0x00 /* R */
43# define IRQCONTROL_RESELECT_CLEAR BIT(0)
44# define IRQCONTROL_PHASE_CHANGE_CLEAR BIT(1)
45# define IRQCONTROL_TIMER_CLEAR BIT(2)
46# define IRQCONTROL_FIFO_CLEAR BIT(3)
47# define IRQCONTROL_ALLMASK 0xff
48# define IRQCONTROL_ALLCLEAR (IRQCONTROL_RESELECT_CLEAR | \
49 IRQCONTROL_PHASE_CHANGE_CLEAR | \
50 IRQCONTROL_TIMER_CLEAR | \
51 IRQCONTROL_FIFO_CLEAR )
52# define IRQCONTROL_IRQDISABLE 0xf0
53
54#define IRQSTATUS 0x00 /* W */
55# define IRQSTATUS_SCSI BIT(0)
56# define IRQSTATUS_TIMER BIT(2)
57# define IRQSTATUS_FIFO BIT(3)
58# define IRQSTATUS_MASK 0x0f
59
60#define IFSELECT 0x01 /* W */
61# define IF_IFSEL BIT(0)
62# define IF_REGSEL BIT(2)
63
64#define FIFOSTATUS 0x01 /* R */
65# define FIFOSTATUS_CHIP_REVISION_MASK 0x0f
66# define FIFOSTATUS_CHIP_ID_MASK 0x70
67# define FIFOSTATUS_FULL_EMPTY BIT(7)
68
69#define INDEXREG 0x02 /* R/W */
70#define DATAREG 0x03 /* R/W */
71#define FIFODATA 0x04 /* R/W */
72#define FIFODATA1 0x05 /* R/W */
73#define FIFODATA2 0x06 /* R/W */
74#define FIFODATA3 0x07 /* R/W */
75
76/*====================================================================
77 * indexed register
78 ====================================================================*/
79#define EXTBUSCTRL 0x10 /* R/W,deleted */
80
81#define CLOCKDIV 0x11 /* R/W */
82# define CLOCK_40M 0x02
83# define CLOCK_20M 0x01
84# define FAST_20 BIT(2)
85
86#define TERMPWRCTRL 0x13 /* R/W */
87# define POWER_ON BIT(0)
88
89#define SCSIIRQMODE 0x15 /* R/W */
90# define SCSI_PHASE_CHANGE_EI BIT(0)
91# define RESELECT_EI BIT(4)
92# define FIFO_IRQ_EI BIT(5)
93# define SCSI_RESET_IRQ_EI BIT(6)
94
95#define IRQPHASESENCE 0x16 /* R */
96# define LATCHED_MSG BIT(0)
97# define LATCHED_IO BIT(1)
98# define LATCHED_CD BIT(2)
99# define LATCHED_BUS_FREE BIT(3)
100# define PHASE_CHANGE_IRQ BIT(4)
101# define RESELECT_IRQ BIT(5)
102# define FIFO_IRQ BIT(6)
103# define SCSI_RESET_IRQ BIT(7)
104
105#define TIMERCOUNT 0x17 /* R/W */
106
107#define SCSIBUSCTRL 0x18 /* R/W */
108# define SCSI_SEL BIT(0)
109# define SCSI_RST BIT(1)
110# define SCSI_DATAOUT_ENB BIT(2)
111# define SCSI_ATN BIT(3)
112# define SCSI_ACK BIT(4)
113# define SCSI_BSY BIT(5)
114# define AUTODIRECTION BIT(6)
115# define ACKENB BIT(7)
116
117#define SCSIBUSMON 0x19 /* R */
118
119#define SETARBIT 0x1A /* W */
120# define ARBIT_GO BIT(0)
121# define ARBIT_FLAG_CLEAR BIT(1)
122
123#define ARBITSTATUS 0x1A /* R */
124/*# define ARBIT_GO BIT(0)*/
125# define ARBIT_WIN BIT(1)
126# define ARBIT_FAIL BIT(2)
127# define RESELECT_FLAG BIT(3)
128
129#define PARITYCTRL 0x1B /* W */
130#define PARITYSTATUS 0x1B /* R */
131
132#define COMMANDCTRL 0x1C /* W */
133# define CLEAR_COMMAND_POINTER BIT(0)
134# define AUTO_COMMAND_GO BIT(1)
135
136#define RESELECTID 0x1C /* R */
137#define COMMANDDATA 0x1D /* R/W */
138
139#define POINTERCLR 0x1E /* W */
140# define POINTER_CLEAR BIT(0)
141# define ACK_COUNTER_CLEAR BIT(1)
142# define REQ_COUNTER_CLEAR BIT(2)
143# define HOST_COUNTER_CLEAR BIT(3)
144# define READ_SOURCE (BIT(4) | BIT(5))
145# define ACK_COUNTER (0)
146# define REQ_COUNTER (BIT(4))
147# define HOST_COUNTER (BIT(5))
148
149#define TRANSFERCOUNT 0x1E /* R */
150
151#define TRANSFERMODE 0x20 /* R/W */
152# define MODE_MEM8 BIT(0)
153# define MODE_MEM32 BIT(1)
154# define MODE_ADR24 BIT(2)
155# define MODE_ADR32 BIT(3)
156# define MODE_IO8 BIT(4)
157# define MODE_IO32 BIT(5)
158# define TRANSFER_GO BIT(6)
159# define BRAIND BIT(7)
160
161#define SYNCREG 0x21 /* R/W */
162# define SYNCREG_OFFSET_MASK 0x0f
163# define SYNCREG_PERIOD_MASK 0xf0
164# define SYNCREG_PERIOD_SHIFT 4
165
166#define SCSIDATALATCH 0x22 /* W */
167#define SCSIDATAIN 0x22 /* R */
168#define SCSIDATAWITHACK 0x23 /* R/W */
169#define SCAMCONTROL 0x24 /* W */
170#define SCAMSTATUS 0x24 /* R */
171#define SCAMDATA 0x25 /* R/W */
172
173#define OTHERCONTROL 0x26 /* R/W */
174# define TPL_ROM_WRITE_EN BIT(0)
175# define TPWR_OUT BIT(1)
176# define TPWR_SENSE BIT(2)
177# define RA8_CONTROL BIT(3)
178
179#define ACKWIDTH 0x27 /* R/W */
180#define CLRTESTPNT 0x28 /* W */
181#define ACKCNTLD 0x29 /* W */
182#define REQCNTLD 0x2A /* W */
183#define HSTCNTLD 0x2B /* W */
184#define CHECKSUM 0x2C /* R/W */
185
186/************************************************************************
187 * Input status bit definitions.
188 ************************************************************************/
189#define S_MESSAGE BIT(0) /* Message line from SCSI bus */
190#define S_IO BIT(1) /* Input/Output line from SCSI bus */
191#define S_CD BIT(2) /* Command/Data line from SCSI bus */
192#define S_BUSY BIT(3) /* Busy line from SCSI bus */
193#define S_ACK BIT(4) /* Acknowlege line from SCSI bus */
194#define S_REQUEST BIT(5) /* Request line from SCSI bus */
195#define S_SELECT BIT(6) /* */
196#define S_ATN BIT(7) /* */
197
198/***********************************************************************
199 * Useful Bus Monitor status combinations.
200 ***********************************************************************/
201#define BUSMON_SEL S_SELECT
202#define BUSMON_BSY S_BUSY
203#define BUSMON_REQ S_REQUEST
204#define BUSMON_IO S_IO
205#define BUSMON_ACK S_ACK
206#define BUSMON_BUS_FREE 0
207#define BUSMON_COMMAND ( S_BUSY | S_CD | S_REQUEST )
208#define BUSMON_MESSAGE_IN ( S_BUSY | S_CD | S_IO | S_MESSAGE | S_REQUEST )
209#define BUSMON_MESSAGE_OUT ( S_BUSY | S_CD | S_MESSAGE | S_REQUEST )
210#define BUSMON_DATA_IN ( S_BUSY | S_IO | S_REQUEST )
211#define BUSMON_DATA_OUT ( S_BUSY | S_REQUEST )
212#define BUSMON_STATUS ( S_BUSY | S_CD | S_IO | S_REQUEST )
213#define BUSMON_SELECT ( S_IO | S_SELECT )
214#define BUSMON_RESELECT ( S_IO | S_SELECT )
215#define BUSMON_PHASE_MASK ( S_CD | S_IO | S_MESSAGE | S_SELECT )
216
217#define BUSPHASE_SELECT ( BUSMON_SELECT & BUSMON_PHASE_MASK )
218#define BUSPHASE_COMMAND ( BUSMON_COMMAND & BUSMON_PHASE_MASK )
219#define BUSPHASE_MESSAGE_IN ( BUSMON_MESSAGE_IN & BUSMON_PHASE_MASK )
220#define BUSPHASE_MESSAGE_OUT ( BUSMON_MESSAGE_OUT & BUSMON_PHASE_MASK )
221#define BUSPHASE_DATA_IN ( BUSMON_DATA_IN & BUSMON_PHASE_MASK )
222#define BUSPHASE_DATA_OUT ( BUSMON_DATA_OUT & BUSMON_PHASE_MASK )
223#define BUSPHASE_STATUS ( BUSMON_STATUS & BUSMON_PHASE_MASK )
224
225/*====================================================================*/
226
227typedef struct scsi_info_t {
228 dev_link_t link;
229 struct Scsi_Host *host;
230#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
231 dev_node_t node;
232#else
233 int ndev;
234 dev_node_t node[8];
235 struct bus_operations *bus;
236#endif
237 int stop;
238} scsi_info_t;
239
240
241/* synchronous transfer negotiation data */
242typedef struct _sync_data {
243 unsigned int SyncNegotiation;
244#define SYNC_NOT_YET 0
245#define SYNC_OK 1
246#define SYNC_NG 2
247
248 unsigned int SyncPeriod;
249 unsigned int SyncOffset;
250 unsigned char SyncRegister;
251 unsigned char AckWidth;
252} sync_data;
253
254typedef struct _nsp_hw_data {
255 unsigned int BaseAddress;
256 unsigned int NumAddress;
257 unsigned int IrqNumber;
258
259 unsigned long MmioAddress;
260#define NSP_MMIO_OFFSET 0x0800
261 unsigned long MmioLength;
262
263 unsigned char ScsiClockDiv;
264
265 unsigned char TransferMode;
266
267 int TimerCount;
268 int SelectionTimeOut;
269 Scsi_Cmnd *CurrentSC;
270 //int CurrnetTarget;
271
272 int FifoCount;
273
274#define MSGBUF_SIZE 20
275 unsigned char MsgBuffer[MSGBUF_SIZE];
276 int MsgLen;
277
278#define N_TARGET 8
279 sync_data Sync[N_TARGET];
280
281 char nspinfo[110]; /* description */
282 spinlock_t Lock;
283
284 scsi_info_t *ScsiInfo; /* attach <-> detect glue */
285
286
287#ifdef NSP_DEBUG
288 int CmdId; /* Accepted command serial number.
289 Used for debugging. */
290#endif
291} nsp_hw_data;
292
293
294/****************************************************************************
295 *
296 */
297
298/* Card service functions */
299static dev_link_t *nsp_cs_attach (void);
300static void nsp_cs_detach (dev_link_t *link);
301static void nsp_cs_release(dev_link_t *link);
302static void nsp_cs_config (dev_link_t *link);
303static int nsp_cs_event (event_t event, int priority, event_callback_args_t *args);
304
305/* Linux SCSI subsystem specific functions */
306static struct Scsi_Host *nsp_detect (Scsi_Host_Template *sht);
307#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
308static int nsp_detect_old (Scsi_Host_Template *sht);
309static int nsp_release_old(struct Scsi_Host *shpnt);
310#endif
311static const char *nsp_info (struct Scsi_Host *shpnt);
312static int nsp_proc_info (
313#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
314 struct Scsi_Host *host,
315#endif
316 char *buffer,
317 char **start,
318 off_t offset,
319 int length,
320#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
321 int hostno,
322#endif
323 int inout);
324static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *SCpnt));
325
326/* Error handler */
327/*static int nsp_eh_abort (Scsi_Cmnd *SCpnt);*/
328/*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/
329static int nsp_eh_bus_reset (Scsi_Cmnd *SCpnt);
330static int nsp_eh_host_reset (Scsi_Cmnd *SCpnt);
331static int nsp_bus_reset (nsp_hw_data *data);
332
333/* */
334static int nsphw_init (nsp_hw_data *data);
335static int nsphw_start_selection(Scsi_Cmnd *SCpnt);
336static void nsp_start_timer (Scsi_Cmnd *SCpnt, int time);
337static int nsp_fifo_count (Scsi_Cmnd *SCpnt);
338static void nsp_pio_read (Scsi_Cmnd *SCpnt);
339static void nsp_pio_write (Scsi_Cmnd *SCpnt);
340static int nsp_nexus (Scsi_Cmnd *SCpnt);
341static void nsp_scsi_done (Scsi_Cmnd *SCpnt);
342static int nsp_analyze_sdtr (Scsi_Cmnd *SCpnt);
343static int nsp_negate_signal (Scsi_Cmnd *SCpnt, unsigned char mask, char *str);
344static int nsp_expect_signal (Scsi_Cmnd *SCpnt, unsigned char current_phase, unsigned char mask);
345static int nsp_xfer (Scsi_Cmnd *SCpnt, int phase);
346static int nsp_dataphase_bypass (Scsi_Cmnd *SCpnt);
347static int nsp_reselected (Scsi_Cmnd *SCpnt);
348static struct Scsi_Host *nsp_detect(Scsi_Host_Template *sht);
349
350/* Interrupt handler */
351//static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs);
352
353/* Module entry point*/
354static int __init nsp_cs_init(void);
355static void __exit nsp_cs_exit(void);
356
357
358/* Debug */
359#ifdef NSP_DEBUG
360static void show_command (Scsi_Cmnd *SCpnt);
361static void show_phase (Scsi_Cmnd *SCpnt);
362static void show_busphase(unsigned char stat);
363static void show_message (nsp_hw_data *data);
364#else
365# define show_command(ptr) /* */
366# define show_phase(SCpnt) /* */
367# define show_busphase(stat) /* */
368# define show_message(data) /* */
369#endif
370
371/*
372 * SCSI phase
373 */
374enum _scsi_phase {
375 PH_UNDETERMINED ,
376 PH_ARBSTART ,
377 PH_SELSTART ,
378 PH_SELECTED ,
379 PH_COMMAND ,
380 PH_DATA ,
381 PH_STATUS ,
382 PH_MSG_IN ,
383 PH_MSG_OUT ,
384 PH_DISCONNECT ,
385 PH_RESELECT ,
386 PH_ABORT ,
387 PH_RESET
388};
389
390enum _data_in_out {
391 IO_UNKNOWN,
392 IO_IN,
393 IO_OUT
394};
395
396enum _burst_mode {
397 BURST_IO8 = 0,
398 BURST_IO32 = 1,
399 BURST_MEM32 = 2,
400};
401
402
403/**************************************************************************
404 * SCSI messaage
405 */
406#define MSG_COMMAND_COMPLETE 0x00
407#define MSG_EXTENDED 0x01
408#define MSG_ABORT 0x06
409#define MSG_NO_OPERATION 0x08
410#define MSG_BUS_DEVICE_RESET 0x0c
411
412#define MSG_EXT_SDTR 0x01
413
414
415/**************************************************************************
416 * Compatibility functions
417 */
418
419/* for Kernel 2.4 */
420#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
421# define scsi_register_host(template) scsi_register_module(MODULE_SCSI_HA, template)
422# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
423# define scsi_host_put(host) scsi_unregister(host)
424
425typedef void irqreturn_t;
426# define IRQ_NONE /* */
427# define IRQ_HANDLED /* */
428# define IRQ_RETVAL(x) /* */
429
430/* This is ad-hoc version of scsi_host_get_next() */
431static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
432{
433 if (host == NULL) {
434 return scsi_hostlist;
435 } else {
436 return host->next;
437 }
438}
439
440/* This is ad-hoc version of scsi_host_hn_get() */
441static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
442{
443 struct Scsi_Host *host;
444
445 for (host = scsi_host_get_next(NULL); host != NULL;
446 host = scsi_host_get_next(host)) {
447 if (host->host_no == hostno) {
448 break;
449 }
450 }
451
452 return host;
453}
454
455static void cs_error(client_handle_t handle, int func, int ret)
456{
457 error_info_t err = { func, ret };
458 pcmcia_report_error(handle, &err);
459}
460
461/* scatter-gather table */
462# define BUFFER_ADDR (SCpnt->SCp.buffer->address)
463#endif
464
465/* for Kernel 2.6 */
466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
467/* scatter-gather table */
468# define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset))
469#endif
470
471#endif /*__nsp_cs__*/
472/* end */
diff --git a/drivers/scsi/pcmcia/nsp_debug.c b/drivers/scsi/pcmcia/nsp_debug.c
new file mode 100644
index 000000000000..62e5c60067fd
--- /dev/null
+++ b/drivers/scsi/pcmcia/nsp_debug.c
@@ -0,0 +1,215 @@
1/*========================================================================
2 Debug routines for nsp_cs
3 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
4
5 This software may be used and distributed according to the terms of
6 the GNU General Public License.
7=========================================================================*/
8
9/* $Id: nsp_debug.c,v 1.3 2003/07/26 14:21:09 elca Exp $ */
10
11/*
12 * Show the command data of a command
13 */
14static const char unknown[] = "UNKNOWN";
15
16static const char * group_0_commands[] = {
17/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
18/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
19/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
20/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
21/* 13-16 */ unknown, "Recover Buffered Data", "Mode Select", "Reserve",
22/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
23/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
24/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
25};
26
27
28static const char *group_1_commands[] = {
29/* 20-22 */ unknown, unknown, unknown,
30/* 23-28 */ unknown, unknown, "Read Capacity", unknown, unknown, "Read (10)",
31/* 29-2d */ unknown, "Write (10)", "Seek (10)", unknown, unknown,
32/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal",
33/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
34/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data",
35/* 38-3c */ "Medium Scan", "Compare","Copy Verify", "Write Buffer", "Read Buffer",
36/* 3d-3f */ "Update Block", "Read Long", "Write Long",
37};
38
39
40static const char *group_2_commands[] = {
41/* 40-41 */ "Change Definition", "Write Same",
42/* 42-48 */ "Read Sub-Ch(cd)", "Read TOC", "Read Header(cd)", "Play Audio(cd)", unknown, "Play Audio MSF(cd)", "Play Audio Track/Index(cd)",
43/* 49-4f */ "Play Track Relative(10)(cd)", unknown, "Pause/Resume(cd)", "Log Select", "Log Sense", unknown, unknown,
44/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
45/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
46/* 5c-5f */ unknown, unknown, unknown,
47};
48
49#define group(opcode) (((opcode) >> 5) & 7)
50
51#define RESERVED_GROUP 0
52#define VENDOR_GROUP 1
53#define NOTEXT_GROUP 2
54
55static const char **commands[] = {
56 group_0_commands, group_1_commands, group_2_commands,
57 (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP,
58 (const char **) NOTEXT_GROUP, (const char **) VENDOR_GROUP,
59 (const char **) VENDOR_GROUP
60};
61
62static const char reserved[] = "RESERVED";
63static const char vendor[] = "VENDOR SPECIFIC";
64
65static void print_opcodek(unsigned char opcode)
66{
67 const char **table = commands[ group(opcode) ];
68
69 switch ((unsigned long) table) {
70 case RESERVED_GROUP:
71 printk("%s[%02x] ", reserved, opcode);
72 break;
73 case NOTEXT_GROUP:
74 printk("%s(notext)[%02x] ", unknown, opcode);
75 break;
76 case VENDOR_GROUP:
77 printk("%s[%02x] ", vendor, opcode);
78 break;
79 default:
80 if (table[opcode & 0x1f] != unknown)
81 printk("%s[%02x] ", table[opcode & 0x1f], opcode);
82 else
83 printk("%s[%02x] ", unknown, opcode);
84 break;
85 }
86}
87
88static void print_commandk (unsigned char *command)
89{
90 int i, s;
91 printk(KERN_DEBUG);
92 print_opcodek(command[0]);
93 /*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
94 if ((command[0] >> 5) == 6 ||
95 (command[0] >> 5) == 7 ) {
96 s = 12; /* vender specific */
97 } else {
98 s = COMMAND_SIZE(command[0]);
99 }
100 for ( i = 1; i < s; ++i) {
101 printk("%02x ", command[i]);
102 }
103
104 switch (s) {
105 case 6:
106 printk("LBA=%d len=%d",
107 (((unsigned int)command[1] & 0x0f) << 16) |
108 ( (unsigned int)command[2] << 8) |
109 ( (unsigned int)command[3] ),
110 (unsigned int)command[4]
111 );
112 break;
113 case 10:
114 printk("LBA=%d len=%d",
115 ((unsigned int)command[2] << 24) |
116 ((unsigned int)command[3] << 16) |
117 ((unsigned int)command[4] << 8) |
118 ((unsigned int)command[5] ),
119 ((unsigned int)command[7] << 8) |
120 ((unsigned int)command[8] )
121 );
122 break;
123 case 12:
124 printk("LBA=%d len=%d",
125 ((unsigned int)command[2] << 24) |
126 ((unsigned int)command[3] << 16) |
127 ((unsigned int)command[4] << 8) |
128 ((unsigned int)command[5] ),
129 ((unsigned int)command[6] << 24) |
130 ((unsigned int)command[7] << 16) |
131 ((unsigned int)command[8] << 8) |
132 ((unsigned int)command[9] )
133 );
134 break;
135 default:
136 break;
137 }
138 printk("\n");
139}
140
141static void show_command(Scsi_Cmnd *SCpnt)
142{
143 print_commandk(SCpnt->cmnd);
144}
145
146static void show_phase(Scsi_Cmnd *SCpnt)
147{
148 int i = SCpnt->SCp.phase;
149
150 char *ph[] = {
151 "PH_UNDETERMINED",
152 "PH_ARBSTART",
153 "PH_SELSTART",
154 "PH_SELECTED",
155 "PH_COMMAND",
156 "PH_DATA",
157 "PH_STATUS",
158 "PH_MSG_IN",
159 "PH_MSG_OUT",
160 "PH_DISCONNECT",
161 "PH_RESELECT"
162 };
163
164 if ( i < PH_UNDETERMINED || i > PH_RESELECT ) {
165 printk(KERN_DEBUG "scsi phase: unknown(%d)\n", i);
166 return;
167 }
168
169 printk(KERN_DEBUG "scsi phase: %s\n", ph[i]);
170
171 return;
172}
173
174static void show_busphase(unsigned char stat)
175{
176 switch(stat) {
177 case BUSPHASE_COMMAND:
178 printk(KERN_DEBUG "BUSPHASE_COMMAND\n");
179 break;
180 case BUSPHASE_MESSAGE_IN:
181 printk(KERN_DEBUG "BUSPHASE_MESSAGE_IN\n");
182 break;
183 case BUSPHASE_MESSAGE_OUT:
184 printk(KERN_DEBUG "BUSPHASE_MESSAGE_OUT\n");
185 break;
186 case BUSPHASE_DATA_IN:
187 printk(KERN_DEBUG "BUSPHASE_DATA_IN\n");
188 break;
189 case BUSPHASE_DATA_OUT:
190 printk(KERN_DEBUG "BUSPHASE_DATA_OUT\n");
191 break;
192 case BUSPHASE_STATUS:
193 printk(KERN_DEBUG "BUSPHASE_STATUS\n");
194 break;
195 case BUSPHASE_SELECT:
196 printk(KERN_DEBUG "BUSPHASE_SELECT\n");
197 break;
198 default:
199 printk(KERN_DEBUG "BUSPHASE_other\n");
200 break;
201 }
202}
203
204static void show_message(nsp_hw_data *data)
205{
206 int i;
207
208 printk(KERN_DEBUG "msg:");
209 for(i=0; i < data->MsgLen; i++) {
210 printk(" %02x", data->MsgBuffer[i]);
211 }
212 printk("\n");
213}
214
215/* end */
diff --git a/drivers/scsi/pcmcia/nsp_io.h b/drivers/scsi/pcmcia/nsp_io.h
new file mode 100644
index 000000000000..3b8746f85b6c
--- /dev/null
+++ b/drivers/scsi/pcmcia/nsp_io.h
@@ -0,0 +1,274 @@
1/*
2 NinjaSCSI I/O funtions
3 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
4
5 This software may be used and distributed according to the terms of
6 the GNU General Public License.
7
8 */
9
10/* $Id: nsp_io.h,v 1.3 2003/08/04 21:15:26 elca Exp $ */
11
12#ifndef __NSP_IO_H__
13#define __NSP_IO_H__
14
15static inline void nsp_write(unsigned int base,
16 unsigned int index,
17 unsigned char val);
18static inline unsigned char nsp_read(unsigned int base,
19 unsigned int index);
20static inline void nsp_index_write(unsigned int BaseAddr,
21 unsigned int Register,
22 unsigned char Value);
23static inline unsigned char nsp_index_read(unsigned int BaseAddr,
24 unsigned int Register);
25
26/*******************************************************************
27 * Basic IO
28 */
29
30static inline void nsp_write(unsigned int base,
31 unsigned int index,
32 unsigned char val)
33{
34 outb(val, (base + index));
35}
36
37static inline unsigned char nsp_read(unsigned int base,
38 unsigned int index)
39{
40 return inb(base + index);
41}
42
43
44/**********************************************************************
45 * Indexed IO
46 */
47static inline unsigned char nsp_index_read(unsigned int BaseAddr,
48 unsigned int Register)
49{
50 outb(Register, BaseAddr + INDEXREG);
51 return inb(BaseAddr + DATAREG);
52}
53
54static inline void nsp_index_write(unsigned int BaseAddr,
55 unsigned int Register,
56 unsigned char Value)
57{
58 outb(Register, BaseAddr + INDEXREG);
59 outb(Value, BaseAddr + DATAREG);
60}
61
62/*********************************************************************
63 * fifo func
64 */
65
66/* read 8 bit FIFO */
67static inline void nsp_multi_read_1(unsigned int BaseAddr,
68 unsigned int Register,
69 void *buf,
70 unsigned long count)
71{
72 insb(BaseAddr + Register, buf, count);
73}
74
75static inline void nsp_fifo8_read(unsigned int base,
76 void *buf,
77 unsigned long count)
78{
79 /*nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx", buf, count);*/
80 nsp_multi_read_1(base, FIFODATA, buf, count);
81}
82
83/*--------------------------------------------------------------*/
84
85/* read 16 bit FIFO */
86static inline void nsp_multi_read_2(unsigned int BaseAddr,
87 unsigned int Register,
88 void *buf,
89 unsigned long count)
90{
91 insw(BaseAddr + Register, buf, count);
92}
93
94static inline void nsp_fifo16_read(unsigned int base,
95 void *buf,
96 unsigned long count)
97{
98 //nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*2", buf, count);
99 nsp_multi_read_2(base, FIFODATA, buf, count);
100}
101
102/*--------------------------------------------------------------*/
103
104/* read 32bit FIFO */
105static inline void nsp_multi_read_4(unsigned int BaseAddr,
106 unsigned int Register,
107 void *buf,
108 unsigned long count)
109{
110 insl(BaseAddr + Register, buf, count);
111}
112
113static inline void nsp_fifo32_read(unsigned int base,
114 void *buf,
115 unsigned long count)
116{
117 //nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
118 nsp_multi_read_4(base, FIFODATA, buf, count);
119}
120
121/*----------------------------------------------------------*/
122
123/* write 8bit FIFO */
124static inline void nsp_multi_write_1(unsigned int BaseAddr,
125 unsigned int Register,
126 void *buf,
127 unsigned long count)
128{
129 outsb(BaseAddr + Register, buf, count);
130}
131
132static inline void nsp_fifo8_write(unsigned int base,
133 void *buf,
134 unsigned long count)
135{
136 nsp_multi_write_1(base, FIFODATA, buf, count);
137}
138
139/*---------------------------------------------------------*/
140
141/* write 16bit FIFO */
142static inline void nsp_multi_write_2(unsigned int BaseAddr,
143 unsigned int Register,
144 void *buf,
145 unsigned long count)
146{
147 outsw(BaseAddr + Register, buf, count);
148}
149
150static inline void nsp_fifo16_write(unsigned int base,
151 void *buf,
152 unsigned long count)
153{
154 nsp_multi_write_2(base, FIFODATA, buf, count);
155}
156
157/*---------------------------------------------------------*/
158
159/* write 32bit FIFO */
160static inline void nsp_multi_write_4(unsigned int BaseAddr,
161 unsigned int Register,
162 void *buf,
163 unsigned long count)
164{
165 outsl(BaseAddr + Register, buf, count);
166}
167
168static inline void nsp_fifo32_write(unsigned int base,
169 void *buf,
170 unsigned long count)
171{
172 nsp_multi_write_4(base, FIFODATA, buf, count);
173}
174
175
176/*====================================================================*/
177
178static inline void nsp_mmio_write(unsigned long base,
179 unsigned int index,
180 unsigned char val)
181{
182 unsigned char *ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + index);
183
184 writeb(val, ptr);
185}
186
187static inline unsigned char nsp_mmio_read(unsigned long base,
188 unsigned int index)
189{
190 unsigned char *ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + index);
191
192 return readb(ptr);
193}
194
195/*-----------*/
196
197static inline unsigned char nsp_mmio_index_read(unsigned long base,
198 unsigned int reg)
199{
200 unsigned char *index_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + INDEXREG);
201 unsigned char *data_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + DATAREG);
202
203 writeb((unsigned char)reg, index_ptr);
204 return readb(data_ptr);
205}
206
207static inline void nsp_mmio_index_write(unsigned long base,
208 unsigned int reg,
209 unsigned char val)
210{
211 unsigned char *index_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + INDEXREG);
212 unsigned char *data_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + DATAREG);
213
214 writeb((unsigned char)reg, index_ptr);
215 writeb(val, data_ptr);
216}
217
218/* read 32bit FIFO */
219static inline void nsp_mmio_multi_read_4(unsigned long base,
220 unsigned int Register,
221 void *buf,
222 unsigned long count)
223{
224 unsigned long *ptr = (unsigned long *)(base + Register);
225 unsigned long *tmp = (unsigned long *)buf;
226 int i;
227
228 //nsp_dbg(NSP_DEBUG_DATA_IO, "base 0x%0lx ptr 0x%p",base,ptr);
229
230 for (i = 0; i < count; i++) {
231 *tmp = readl(ptr);
232 //nsp_dbg(NSP_DEBUG_DATA_IO, "<%d,%p,%p,%lx>", i, ptr, tmp, *tmp);
233 tmp++;
234 }
235}
236
237static inline void nsp_mmio_fifo32_read(unsigned int base,
238 void *buf,
239 unsigned long count)
240{
241 //nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
242 nsp_mmio_multi_read_4(base, FIFODATA, buf, count);
243}
244
245static inline void nsp_mmio_multi_write_4(unsigned long base,
246 unsigned int Register,
247 void *buf,
248 unsigned long count)
249{
250 unsigned long *ptr = (unsigned long *)(base + Register);
251 unsigned long *tmp = (unsigned long *)buf;
252 int i;
253
254 //nsp_dbg(NSP_DEBUG_DATA_IO, "base 0x%0lx ptr 0x%p",base,ptr);
255
256 for (i = 0; i < count; i++) {
257 writel(*tmp, ptr);
258 //nsp_dbg(NSP_DEBUG_DATA_IO, "<%d,%p,%p,%lx>", i, ptr, tmp, *tmp);
259 tmp++;
260 }
261}
262
263static inline void nsp_mmio_fifo32_write(unsigned int base,
264 void *buf,
265 unsigned long count)
266{
267 //nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
268 nsp_mmio_multi_write_4(base, FIFODATA, buf, count);
269}
270
271
272
273#endif
274/* end */
diff --git a/drivers/scsi/pcmcia/nsp_message.c b/drivers/scsi/pcmcia/nsp_message.c
new file mode 100644
index 000000000000..d7057737ff34
--- /dev/null
+++ b/drivers/scsi/pcmcia/nsp_message.c
@@ -0,0 +1,78 @@
1/*==========================================================================
2 NinjaSCSI-3 message handler
3 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
4
5 This software may be used and distributed according to the terms of
6 the GNU General Public License.
7 */
8
9/* $Id: nsp_message.c,v 1.6 2003/07/26 14:21:09 elca Exp $ */
10
11static void nsp_message_in(Scsi_Cmnd *SCpnt)
12{
13 unsigned int base = SCpnt->device->host->io_port;
14 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
15 unsigned char data_reg, control_reg;
16 int ret, len;
17
18 /*
19 * XXX: NSP QUIRK
20 * NSP invoke interrupts only in the case of scsi phase changes,
21 * therefore we should poll the scsi phase here to catch
22 * the next "msg in" if exists (no scsi phase changes).
23 */
24 ret = 16;
25 len = 0;
26
27 nsp_dbg(NSP_DEBUG_MSGINOCCUR, "msgin loop");
28 do {
29 /* read data */
30 data_reg = nsp_index_read(base, SCSIDATAIN);
31
32 /* assert ACK */
33 control_reg = nsp_index_read(base, SCSIBUSCTRL);
34 control_reg |= SCSI_ACK;
35 nsp_index_write(base, SCSIBUSCTRL, control_reg);
36 nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>");
37
38 data->MsgBuffer[len] = data_reg; len++;
39
40 /* deassert ACK */
41 control_reg = nsp_index_read(base, SCSIBUSCTRL);
42 control_reg &= ~SCSI_ACK;
43 nsp_index_write(base, SCSIBUSCTRL, control_reg);
44
45 /* catch a next signal */
46 ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ);
47 } while (ret > 0 && MSGBUF_SIZE > len);
48
49 data->MsgLen = len;
50
51}
52
53static void nsp_message_out(Scsi_Cmnd *SCpnt)
54{
55 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
56 int ret = 1;
57 int len = data->MsgLen;
58
59 /*
60 * XXX: NSP QUIRK
61 * NSP invoke interrupts only in the case of scsi phase changes,
62 * therefore we should poll the scsi phase here to catch
63 * the next "msg out" if exists (no scsi phase changes).
64 */
65
66 nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop");
67 do {
68 if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) {
69 nsp_msg(KERN_DEBUG, "msgout: xfer short");
70 }
71
72 /* catch a next signal */
73 ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, BUSMON_REQ);
74 } while (ret > 0 && len-- > 0);
75
76}
77
78/* end */
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
new file mode 100644
index 000000000000..4766bcd63692
--- /dev/null
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -0,0 +1,425 @@
1/*======================================================================
2
3 A driver for the Qlogic SCSI card
4
5 qlogic_cs.c 1.79 2000/06/12 21:27:26
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/kernel.h>
37#include <linux/sched.h>
38#include <linux/slab.h>
39#include <linux/string.h>
40#include <linux/ioport.h>
41#include <asm/io.h>
42#include <scsi/scsi.h>
43#include <linux/major.h>
44#include <linux/blkdev.h>
45#include <scsi/scsi_ioctl.h>
46#include <linux/interrupt.h>
47
48#include "scsi.h"
49#include <scsi/scsi_host.h>
50#include "../qlogicfas408.h"
51
52#include <pcmcia/version.h>
53#include <pcmcia/cs_types.h>
54#include <pcmcia/cs.h>
55#include <pcmcia/cistpl.h>
56#include <pcmcia/ds.h>
57#include <pcmcia/ciscode.h>
58
59/* Set the following to 2 to use normal interrupt (active high/totempole-
60 * tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
61 * drain
62 */
63#define INT_TYPE 0
64
65static char qlogic_name[] = "qlogic_cs";
66
67#ifdef PCMCIA_DEBUG
68static int pc_debug = PCMCIA_DEBUG;
69module_param(pc_debug, int, 0644);
70#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
71static char *version = "qlogic_cs.c 1.79-ac 2002/10/26 (David Hinds)";
72#else
73#define DEBUG(n, args...)
74#endif
75
76static Scsi_Host_Template qlogicfas_driver_template = {
77 .module = THIS_MODULE,
78 .name = qlogic_name,
79 .proc_name = qlogic_name,
80 .info = qlogicfas408_info,
81 .queuecommand = qlogicfas408_queuecommand,
82 .eh_abort_handler = qlogicfas408_abort,
83 .eh_bus_reset_handler = qlogicfas408_bus_reset,
84 .eh_device_reset_handler= qlogicfas408_device_reset,
85 .eh_host_reset_handler = qlogicfas408_host_reset,
86 .bios_param = qlogicfas408_biosparam,
87 .can_queue = 1,
88 .this_id = -1,
89 .sg_tablesize = SG_ALL,
90 .cmd_per_lun = 1,
91 .use_clustering = DISABLE_CLUSTERING,
92};
93
94/*====================================================================*/
95
96typedef struct scsi_info_t {
97 dev_link_t link;
98 dev_node_t node;
99 struct Scsi_Host *host;
100 unsigned short manf_id;
101} scsi_info_t;
102
103static void qlogic_release(dev_link_t *link);
104static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
105
106static dev_link_t *qlogic_attach(void);
107static void qlogic_detach(dev_link_t *);
108
109
110static dev_link_t *dev_list = NULL;
111
112static dev_info_t dev_info = "qlogic_cs";
113
114static struct Scsi_Host *qlogic_detect(Scsi_Host_Template *host,
115 dev_link_t *link, int qbase, int qlirq)
116{
117 int qltyp; /* type of chip */
118 int qinitid;
119 struct Scsi_Host *shost; /* registered host structure */
120 struct qlogicfas408_priv *priv;
121
122 qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE);
123 qinitid = host->this_id;
124 if (qinitid < 0)
125 qinitid = 7; /* if no ID, use 7 */
126
127 qlogicfas408_setup(qbase, qinitid, INT_TYPE);
128
129 host->name = qlogic_name;
130 shost = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv));
131 if (!shost)
132 goto err;
133 shost->io_port = qbase;
134 shost->n_io_port = 16;
135 shost->dma_channel = -1;
136 if (qlirq != -1)
137 shost->irq = qlirq;
138
139 priv = get_priv_by_host(shost);
140 priv->qlirq = qlirq;
141 priv->qbase = qbase;
142 priv->qinitid = qinitid;
143 priv->shost = shost;
144 priv->int_type = INT_TYPE;
145
146 if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogic_name, shost))
147 goto free_scsi_host;
148
149 sprintf(priv->qinfo,
150 "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d",
151 qltyp, qbase, qlirq, QL_TURBO_PDMA);
152
153 if (scsi_add_host(shost, NULL))
154 goto free_interrupt;
155
156 scsi_scan_host(shost);
157
158 return shost;
159
160free_interrupt:
161 free_irq(qlirq, shost);
162
163free_scsi_host:
164 scsi_host_put(shost);
165
166err:
167 return NULL;
168}
169static dev_link_t *qlogic_attach(void)
170{
171 scsi_info_t *info;
172 client_reg_t client_reg;
173 dev_link_t *link;
174 int ret;
175
176 DEBUG(0, "qlogic_attach()\n");
177
178 /* Create new SCSI device */
179 info = kmalloc(sizeof(*info), GFP_KERNEL);
180 if (!info)
181 return NULL;
182 memset(info, 0, sizeof(*info));
183 link = &info->link;
184 link->priv = info;
185 link->io.NumPorts1 = 16;
186 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
187 link->io.IOAddrLines = 10;
188 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
189 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
190 link->conf.Attributes = CONF_ENABLE_IRQ;
191 link->conf.Vcc = 50;
192 link->conf.IntType = INT_MEMORY_AND_IO;
193 link->conf.Present = PRESENT_OPTION;
194
195 /* Register with Card Services */
196 link->next = dev_list;
197 dev_list = link;
198 client_reg.dev_info = &dev_info;
199 client_reg.event_handler = &qlogic_event;
200 client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
201 client_reg.Version = 0x0210;
202 client_reg.event_callback_args.client_data = link;
203 ret = pcmcia_register_client(&link->handle, &client_reg);
204 if (ret != 0) {
205 cs_error(link->handle, RegisterClient, ret);
206 qlogic_detach(link);
207 return NULL;
208 }
209
210 return link;
211} /* qlogic_attach */
212
213/*====================================================================*/
214
215static void qlogic_detach(dev_link_t * link)
216{
217 dev_link_t **linkp;
218
219 DEBUG(0, "qlogic_detach(0x%p)\n", link);
220
221 /* Locate device structure */
222 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
223 if (*linkp == link)
224 break;
225 if (*linkp == NULL)
226 return;
227
228 if (link->state & DEV_CONFIG)
229 qlogic_release(link);
230
231 if (link->handle)
232 pcmcia_deregister_client(link->handle);
233
234 /* Unlink device structure, free bits */
235 *linkp = link->next;
236 kfree(link->priv);
237
238} /* qlogic_detach */
239
240/*====================================================================*/
241
242#define CS_CHECK(fn, ret) \
243do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
244
245static void qlogic_config(dev_link_t * link)
246{
247 client_handle_t handle = link->handle;
248 scsi_info_t *info = link->priv;
249 tuple_t tuple;
250 cisparse_t parse;
251 int i, last_ret, last_fn;
252 unsigned short tuple_data[32];
253 struct Scsi_Host *host;
254
255 DEBUG(0, "qlogic_config(0x%p)\n", link);
256
257 tuple.TupleData = (cisdata_t *) tuple_data;
258 tuple.TupleDataMax = 64;
259 tuple.TupleOffset = 0;
260 tuple.DesiredTuple = CISTPL_CONFIG;
261 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
262 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
263 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
264 link->conf.ConfigBase = parse.config.base;
265
266 tuple.DesiredTuple = CISTPL_MANFID;
267 if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
268 info->manf_id = le16_to_cpu(tuple.TupleData[0]);
269
270 /* Configure card */
271 link->state |= DEV_CONFIG;
272
273 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
274 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
275 while (1) {
276 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
277 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
278 goto next_entry;
279 link->conf.ConfigIndex = parse.cftable_entry.index;
280 link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
281 link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
282 if (link->io.BasePort1 != 0) {
283 i = pcmcia_request_io(handle, &link->io);
284 if (i == CS_SUCCESS)
285 break;
286 }
287 next_entry:
288 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
289 }
290
291 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
292 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
293
294 if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
295 /* set ATAcmd */
296 outb(0xb4, link->io.BasePort1 + 0xd);
297 outb(0x24, link->io.BasePort1 + 0x9);
298 outb(0x04, link->io.BasePort1 + 0xd);
299 }
300
301 /* The KXL-810AN has a bigger IO port window */
302 if (link->io.NumPorts1 == 32)
303 host = qlogic_detect(&qlogicfas_driver_template, link,
304 link->io.BasePort1 + 16, link->irq.AssignedIRQ);
305 else
306 host = qlogic_detect(&qlogicfas_driver_template, link,
307 link->io.BasePort1, link->irq.AssignedIRQ);
308
309 if (!host) {
310 printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
311 goto out;
312 }
313
314 sprintf(info->node.dev_name, "scsi%d", host->host_no);
315 link->dev = &info->node;
316 info->host = host;
317
318out:
319 link->state &= ~DEV_CONFIG_PENDING;
320 return;
321
322cs_failed:
323 cs_error(link->handle, last_fn, last_ret);
324 link->dev = NULL;
325 pcmcia_release_configuration(link->handle);
326 pcmcia_release_io(link->handle, &link->io);
327 pcmcia_release_irq(link->handle, &link->irq);
328 link->state &= ~DEV_CONFIG;
329 return;
330
331} /* qlogic_config */
332
333/*====================================================================*/
334
335static void qlogic_release(dev_link_t *link)
336{
337 scsi_info_t *info = link->priv;
338
339 DEBUG(0, "qlogic_release(0x%p)\n", link);
340
341 scsi_remove_host(info->host);
342 link->dev = NULL;
343
344 free_irq(link->irq.AssignedIRQ, info->host);
345
346 pcmcia_release_configuration(link->handle);
347 pcmcia_release_io(link->handle, &link->io);
348 pcmcia_release_irq(link->handle, &link->irq);
349
350 scsi_host_put(info->host);
351
352 link->state &= ~DEV_CONFIG;
353}
354
355/*====================================================================*/
356
357static int qlogic_event(event_t event, int priority, event_callback_args_t * args)
358{
359 dev_link_t *link = args->client_data;
360
361 DEBUG(1, "qlogic_event(0x%06x)\n", event);
362
363 switch (event) {
364 case CS_EVENT_CARD_REMOVAL:
365 link->state &= ~DEV_PRESENT;
366 if (link->state & DEV_CONFIG)
367 qlogic_release(link);
368 break;
369 case CS_EVENT_CARD_INSERTION:
370 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
371 qlogic_config(link);
372 break;
373 case CS_EVENT_PM_SUSPEND:
374 link->state |= DEV_SUSPEND;
375 /* Fall through... */
376 case CS_EVENT_RESET_PHYSICAL:
377 if (link->state & DEV_CONFIG)
378 pcmcia_release_configuration(link->handle);
379 break;
380 case CS_EVENT_PM_RESUME:
381 link->state &= ~DEV_SUSPEND;
382 /* Fall through... */
383 case CS_EVENT_CARD_RESET:
384 if (link->state & DEV_CONFIG) {
385 scsi_info_t *info = link->priv;
386 pcmcia_request_configuration(link->handle, &link->conf);
387 if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
388 outb(0x80, link->io.BasePort1 + 0xd);
389 outb(0x24, link->io.BasePort1 + 0x9);
390 outb(0x04, link->io.BasePort1 + 0xd);
391 }
392 /* Ugggglllyyyy!!! */
393 qlogicfas408_bus_reset(NULL);
394 }
395 break;
396 }
397 return 0;
398} /* qlogic_event */
399
400
401static struct pcmcia_driver qlogic_cs_driver = {
402 .owner = THIS_MODULE,
403 .drv = {
404 .name = "qlogic_cs",
405 },
406 .attach = qlogic_attach,
407 .detach = qlogic_detach,
408};
409
410static int __init init_qlogic_cs(void)
411{
412 return pcmcia_register_driver(&qlogic_cs_driver);
413}
414
415static void __exit exit_qlogic_cs(void)
416{
417 pcmcia_unregister_driver(&qlogic_cs_driver);
418 BUG_ON(dev_list != NULL);
419}
420
421MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
422MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers");
423MODULE_LICENSE("GPL");
424module_init(init_qlogic_cs);
425module_exit(exit_qlogic_cs);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
new file mode 100644
index 000000000000..8457d0d7748a
--- /dev/null
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -0,0 +1,1022 @@
1/*
2* sym53c500_cs.c Bob Tracy (rct@frus.com)
3*
4* A rewrite of the pcmcia-cs add-on driver for newer (circa 1997)
5* New Media Bus Toaster PCMCIA SCSI cards using the Symbios Logic
6* 53c500 controller: intended for use with 2.6 and later kernels.
7* The pcmcia-cs add-on version of this driver is not supported
8* beyond 2.4. It consisted of three files with history/copyright
9* information as follows:
10*
11* SYM53C500.h
12* Bob Tracy (rct@frus.com)
13* Original by Tom Corner (tcorner@via.at).
14* Adapted from NCR53c406a.h which is Copyrighted (C) 1994
15* Normunds Saumanis (normunds@rx.tech.swh.lv)
16*
17* SYM53C500.c
18* Bob Tracy (rct@frus.com)
19* Original driver by Tom Corner (tcorner@via.at) was adapted
20* from NCR53c406a.c which is Copyrighted (C) 1994, 1995, 1996
21* Normunds Saumanis (normunds@fi.ibm.com)
22*
23* sym53c500.c
24* Bob Tracy (rct@frus.com)
25* Original by Tom Corner (tcorner@via.at) was adapted from a
26* driver for the Qlogic SCSI card written by
27* David Hinds (dhinds@allegro.stanford.edu).
28*
29* This program is free software; you can redistribute it and/or modify it
30* under the terms of the GNU General Public License as published by the
31* Free Software Foundation; either version 2, or (at your option) any
32* later version.
33*
34* This program is distributed in the hope that it will be useful, but
35* WITHOUT ANY WARRANTY; without even the implied warranty of
36* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37* General Public License for more details.
38*/
39
40#define SYM53C500_DEBUG 0
41#define VERBOSE_SYM53C500_DEBUG 0
42
43/*
44* Set this to 0 if you encounter kernel lockups while transferring
45* data in PIO mode. Note this can be changed via "sysfs".
46*/
47#define USE_FAST_PIO 1
48
49/* =============== End of user configurable parameters ============== */
50
51#include <linux/module.h>
52#include <linux/moduleparam.h>
53#include <linux/errno.h>
54#include <linux/init.h>
55#include <linux/interrupt.h>
56#include <linux/kernel.h>
57#include <linux/sched.h>
58#include <linux/slab.h>
59#include <linux/string.h>
60#include <linux/ioport.h>
61#include <linux/blkdev.h>
62#include <linux/spinlock.h>
63#include <linux/bitops.h>
64
65#include <asm/io.h>
66#include <asm/dma.h>
67#include <asm/irq.h>
68
69#include <scsi/scsi_ioctl.h>
70#include <scsi/scsi_cmnd.h>
71#include <scsi/scsi_device.h>
72#include <scsi/scsi.h>
73#include <scsi/scsi_host.h>
74
75#include <pcmcia/cs_types.h>
76#include <pcmcia/cs.h>
77#include <pcmcia/cistpl.h>
78#include <pcmcia/ds.h>
79#include <pcmcia/ciscode.h>
80
81/* ================================================================== */
82
83#ifdef PCMCIA_DEBUG
84static int pc_debug = PCMCIA_DEBUG;
85module_param(pc_debug, int, 0);
86#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
87static char *version =
88"sym53c500_cs.c 0.9c 2004/10/27 (Bob Tracy)";
89#else
90#define DEBUG(n, args...)
91#endif
92
93/* ================================================================== */
94
95#define SYNC_MODE 0 /* Synchronous transfer mode */
96
97/* Default configuration */
98#define C1_IMG 0x07 /* ID=7 */
99#define C2_IMG 0x48 /* FE SCSI2 */
100#define C3_IMG 0x20 /* CDB */
101#define C4_IMG 0x04 /* ANE */
102#define C5_IMG 0xa4 /* ? changed from b6= AA PI SIE POL */
103#define C7_IMG 0x80 /* added for SYM53C500 t. corner */
104
105/* Hardware Registers: offsets from io_port (base) */
106
107/* Control Register Set 0 */
108#define TC_LSB 0x00 /* transfer counter lsb */
109#define TC_MSB 0x01 /* transfer counter msb */
110#define SCSI_FIFO 0x02 /* scsi fifo register */
111#define CMD_REG 0x03 /* command register */
112#define STAT_REG 0x04 /* status register */
113#define DEST_ID 0x04 /* selection/reselection bus id */
114#define INT_REG 0x05 /* interrupt status register */
115#define SRTIMOUT 0x05 /* select/reselect timeout reg */
116#define SEQ_REG 0x06 /* sequence step register */
117#define SYNCPRD 0x06 /* synchronous transfer period */
118#define FIFO_FLAGS 0x07 /* indicates # of bytes in fifo */
119#define SYNCOFF 0x07 /* synchronous offset register */
120#define CONFIG1 0x08 /* configuration register */
121#define CLKCONV 0x09 /* clock conversion register */
122/* #define TESTREG 0x0A */ /* test mode register */
123#define CONFIG2 0x0B /* configuration 2 register */
124#define CONFIG3 0x0C /* configuration 3 register */
125#define CONFIG4 0x0D /* configuration 4 register */
126#define TC_HIGH 0x0E /* transfer counter high */
127/* #define FIFO_BOTTOM 0x0F */ /* reserve FIFO byte register */
128
129/* Control Register Set 1 */
130/* #define JUMPER_SENSE 0x00 */ /* jumper sense port reg (r/w) */
131/* #define SRAM_PTR 0x01 */ /* SRAM address pointer reg (r/w) */
132/* #define SRAM_DATA 0x02 */ /* SRAM data register (r/w) */
133#define PIO_FIFO 0x04 /* PIO FIFO registers (r/w) */
134/* #define PIO_FIFO1 0x05 */ /* */
135/* #define PIO_FIFO2 0x06 */ /* */
136/* #define PIO_FIFO3 0x07 */ /* */
137#define PIO_STATUS 0x08 /* PIO status (r/w) */
138/* #define ATA_CMD 0x09 */ /* ATA command/status reg (r/w) */
139/* #define ATA_ERR 0x0A */ /* ATA features/error reg (r/w) */
140#define PIO_FLAG 0x0B /* PIO flag interrupt enable (r/w) */
141#define CONFIG5 0x09 /* configuration 5 register */
142/* #define SIGNATURE 0x0E */ /* signature register (r) */
143/* #define CONFIG6 0x0F */ /* configuration 6 register (r) */
144#define CONFIG7 0x0d
145
146/* select register set 0 */
147#define REG0(x) (outb(C4_IMG, (x) + CONFIG4))
148/* select register set 1 */
149#define REG1(x) outb(C7_IMG, (x) + CONFIG7); outb(C5_IMG, (x) + CONFIG5)
150
151#if SYM53C500_DEBUG
152#define DEB(x) x
153#else
154#define DEB(x)
155#endif
156
157#if VERBOSE_SYM53C500_DEBUG
158#define VDEB(x) x
159#else
160#define VDEB(x)
161#endif
162
163#define LOAD_DMA_COUNT(x, count) \
164 outb(count & 0xff, (x) + TC_LSB); \
165 outb((count >> 8) & 0xff, (x) + TC_MSB); \
166 outb((count >> 16) & 0xff, (x) + TC_HIGH);
167
168/* Chip commands */
169#define DMA_OP 0x80
170
171#define SCSI_NOP 0x00
172#define FLUSH_FIFO 0x01
173#define CHIP_RESET 0x02
174#define SCSI_RESET 0x03
175#define RESELECT 0x40
176#define SELECT_NO_ATN 0x41
177#define SELECT_ATN 0x42
178#define SELECT_ATN_STOP 0x43
179#define ENABLE_SEL 0x44
180#define DISABLE_SEL 0x45
181#define SELECT_ATN3 0x46
182#define RESELECT3 0x47
183#define TRANSFER_INFO 0x10
184#define INIT_CMD_COMPLETE 0x11
185#define MSG_ACCEPT 0x12
186#define TRANSFER_PAD 0x18
187#define SET_ATN 0x1a
188#define RESET_ATN 0x1b
189#define SEND_MSG 0x20
190#define SEND_STATUS 0x21
191#define SEND_DATA 0x22
192#define DISCONN_SEQ 0x23
193#define TERMINATE_SEQ 0x24
194#define TARG_CMD_COMPLETE 0x25
195#define DISCONN 0x27
196#define RECV_MSG 0x28
197#define RECV_CMD 0x29
198#define RECV_DATA 0x2a
199#define RECV_CMD_SEQ 0x2b
200#define TARGET_ABORT_DMA 0x04
201
202/* ================================================================== */
203
204struct scsi_info_t {
205 dev_link_t link;
206 dev_node_t node;
207 struct Scsi_Host *host;
208 unsigned short manf_id;
209};
210
211/*
212* Repository for per-instance host data.
213*/
214struct sym53c500_data {
215 struct scsi_cmnd *current_SC;
216 int fast_pio;
217};
218
219enum Phase {
220 idle,
221 data_out,
222 data_in,
223 command_ph,
224 status_ph,
225 message_out,
226 message_in
227};
228
229/* ================================================================== */
230
231/*
232* Global (within this module) variables other than
233* sym53c500_driver_template (the scsi_host_template).
234*/
235static dev_link_t *dev_list;
236static dev_info_t dev_info = "sym53c500_cs";
237
238/* ================================================================== */
239
240static void
241chip_init(int io_port)
242{
243 REG1(io_port);
244 outb(0x01, io_port + PIO_STATUS);
245 outb(0x00, io_port + PIO_FLAG);
246
247 outb(C4_IMG, io_port + CONFIG4); /* REG0(io_port); */
248 outb(C3_IMG, io_port + CONFIG3);
249 outb(C2_IMG, io_port + CONFIG2);
250 outb(C1_IMG, io_port + CONFIG1);
251
252 outb(0x05, io_port + CLKCONV); /* clock conversion factor */
253 outb(0x9C, io_port + SRTIMOUT); /* Selection timeout */
254 outb(0x05, io_port + SYNCPRD); /* Synchronous transfer period */
255 outb(SYNC_MODE, io_port + SYNCOFF); /* synchronous mode */
256}
257
258static void
259SYM53C500_int_host_reset(int io_port)
260{
261 outb(C4_IMG, io_port + CONFIG4); /* REG0(io_port); */
262 outb(CHIP_RESET, io_port + CMD_REG);
263 outb(SCSI_NOP, io_port + CMD_REG); /* required after reset */
264 outb(SCSI_RESET, io_port + CMD_REG);
265 chip_init(io_port);
266}
267
268static __inline__ int
269SYM53C500_pio_read(int fast_pio, int base, unsigned char *request, unsigned int reqlen)
270{
271 int i;
272 int len; /* current scsi fifo size */
273
274 REG1(base);
275 while (reqlen) {
276 i = inb(base + PIO_STATUS);
277 /* VDEB(printk("pio_status=%x\n", i)); */
278 if (i & 0x80)
279 return 0;
280
281 switch (i & 0x1e) {
282 default:
283 case 0x10: /* fifo empty */
284 len = 0;
285 break;
286 case 0x0:
287 len = 1;
288 break;
289 case 0x8: /* fifo 1/3 full */
290 len = 42;
291 break;
292 case 0xc: /* fifo 2/3 full */
293 len = 84;
294 break;
295 case 0xe: /* fifo full */
296 len = 128;
297 break;
298 }
299
300 if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occurred */
301 return 0;
302 }
303
304 if (len) {
305 if (len > reqlen)
306 len = reqlen;
307
308 if (fast_pio && len > 3) {
309 insl(base + PIO_FIFO, request, len >> 2);
310 request += len & 0xfc;
311 reqlen -= len & 0xfc;
312 } else {
313 while (len--) {
314 *request++ = inb(base + PIO_FIFO);
315 reqlen--;
316 }
317 }
318 }
319 }
320 return 0;
321}
322
323static __inline__ int
324SYM53C500_pio_write(int fast_pio, int base, unsigned char *request, unsigned int reqlen)
325{
326 int i = 0;
327 int len; /* current scsi fifo size */
328
329 REG1(base);
330 while (reqlen && !(i & 0x40)) {
331 i = inb(base + PIO_STATUS);
332 /* VDEB(printk("pio_status=%x\n", i)); */
333 if (i & 0x80) /* error */
334 return 0;
335
336 switch (i & 0x1e) {
337 case 0x10:
338 len = 128;
339 break;
340 case 0x0:
341 len = 84;
342 break;
343 case 0x8:
344 len = 42;
345 break;
346 case 0xc:
347 len = 1;
348 break;
349 default:
350 case 0xe:
351 len = 0;
352 break;
353 }
354
355 if (len) {
356 if (len > reqlen)
357 len = reqlen;
358
359 if (fast_pio && len > 3) {
360 outsl(base + PIO_FIFO, request, len >> 2);
361 request += len & 0xfc;
362 reqlen -= len & 0xfc;
363 } else {
364 while (len--) {
365 outb(*request++, base + PIO_FIFO);
366 reqlen--;
367 }
368 }
369 }
370 }
371 return 0;
372}
373
374static irqreturn_t
375SYM53C500_intr(int irq, void *dev_id, struct pt_regs *regs)
376{
377 unsigned long flags;
378 struct Scsi_Host *dev = dev_id;
379 DEB(unsigned char fifo_size;)
380 DEB(unsigned char seq_reg;)
381 unsigned char status, int_reg;
382 unsigned char pio_status;
383 struct scatterlist *sglist;
384 unsigned int sgcount;
385 int port_base = dev->io_port;
386 struct sym53c500_data *data =
387 (struct sym53c500_data *)dev->hostdata;
388 struct scsi_cmnd *curSC = data->current_SC;
389 int fast_pio = data->fast_pio;
390
391 spin_lock_irqsave(dev->host_lock, flags);
392
393 VDEB(printk("SYM53C500_intr called\n"));
394
395 REG1(port_base);
396 pio_status = inb(port_base + PIO_STATUS);
397 REG0(port_base);
398 status = inb(port_base + STAT_REG);
399 DEB(seq_reg = inb(port_base + SEQ_REG));
400 int_reg = inb(port_base + INT_REG);
401 DEB(fifo_size = inb(port_base + FIFO_FLAGS) & 0x1f);
402
403#if SYM53C500_DEBUG
404 printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x",
405 status, seq_reg, int_reg, fifo_size);
406 printk(", pio=%02x\n", pio_status);
407#endif /* SYM53C500_DEBUG */
408
409 if (int_reg & 0x80) { /* SCSI reset intr */
410 DEB(printk("SYM53C500: reset intr received\n"));
411 curSC->result = DID_RESET << 16;
412 goto idle_out;
413 }
414
415 if (pio_status & 0x80) {
416 printk("SYM53C500: Warning: PIO error!\n");
417 curSC->result = DID_ERROR << 16;
418 goto idle_out;
419 }
420
421 if (status & 0x20) { /* Parity error */
422 printk("SYM53C500: Warning: parity error!\n");
423 curSC->result = DID_PARITY << 16;
424 goto idle_out;
425 }
426
427 if (status & 0x40) { /* Gross error */
428 printk("SYM53C500: Warning: gross error!\n");
429 curSC->result = DID_ERROR << 16;
430 goto idle_out;
431 }
432
433 if (int_reg & 0x20) { /* Disconnect */
434 DEB(printk("SYM53C500: disconnect intr received\n"));
435 if (curSC->SCp.phase != message_in) { /* Unexpected disconnect */
436 curSC->result = DID_NO_CONNECT << 16;
437 } else { /* Command complete, return status and message */
438 curSC->result = (curSC->SCp.Status & 0xff)
439 | ((curSC->SCp.Message & 0xff) << 8) | (DID_OK << 16);
440 }
441 goto idle_out;
442 }
443
444 switch (status & 0x07) { /* scsi phase */
445 case 0x00: /* DATA-OUT */
446 if (int_reg & 0x10) { /* Target requesting info transfer */
447 curSC->SCp.phase = data_out;
448 VDEB(printk("SYM53C500: Data-Out phase\n"));
449 outb(FLUSH_FIFO, port_base + CMD_REG);
450 LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */
451 outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
452 if (!curSC->use_sg) /* Don't use scatter-gather */
453 SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
454 else { /* use scatter-gather */
455 sgcount = curSC->use_sg;
456 sglist = curSC->request_buffer;
457 while (sgcount--) {
458 SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
459 sglist++;
460 }
461 }
462 REG0(port_base);
463 }
464 break;
465
466 case 0x01: /* DATA-IN */
467 if (int_reg & 0x10) { /* Target requesting info transfer */
468 curSC->SCp.phase = data_in;
469 VDEB(printk("SYM53C500: Data-In phase\n"));
470 outb(FLUSH_FIFO, port_base + CMD_REG);
471 LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */
472 outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
473 if (!curSC->use_sg) /* Don't use scatter-gather */
474 SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
475 else { /* Use scatter-gather */
476 sgcount = curSC->use_sg;
477 sglist = curSC->request_buffer;
478 while (sgcount--) {
479 SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
480 sglist++;
481 }
482 }
483 REG0(port_base);
484 }
485 break;
486
487 case 0x02: /* COMMAND */
488 curSC->SCp.phase = command_ph;
489 printk("SYM53C500: Warning: Unknown interrupt occurred in command phase!\n");
490 break;
491
492 case 0x03: /* STATUS */
493 curSC->SCp.phase = status_ph;
494 VDEB(printk("SYM53C500: Status phase\n"));
495 outb(FLUSH_FIFO, port_base + CMD_REG);
496 outb(INIT_CMD_COMPLETE, port_base + CMD_REG);
497 break;
498
499 case 0x04: /* Reserved */
500 case 0x05: /* Reserved */
501 printk("SYM53C500: WARNING: Reserved phase!!!\n");
502 break;
503
504 case 0x06: /* MESSAGE-OUT */
505 DEB(printk("SYM53C500: Message-Out phase\n"));
506 curSC->SCp.phase = message_out;
507 outb(SET_ATN, port_base + CMD_REG); /* Reject the message */
508 outb(MSG_ACCEPT, port_base + CMD_REG);
509 break;
510
511 case 0x07: /* MESSAGE-IN */
512 VDEB(printk("SYM53C500: Message-In phase\n"));
513 curSC->SCp.phase = message_in;
514
515 curSC->SCp.Status = inb(port_base + SCSI_FIFO);
516 curSC->SCp.Message = inb(port_base + SCSI_FIFO);
517
518 VDEB(printk("SCSI FIFO size=%d\n", inb(port_base + FIFO_FLAGS) & 0x1f));
519 DEB(printk("Status = %02x Message = %02x\n", curSC->SCp.Status, curSC->SCp.Message));
520
521 if (curSC->SCp.Message == SAVE_POINTERS || curSC->SCp.Message == DISCONNECT) {
522 outb(SET_ATN, port_base + CMD_REG); /* Reject message */
523 DEB(printk("Discarding SAVE_POINTERS message\n"));
524 }
525 outb(MSG_ACCEPT, port_base + CMD_REG);
526 break;
527 }
528out:
529 spin_unlock_irqrestore(dev->host_lock, flags);
530 return IRQ_HANDLED;
531
532idle_out:
533 curSC->SCp.phase = idle;
534 curSC->scsi_done(curSC);
535 goto out;
536}
537
538static void
539SYM53C500_release(dev_link_t *link)
540{
541 struct scsi_info_t *info = link->priv;
542 struct Scsi_Host *shost = info->host;
543
544 DEBUG(0, "SYM53C500_release(0x%p)\n", link);
545
546 /*
547 * Do this before releasing/freeing resources.
548 */
549 scsi_remove_host(shost);
550
551 /*
552 * Interrupts getting hosed on card removal. Try
553 * the following code, mostly from qlogicfas.c.
554 */
555 if (shost->irq)
556 free_irq(shost->irq, shost);
557 if (shost->dma_channel != 0xff)
558 free_dma(shost->dma_channel);
559 if (shost->io_port && shost->n_io_port)
560 release_region(shost->io_port, shost->n_io_port);
561
562 link->dev = NULL;
563
564 pcmcia_release_configuration(link->handle);
565 pcmcia_release_io(link->handle, &link->io);
566 pcmcia_release_irq(link->handle, &link->irq);
567
568 link->state &= ~DEV_CONFIG;
569
570 scsi_host_put(shost);
571} /* SYM53C500_release */
572
573static const char*
574SYM53C500_info(struct Scsi_Host *SChost)
575{
576 static char info_msg[256];
577 struct sym53c500_data *data =
578 (struct sym53c500_data *)SChost->hostdata;
579
580 DEB(printk("SYM53C500_info called\n"));
581 (void)snprintf(info_msg, sizeof(info_msg),
582 "SYM53C500 at 0x%lx, IRQ %d, %s PIO mode.",
583 SChost->io_port, SChost->irq, data->fast_pio ? "fast" : "slow");
584 return (info_msg);
585}
586
587static int
588SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
589{
590 int i;
591 int port_base = SCpnt->device->host->io_port;
592 struct sym53c500_data *data =
593 (struct sym53c500_data *)SCpnt->device->host->hostdata;
594
595 VDEB(printk("SYM53C500_queue called\n"));
596
597 DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n",
598 SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id,
599 SCpnt->device->lun, SCpnt->request_bufflen));
600
601 VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
602 printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i]));
603 VDEB(printk("\n"));
604
605 data->current_SC = SCpnt;
606 data->current_SC->scsi_done = done;
607 data->current_SC->SCp.phase = command_ph;
608 data->current_SC->SCp.Status = 0;
609 data->current_SC->SCp.Message = 0;
610
611 /* We are locked here already by the mid layer */
612 REG0(port_base);
613 outb(SCpnt->device->id, port_base + DEST_ID); /* set destination */
614 outb(FLUSH_FIFO, port_base + CMD_REG); /* reset the fifos */
615
616 for (i = 0; i < SCpnt->cmd_len; i++) {
617 outb(SCpnt->cmnd[i], port_base + SCSI_FIFO);
618 }
619 outb(SELECT_NO_ATN, port_base + CMD_REG);
620
621 return 0;
622}
623
624static int
625SYM53C500_host_reset(struct scsi_cmnd *SCpnt)
626{
627 int port_base = SCpnt->device->host->io_port;
628
629 DEB(printk("SYM53C500_host_reset called\n"));
630 SYM53C500_int_host_reset(port_base);
631
632 return SUCCESS;
633}
634
635static int
636SYM53C500_biosparm(struct scsi_device *disk,
637 struct block_device *dev,
638 sector_t capacity, int *info_array)
639{
640 int size;
641
642 DEB(printk("SYM53C500_biosparm called\n"));
643
644 size = capacity;
645 info_array[0] = 64; /* heads */
646 info_array[1] = 32; /* sectors */
647 info_array[2] = size >> 11; /* cylinders */
648 if (info_array[2] > 1024) { /* big disk */
649 info_array[0] = 255;
650 info_array[1] = 63;
651 info_array[2] = size / (255 * 63);
652 }
653 return 0;
654}
655
656static ssize_t
657SYM53C500_show_pio(struct class_device *cdev, char *buf)
658{
659 struct Scsi_Host *SHp = class_to_shost(cdev);
660 struct sym53c500_data *data =
661 (struct sym53c500_data *)SHp->hostdata;
662
663 return snprintf(buf, 4, "%d\n", data->fast_pio);
664}
665
666static ssize_t
667SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
668{
669 int pio;
670 struct Scsi_Host *SHp = class_to_shost(cdev);
671 struct sym53c500_data *data =
672 (struct sym53c500_data *)SHp->hostdata;
673
674 pio = simple_strtoul(buf, NULL, 0);
675 if (pio == 0 || pio == 1) {
676 data->fast_pio = pio;
677 return count;
678 }
679 else
680 return -EINVAL;
681}
682
683/*
684* SCSI HBA device attributes we want to
685* make available via sysfs.
686*/
687static struct class_device_attribute SYM53C500_pio_attr = {
688 .attr = {
689 .name = "fast_pio",
690 .mode = (S_IRUGO | S_IWUSR),
691 },
692 .show = SYM53C500_show_pio,
693 .store = SYM53C500_store_pio,
694};
695
696static struct class_device_attribute *SYM53C500_shost_attrs[] = {
697 &SYM53C500_pio_attr,
698 NULL,
699};
700
701/*
702* scsi_host_template initializer
703*/
704static struct scsi_host_template sym53c500_driver_template = {
705 .module = THIS_MODULE,
706 .name = "SYM53C500",
707 .info = SYM53C500_info,
708 .queuecommand = SYM53C500_queue,
709 .eh_host_reset_handler = SYM53C500_host_reset,
710 .bios_param = SYM53C500_biosparm,
711 .proc_name = "SYM53C500",
712 .can_queue = 1,
713 .this_id = 7,
714 .sg_tablesize = 32,
715 .cmd_per_lun = 1,
716 .use_clustering = ENABLE_CLUSTERING,
717 .shost_attrs = SYM53C500_shost_attrs
718};
719
720#define CS_CHECK(fn, ret) \
721do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
722
723static void
724SYM53C500_config(dev_link_t *link)
725{
726 client_handle_t handle = link->handle;
727 struct scsi_info_t *info = link->priv;
728 tuple_t tuple;
729 cisparse_t parse;
730 int i, last_ret, last_fn;
731 int irq_level, port_base;
732 unsigned short tuple_data[32];
733 struct Scsi_Host *host;
734 struct scsi_host_template *tpnt = &sym53c500_driver_template;
735 struct sym53c500_data *data;
736
737 DEBUG(0, "SYM53C500_config(0x%p)\n", link);
738
739 tuple.TupleData = (cisdata_t *)tuple_data;
740 tuple.TupleDataMax = 64;
741 tuple.TupleOffset = 0;
742 tuple.DesiredTuple = CISTPL_CONFIG;
743 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
744 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
745 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
746 link->conf.ConfigBase = parse.config.base;
747
748 tuple.DesiredTuple = CISTPL_MANFID;
749 if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
750 (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
751 info->manf_id = le16_to_cpu(tuple.TupleData[0]);
752
753 /* Configure card */
754 link->state |= DEV_CONFIG;
755
756 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
757 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
758 while (1) {
759 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
760 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
761 goto next_entry;
762 link->conf.ConfigIndex = parse.cftable_entry.index;
763 link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
764 link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
765
766 if (link->io.BasePort1 != 0) {
767 i = pcmcia_request_io(handle, &link->io);
768 if (i == CS_SUCCESS)
769 break;
770 }
771next_entry:
772 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
773 }
774
775 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
776 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
777
778 /*
779 * That's the trouble with copying liberally from another driver.
780 * Some things probably aren't relevant, and I suspect this entire
781 * section dealing with manufacturer IDs can be scrapped. --rct
782 */
783 if ((info->manf_id == MANFID_MACNICA) ||
784 (info->manf_id == MANFID_PIONEER) ||
785 (info->manf_id == 0x0098)) {
786 /* set ATAcmd */
787 outb(0xb4, link->io.BasePort1 + 0xd);
788 outb(0x24, link->io.BasePort1 + 0x9);
789 outb(0x04, link->io.BasePort1 + 0xd);
790 }
791
792 /*
793 * irq_level == 0 implies tpnt->can_queue == 0, which
794 * is not supported in 2.6. Thus, only irq_level > 0
795 * will be allowed.
796 *
797 * Possible port_base values are as follows:
798 *
799 * 0x130, 0x230, 0x280, 0x290,
800 * 0x320, 0x330, 0x340, 0x350
801 */
802 port_base = link->io.BasePort1;
803 irq_level = link->irq.AssignedIRQ;
804
805 DEB(printk("SYM53C500: port_base=0x%x, irq=%d, fast_pio=%d\n",
806 port_base, irq_level, USE_FAST_PIO);)
807
808 chip_init(port_base);
809
810 host = scsi_host_alloc(tpnt, sizeof(struct sym53c500_data));
811 if (!host) {
812 printk("SYM53C500: Unable to register host, giving up.\n");
813 goto err_release;
814 }
815
816 data = (struct sym53c500_data *)host->hostdata;
817
818 if (irq_level > 0) {
819 if (request_irq(irq_level, SYM53C500_intr, SA_SHIRQ, "SYM53C500", host)) {
820 printk("SYM53C500: unable to allocate IRQ %d\n", irq_level);
821 goto err_free_scsi;
822 }
823 DEB(printk("SYM53C500: allocated IRQ %d\n", irq_level));
824 } else if (irq_level == 0) {
825 DEB(printk("SYM53C500: No interrupts detected\n"));
826 goto err_free_scsi;
827 } else {
828 DEB(printk("SYM53C500: Shouldn't get here!\n"));
829 goto err_free_scsi;
830 }
831
832 host->unique_id = port_base;
833 host->irq = irq_level;
834 host->io_port = port_base;
835 host->n_io_port = 0x10;
836 host->dma_channel = -1;
837
838 /*
839 * Note fast_pio is set to USE_FAST_PIO by
840 * default, but can be changed via "sysfs".
841 */
842 data->fast_pio = USE_FAST_PIO;
843
844 sprintf(info->node.dev_name, "scsi%d", host->host_no);
845 link->dev = &info->node;
846 info->host = host;
847
848 if (scsi_add_host(host, NULL))
849 goto err_free_irq;
850
851 scsi_scan_host(host);
852
853 goto out; /* SUCCESS */
854
855err_free_irq:
856 free_irq(irq_level, host);
857err_free_scsi:
858 scsi_host_put(host);
859err_release:
860 release_region(port_base, 0x10);
861 printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
862
863out:
864 link->state &= ~DEV_CONFIG_PENDING;
865 return;
866
867cs_failed:
868 cs_error(link->handle, last_fn, last_ret);
869 SYM53C500_release(link);
870 return;
871} /* SYM53C500_config */
872
873static int
874SYM53C500_event(event_t event, int priority, event_callback_args_t *args)
875{
876 dev_link_t *link = args->client_data;
877 struct scsi_info_t *info = link->priv;
878
879 DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
880
881 switch (event) {
882 case CS_EVENT_CARD_REMOVAL:
883 link->state &= ~DEV_PRESENT;
884 if (link->state & DEV_CONFIG)
885 SYM53C500_release(link);
886 break;
887 case CS_EVENT_CARD_INSERTION:
888 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
889 SYM53C500_config(link);
890 break;
891 case CS_EVENT_PM_SUSPEND:
892 link->state |= DEV_SUSPEND;
893 /* Fall through... */
894 case CS_EVENT_RESET_PHYSICAL:
895 if (link->state & DEV_CONFIG)
896 pcmcia_release_configuration(link->handle);
897 break;
898 case CS_EVENT_PM_RESUME:
899 link->state &= ~DEV_SUSPEND;
900 /* Fall through... */
901 case CS_EVENT_CARD_RESET:
902 if (link->state & DEV_CONFIG) {
903 pcmcia_request_configuration(link->handle, &link->conf);
904 /* See earlier comment about manufacturer IDs. */
905 if ((info->manf_id == MANFID_MACNICA) ||
906 (info->manf_id == MANFID_PIONEER) ||
907 (info->manf_id == 0x0098)) {
908 outb(0x80, link->io.BasePort1 + 0xd);
909 outb(0x24, link->io.BasePort1 + 0x9);
910 outb(0x04, link->io.BasePort1 + 0xd);
911 }
912 /*
913 * If things don't work after a "resume",
914 * this is a good place to start looking.
915 */
916 SYM53C500_int_host_reset(link->io.BasePort1);
917 }
918 break;
919 }
920 return 0;
921} /* SYM53C500_event */
922
923static void
924SYM53C500_detach(dev_link_t *link)
925{
926 dev_link_t **linkp;
927
928 DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
929
930 /* Locate device structure */
931 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
932 if (*linkp == link)
933 break;
934 if (*linkp == NULL)
935 return;
936
937 if (link->state & DEV_CONFIG)
938 SYM53C500_release(link);
939
940 if (link->handle)
941 pcmcia_deregister_client(link->handle);
942
943 /* Unlink device structure, free bits. */
944 *linkp = link->next;
945 kfree(link->priv);
946 link->priv = NULL;
947} /* SYM53C500_detach */
948
949static dev_link_t *
950SYM53C500_attach(void)
951{
952 struct scsi_info_t *info;
953 client_reg_t client_reg;
954 dev_link_t *link;
955 int ret;
956
957 DEBUG(0, "SYM53C500_attach()\n");
958
959 /* Create new SCSI device */
960 info = kmalloc(sizeof(*info), GFP_KERNEL);
961 if (!info)
962 return NULL;
963 memset(info, 0, sizeof(*info));
964 link = &info->link;
965 link->priv = info;
966 link->io.NumPorts1 = 16;
967 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
968 link->io.IOAddrLines = 10;
969 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
970 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
971 link->conf.Attributes = CONF_ENABLE_IRQ;
972 link->conf.Vcc = 50;
973 link->conf.IntType = INT_MEMORY_AND_IO;
974 link->conf.Present = PRESENT_OPTION;
975
976 /* Register with Card Services */
977 link->next = dev_list;
978 dev_list = link;
979 client_reg.dev_info = &dev_info;
980 client_reg.event_handler = &SYM53C500_event;
981 client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
982 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
983 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
984 client_reg.Version = 0x0210;
985 client_reg.event_callback_args.client_data = link;
986 ret = pcmcia_register_client(&link->handle, &client_reg);
987 if (ret != 0) {
988 cs_error(link->handle, RegisterClient, ret);
989 SYM53C500_detach(link);
990 return NULL;
991 }
992
993 return link;
994} /* SYM53C500_attach */
995
996MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
997MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver");
998MODULE_LICENSE("GPL");
999
1000static struct pcmcia_driver sym53c500_cs_driver = {
1001 .owner = THIS_MODULE,
1002 .drv = {
1003 .name = "sym53c500_cs",
1004 },
1005 .attach = SYM53C500_attach,
1006 .detach = SYM53C500_detach,
1007};
1008
1009static int __init
1010init_sym53c500_cs(void)
1011{
1012 return pcmcia_register_driver(&sym53c500_cs_driver);
1013}
1014
1015static void __exit
1016exit_sym53c500_cs(void)
1017{
1018 pcmcia_unregister_driver(&sym53c500_cs_driver);
1019}
1020
1021module_init(init_sym53c500_cs);
1022module_exit(exit_sym53c500_cs);