aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/arm
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/arm
Linux-2.6.12-rc2v2.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/arm')
-rw-r--r--drivers/scsi/arm/Kconfig89
-rw-r--r--drivers/scsi/arm/Makefile14
-rw-r--r--drivers/scsi/arm/acornscsi-io.S145
-rw-r--r--drivers/scsi/arm/acornscsi.c3130
-rw-r--r--drivers/scsi/arm/acornscsi.h358
-rw-r--r--drivers/scsi/arm/arxescsi.c395
-rw-r--r--drivers/scsi/arm/cumana_1.c357
-rw-r--r--drivers/scsi/arm/cumana_2.c556
-rw-r--r--drivers/scsi/arm/ecoscsi.c239
-rw-r--r--drivers/scsi/arm/eesox.c680
-rw-r--r--drivers/scsi/arm/fas216.c3043
-rw-r--r--drivers/scsi/arm/fas216.h394
-rw-r--r--drivers/scsi/arm/msgqueue.c171
-rw-r--r--drivers/scsi/arm/msgqueue.h82
-rw-r--r--drivers/scsi/arm/oak.c217
-rw-r--r--drivers/scsi/arm/powertec.c472
-rw-r--r--drivers/scsi/arm/queue.c319
-rw-r--r--drivers/scsi/arm/queue.h105
-rw-r--r--drivers/scsi/arm/scsi.h115
19 files changed, 10881 insertions, 0 deletions
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
new file mode 100644
index 000000000000..54b32868aaf7
--- /dev/null
+++ b/drivers/scsi/arm/Kconfig
@@ -0,0 +1,89 @@
1#
2# SCSI driver configuration for Acorn
3#
4config SCSI_ACORNSCSI_3
5 tristate "Acorn SCSI card (aka30) support"
6 depends on ARCH_ACORN && SCSI
7 help
8 This enables support for the Acorn SCSI card (aka30). If you have an
9 Acorn system with one of these, say Y. If unsure, say N.
10
11config SCSI_ACORNSCSI_TAGGED_QUEUE
12 bool "Support SCSI 2 Tagged queueing"
13 depends on SCSI_ACORNSCSI_3
14 help
15 Say Y here to enable tagged queuing support on the Acorn SCSI card.
16
17 This is a feature of SCSI-2 which improves performance: the host
18 adapter can send several SCSI commands to a device's queue even if
19 previous commands haven't finished yet. Some SCSI devices don't
20 implement this properly, so the safe answer is N.
21
22config SCSI_ACORNSCSI_SYNC
23 bool "Support SCSI 2 Synchronous Transfers"
24 depends on SCSI_ACORNSCSI_3
25 help
26 Say Y here to enable synchronous transfer negotiation with all
27 targets on the Acorn SCSI card.
28
29 In general, this improves performance; however some SCSI devices
30 don't implement it properly, so the safe answer is N.
31
32config SCSI_ARXESCSI
33 tristate "ARXE SCSI support"
34 depends on ARCH_ACORN && SCSI
35 help
36 Around 1991, Arxe Systems Limited released a high density floppy
37 disc interface for the Acorn Archimedes range, to allow the use of
38 HD discs from the then new A5000 on earlier models. This interface
39 was either sold on its own or with an integral SCSI controller.
40 Technical details on this NCR53c94-based device are available at
41 <http://www.cryton.demon.co.uk/acornbits/scsi_arxe.html>
42 Say Y here to compile in support for the SCSI controller.
43
44config SCSI_CUMANA_2
45 tristate "CumanaSCSI II support"
46 depends on ARCH_ACORN && SCSI
47 help
48 This enables support for the Cumana SCSI II card. If you have an
49 Acorn system with one of these, say Y. If unsure, say N.
50
51config SCSI_EESOXSCSI
52 tristate "EESOX support"
53 depends on ARCH_ACORN && SCSI
54 help
55 This enables support for the EESOX SCSI card. If you have an Acorn
56 system with one of these, say Y, otherwise say N.
57
58config SCSI_POWERTECSCSI
59 tristate "PowerTec support"
60 depends on ARCH_ACORN && SCSI
61 help
62 This enables support for the Powertec SCSI card on Acorn systems. If
63 you have one of these, say Y. If unsure, say N.
64
65comment "The following drivers are not fully supported"
66 depends on ARCH_ACORN && EXPERIMENTAL
67
68config SCSI_CUMANA_1
69 tristate "CumanaSCSI I support (EXPERIMENTAL)"
70 depends on ARCH_ACORN && EXPERIMENTAL && SCSI
71 help
72 This enables support for the Cumana SCSI I card. If you have an
73 Acorn system with one of these, say Y. If unsure, say N.
74
75config SCSI_ECOSCSI
76 tristate "EcoScsi support (EXPERIMENTAL)"
77 depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI
78 help
79 This enables support for the EcoSCSI card -- a small card that sits
80 in the Econet socket. If you have an Acorn system with one of these,
81 say Y. If unsure, say N.
82
83config SCSI_OAK1
84 tristate "Oak SCSI support (EXPERIMENTAL)"
85 depends on ARCH_ACORN && EXPERIMENTAL && SCSI
86 help
87 This enables support for the Oak SCSI card. If you have an Acorn
88 system with one of these, say Y. If unsure, say N.
89
diff --git a/drivers/scsi/arm/Makefile b/drivers/scsi/arm/Makefile
new file mode 100644
index 000000000000..e8db17924c1d
--- /dev/null
+++ b/drivers/scsi/arm/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for drivers/scsi/arm
3#
4
5acornscsi_mod-objs := acornscsi.o acornscsi-io.o
6
7obj-$(CONFIG_SCSI_ACORNSCSI_3) += acornscsi_mod.o queue.o msgqueue.o
8obj-$(CONFIG_SCSI_ARXESCSI) += arxescsi.o fas216.o queue.o msgqueue.o
9obj-$(CONFIG_SCSI_CUMANA_1) += cumana_1.o
10obj-$(CONFIG_SCSI_CUMANA_2) += cumana_2.o fas216.o queue.o msgqueue.o
11obj-$(CONFIG_SCSI_ECOSCSI) += ecoscsi.o
12obj-$(CONFIG_SCSI_OAK1) += oak.o
13obj-$(CONFIG_SCSI_POWERTECSCSI) += powertec.o fas216.o queue.o msgqueue.o
14obj-$(CONFIG_SCSI_EESOXSCSI) += eesox.o fas216.o queue.o msgqueue.o
diff --git a/drivers/scsi/arm/acornscsi-io.S b/drivers/scsi/arm/acornscsi-io.S
new file mode 100644
index 000000000000..93467e6ac923
--- /dev/null
+++ b/drivers/scsi/arm/acornscsi-io.S
@@ -0,0 +1,145 @@
1/*
2 * linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/linkage.h>
9
10#include <asm/assembler.h>
11#include <asm/hardware.h>
12
13#if (IO_BASE == (PCIO_BASE & 0xff000000))
14#define ADDR(off,reg) \
15 tst off, $0x80000000 ;\
16 mov reg, $IO_BASE ;\
17 orreq reg, reg, $(PCIO_BASE & 0x00ff0000)
18#else
19#define ADDR(off,reg) \
20 tst off, $0x80000000 ;\
21 movne reg, $IO_BASE ;\
22 moveq reg, $(PCIO_BASE & 0xff000000) ;\
23 orreq reg, reg, $(PCIO_BASE & 0x00ff0000)
24#endif
25
26@ Purpose: transfer a block of data from the acorn scsi card to memory
27@ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
28@ Returns: nothing
29
30 .align
31ENTRY(__acornscsi_in)
32 stmfd sp!, {r4 - r7, lr}
33 bic r0, r0, #3
34 mov lr, #0xff
35 orr lr, lr, #0xff00
36acornscsi_in16lp:
37 subs r2, r2, #16
38 bmi acornscsi_in8
39 ldmia r0!, {r3, r4, r5, r6}
40 and r3, r3, lr
41 orr r3, r3, r4, lsl #16
42 and r4, r5, lr
43 orr r4, r4, r6, lsl #16
44 ldmia r0!, {r5, r6, r7, ip}
45 and r5, r5, lr
46 orr r5, r5, r6, lsl #16
47 and r6, r7, lr
48 orr r6, r6, ip, lsl #16
49 stmia r1!, {r3 - r6}
50 bne acornscsi_in16lp
51 LOADREGS(fd, sp!, {r4 - r7, pc})
52
53acornscsi_in8: adds r2, r2, #8
54 bmi acornscsi_in4
55 ldmia r0!, {r3, r4, r5, r6}
56 and r3, r3, lr
57 orr r3, r3, r4, lsl #16
58 and r4, r5, lr
59 orr r4, r4, r6, lsl #16
60 stmia r1!, {r3 - r4}
61 LOADREGS(eqfd, sp!, {r4 - r7, pc})
62 sub r2, r2, #8
63
64acornscsi_in4: adds r2, r2, #4
65 bmi acornscsi_in2
66 ldmia r0!, {r3, r4}
67 and r3, r3, lr
68 orr r3, r3, r4, lsl #16
69 str r3, [r1], #4
70 LOADREGS(eqfd, sp!, {r4 - r7, pc})
71 sub r2, r2, #4
72
73acornscsi_in2: adds r2, r2, #2
74 ldr r3, [r0], #4
75 and r3, r3, lr
76 strb r3, [r1], #1
77 mov r3, r3, lsr #8
78 strplb r3, [r1], #1
79 LOADREGS(fd, sp!, {r4 - r7, pc})
80
81@ Purpose: transfer a block of data from memory to the acorn scsi card
82@ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
83@ Returns: nothing
84
85ENTRY(__acornscsi_out)
86 stmfd sp!, {r4 - r6, lr}
87 bic r0, r0, #3
88acornscsi_out16lp:
89 subs r2, r2, #16
90 bmi acornscsi_out8
91 ldmia r1!, {r4, r6, ip, lr}
92 mov r3, r4, lsl #16
93 orr r3, r3, r3, lsr #16
94 mov r4, r4, lsr #16
95 orr r4, r4, r4, lsl #16
96 mov r5, r6, lsl #16
97 orr r5, r5, r5, lsr #16
98 mov r6, r6, lsr #16
99 orr r6, r6, r6, lsl #16
100 stmia r0!, {r3, r4, r5, r6}
101 mov r3, ip, lsl #16
102 orr r3, r3, r3, lsr #16
103 mov r4, ip, lsr #16
104 orr r4, r4, r4, lsl #16
105 mov ip, lr, lsl #16
106 orr ip, ip, ip, lsr #16
107 mov lr, lr, lsr #16
108 orr lr, lr, lr, lsl #16
109 stmia r0!, {r3, r4, ip, lr}
110 bne acornscsi_out16lp
111 LOADREGS(fd, sp!, {r4 - r6, pc})
112
113acornscsi_out8: adds r2, r2, #8
114 bmi acornscsi_out4
115 ldmia r1!, {r4, r6}
116 mov r3, r4, lsl #16
117 orr r3, r3, r3, lsr #16
118 mov r4, r4, lsr #16
119 orr r4, r4, r4, lsl #16
120 mov r5, r6, lsl #16
121 orr r5, r5, r5, lsr #16
122 mov r6, r6, lsr #16
123 orr r6, r6, r6, lsl #16
124 stmia r0!, {r3, r4, r5, r6}
125 LOADREGS(eqfd, sp!, {r4 - r6, pc})
126
127 sub r2, r2, #8
128acornscsi_out4: adds r2, r2, #4
129 bmi acornscsi_out2
130 ldr r4, [r1], #4
131 mov r3, r4, lsl #16
132 orr r3, r3, r3, lsr #16
133 mov r4, r4, lsr #16
134 orr r4, r4, r4, lsl #16
135 stmia r0!, {r3, r4}
136 LOADREGS(eqfd, sp!, {r4 - r6, pc})
137
138 sub r2, r2, #4
139acornscsi_out2: adds r2, r2, #2
140 ldr r3, [r1], #2
141 strb r3, [r0], #1
142 mov r3, r3, lsr #8
143 strplb r3, [r0], #1
144 LOADREGS(fd, sp!, {r4 - r6, pc})
145
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
new file mode 100644
index 000000000000..24dd0b890dd2
--- /dev/null
+++ b/drivers/scsi/arm/acornscsi.c
@@ -0,0 +1,3130 @@
1/*
2 * linux/drivers/acorn/scsi/acornscsi.c
3 *
4 * Acorn SCSI 3 driver
5 * By R.M.King.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Abandoned using the Select and Transfer command since there were
12 * some nasty races between our software and the target devices that
13 * were not easy to solve, and the device errata had a lot of entries
14 * for this command, some of them quite nasty...
15 *
16 * Changelog:
17 * 26-Sep-1997 RMK Re-jigged to use the queue module.
18 * Re-coded state machine to be based on driver
19 * state not scsi state. Should be easier to debug.
20 * Added acornscsi_release to clean up properly.
21 * Updated proc/scsi reporting.
22 * 05-Oct-1997 RMK Implemented writing to SCSI devices.
23 * 06-Oct-1997 RMK Corrected small (non-serious) bug with the connect/
24 * reconnect race condition causing a warning message.
25 * 12-Oct-1997 RMK Added catch for re-entering interrupt routine.
26 * 15-Oct-1997 RMK Improved handling of commands.
27 * 27-Jun-1998 RMK Changed asm/delay.h to linux/delay.h.
28 * 13-Dec-1998 RMK Better abort code and command handling. Extra state
29 * transitions added to allow dodgy devices to work.
30 */
31#define DEBUG_NO_WRITE 1
32#define DEBUG_QUEUES 2
33#define DEBUG_DMA 4
34#define DEBUG_ABORT 8
35#define DEBUG_DISCON 16
36#define DEBUG_CONNECT 32
37#define DEBUG_PHASES 64
38#define DEBUG_WRITE 128
39#define DEBUG_LINK 256
40#define DEBUG_MESSAGES 512
41#define DEBUG_RESET 1024
42#define DEBUG_ALL (DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\
43 DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\
44 DEBUG_DMA|DEBUG_QUEUES)
45
46/* DRIVER CONFIGURATION
47 *
48 * SCSI-II Tagged queue support.
49 *
50 * I don't have any SCSI devices that support it, so it is totally untested
51 * (except to make sure that it doesn't interfere with any non-tagging
52 * devices). It is not fully implemented either - what happens when a
53 * tagging device reconnects???
54 *
55 * You can tell if you have a device that supports tagged queueing my
56 * cating (eg) /proc/scsi/acornscsi/0 and see if the SCSI revision is reported
57 * as '2 TAG'.
58 *
59 * Also note that CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE is normally set in the config
60 * scripts, but disabled here. Once debugged, remove the #undef, otherwise to debug,
61 * comment out the undef.
62 */
63#undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
64/*
65 * SCSI-II Linked command support.
66 *
67 * The higher level code doesn't support linked commands yet, and so the option
68 * is undef'd here.
69 */
70#undef CONFIG_SCSI_ACORNSCSI_LINK
71/*
72 * SCSI-II Synchronous transfer support.
73 *
74 * Tried and tested...
75 *
76 * SDTR_SIZE - maximum number of un-acknowledged bytes (0 = off, 12 = max)
77 * SDTR_PERIOD - period of REQ signal (min=125, max=1020)
78 * DEFAULT_PERIOD - default REQ period.
79 */
80#define SDTR_SIZE 12
81#define SDTR_PERIOD 125
82#define DEFAULT_PERIOD 500
83
84/*
85 * Debugging information
86 *
87 * DEBUG - bit mask from list above
88 * DEBUG_TARGET - is defined to the target number if you want to debug
89 * a specific target. [only recon/write/dma].
90 */
91#define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE)
92/* only allow writing to SCSI device 0 */
93#define NO_WRITE 0xFE
94/*#define DEBUG_TARGET 2*/
95/*
96 * Select timeout time (in 10ms units)
97 *
98 * This is the timeout used between the start of selection and the WD33C93
99 * chip deciding that the device isn't responding.
100 */
101#define TIMEOUT_TIME 10
102/*
103 * Define this if you want to have verbose explaination of SCSI
104 * status/messages.
105 */
106#undef CONFIG_ACORNSCSI_CONSTANTS
107/*
108 * Define this if you want to use the on board DMAC [don't remove this option]
109 * If not set, then use PIO mode (not currently supported).
110 */
111#define USE_DMAC
112
113/*
114 * ====================================================================================
115 */
116
117#ifdef DEBUG_TARGET
118#define DBG(cmd,xxx...) \
119 if (cmd->device->id == DEBUG_TARGET) { \
120 xxx; \
121 }
122#else
123#define DBG(cmd,xxx...) xxx
124#endif
125
126#ifndef STRINGIFY
127#define STRINGIFY(x) #x
128#endif
129#define STRx(x) STRINGIFY(x)
130#define NO_WRITE_STR STRx(NO_WRITE)
131
132#include <linux/config.h>
133#include <linux/module.h>
134#include <linux/kernel.h>
135#include <linux/sched.h>
136#include <linux/string.h>
137#include <linux/signal.h>
138#include <linux/errno.h>
139#include <linux/proc_fs.h>
140#include <linux/ioport.h>
141#include <linux/blkdev.h>
142#include <linux/delay.h>
143#include <linux/interrupt.h>
144#include <linux/init.h>
145#include <linux/bitops.h>
146
147#include <asm/system.h>
148#include <asm/io.h>
149#include <asm/irq.h>
150#include <asm/ecard.h>
151
152#include "../scsi.h"
153#include <scsi/scsi_host.h>
154#include "acornscsi.h"
155#include "msgqueue.h"
156#include "scsi.h"
157
158#include <scsi/scsicam.h>
159
160#define VER_MAJOR 2
161#define VER_MINOR 0
162#define VER_PATCH 6
163
164#ifndef ABORT_TAG
165#define ABORT_TAG 0xd
166#else
167#error "Yippee! ABORT TAG is now defined! Remove this error!"
168#endif
169
170#ifdef CONFIG_SCSI_ACORNSCSI_LINK
171#error SCSI2 LINKed commands not supported (yet)!
172#endif
173
174#ifdef USE_DMAC
175/*
176 * DMAC setup parameters
177 */
178#define INIT_DEVCON0 (DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP)
179#define INIT_DEVCON1 (DEVCON1_BHLD)
180#define DMAC_READ (MODECON_READ)
181#define DMAC_WRITE (MODECON_WRITE)
182#define INIT_SBICDMA (CTRL_DMABURST)
183
184#define scsi_xferred have_data_in
185
186/*
187 * Size of on-board DMA buffer
188 */
189#define DMAC_BUFFER_SIZE 65536
190#endif
191
192#define STATUS_BUFFER_TO_PRINT 24
193
194unsigned int sdtr_period = SDTR_PERIOD;
195unsigned int sdtr_size = SDTR_SIZE;
196
197static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
198static int acornscsi_reconnect_finish(AS_Host *host);
199static void acornscsi_dma_cleanup(AS_Host *host);
200static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
201
202/* ====================================================================================
203 * Miscellaneous
204 */
205
206static inline void
207sbic_arm_write(unsigned int io_port, int reg, int value)
208{
209 __raw_writeb(reg, io_port);
210 __raw_writeb(value, io_port + 4);
211}
212
213#define sbic_arm_writenext(io,val) \
214 __raw_writeb((val), (io) + 4)
215
216static inline
217int sbic_arm_read(unsigned int io_port, int reg)
218{
219 if(reg == SBIC_ASR)
220 return __raw_readl(io_port) & 255;
221 __raw_writeb(reg, io_port);
222 return __raw_readl(io_port + 4) & 255;
223}
224
225#define sbic_arm_readnext(io) \
226 __raw_readb((io) + 4)
227
228#ifdef USE_DMAC
229#define dmac_read(io_port,reg) \
230 inb((io_port) + (reg))
231
232#define dmac_write(io_port,reg,value) \
233 ({ outb((value), (io_port) + (reg)); })
234
235#define dmac_clearintr(io_port) \
236 ({ outb(0, (io_port)); })
237
238static inline
239unsigned int dmac_address(unsigned int io_port)
240{
241 return dmac_read(io_port, DMAC_TXADRHI) << 16 |
242 dmac_read(io_port, DMAC_TXADRMD) << 8 |
243 dmac_read(io_port, DMAC_TXADRLO);
244}
245
246static
247void acornscsi_dumpdma(AS_Host *host, char *where)
248{
249 unsigned int mode, addr, len;
250
251 mode = dmac_read(host->dma.io_port, DMAC_MODECON);
252 addr = dmac_address(host->dma.io_port);
253 len = dmac_read(host->dma.io_port, DMAC_TXCNTHI) << 8 |
254 dmac_read(host->dma.io_port, DMAC_TXCNTLO);
255
256 printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
257 host->host->host_no, where,
258 mode, addr, (len + 1) & 0xffff,
259 dmac_read(host->dma.io_port, DMAC_MASKREG));
260
261 printk("DMA @%06x, ", host->dma.start_addr);
262 printk("BH @%p +%04x, ", host->scsi.SCp.ptr,
263 host->scsi.SCp.this_residual);
264 printk("DT @+%04x ST @+%04x", host->dma.transferred,
265 host->scsi.SCp.scsi_xferred);
266 printk("\n");
267}
268#endif
269
270static
271unsigned long acornscsi_sbic_xfcount(AS_Host *host)
272{
273 unsigned long length;
274
275 length = sbic_arm_read(host->scsi.io_port, SBIC_TRANSCNTH) << 16;
276 length |= sbic_arm_readnext(host->scsi.io_port) << 8;
277 length |= sbic_arm_readnext(host->scsi.io_port);
278
279 return length;
280}
281
282static int
283acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
284{
285 int asr;
286
287 do {
288 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
289
290 if ((asr & stat_mask) == stat)
291 return 0;
292
293 udelay(1);
294 } while (--timeout);
295
296 printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
297
298 return -1;
299}
300
301static
302int acornscsi_sbic_issuecmd(AS_Host *host, int command)
303{
304 if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
305 return -1;
306
307 sbic_arm_write(host->scsi.io_port, SBIC_CMND, command);
308
309 return 0;
310}
311
312static void
313acornscsi_csdelay(unsigned int cs)
314{
315 unsigned long target_jiffies, flags;
316
317 target_jiffies = jiffies + 1 + cs * HZ / 100;
318
319 local_save_flags(flags);
320 local_irq_enable();
321
322 while (time_before(jiffies, target_jiffies)) barrier();
323
324 local_irq_restore(flags);
325}
326
327static
328void acornscsi_resetcard(AS_Host *host)
329{
330 unsigned int i, timeout;
331
332 /* assert reset line */
333 host->card.page_reg = 0x80;
334 outb(host->card.page_reg, host->card.io_page);
335
336 /* wait 3 cs. SCSI standard says 25ms. */
337 acornscsi_csdelay(3);
338
339 host->card.page_reg = 0;
340 outb(host->card.page_reg, host->card.io_page);
341
342 /*
343 * Should get a reset from the card
344 */
345 timeout = 1000;
346 do {
347 if (inb(host->card.io_intr) & 8)
348 break;
349 udelay(1);
350 } while (--timeout);
351
352 if (timeout == 0)
353 printk("scsi%d: timeout while resetting card\n",
354 host->host->host_no);
355
356 sbic_arm_read(host->scsi.io_port, SBIC_ASR);
357 sbic_arm_read(host->scsi.io_port, SBIC_SSR);
358
359 /* setup sbic - WD33C93A */
360 sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id);
361 sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET);
362
363 /*
364 * Command should cause a reset interrupt
365 */
366 timeout = 1000;
367 do {
368 if (inb(host->card.io_intr) & 8)
369 break;
370 udelay(1);
371 } while (--timeout);
372
373 if (timeout == 0)
374 printk("scsi%d: timeout while resetting card\n",
375 host->host->host_no);
376
377 sbic_arm_read(host->scsi.io_port, SBIC_ASR);
378 if (sbic_arm_read(host->scsi.io_port, SBIC_SSR) != 0x01)
379 printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
380 host->host->host_no);
381
382 sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI);
383 sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME);
384 sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
385 sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
386
387 host->card.page_reg = 0x40;
388 outb(host->card.page_reg, host->card.io_page);
389
390 /* setup dmac - uPC71071 */
391 dmac_write(host->dma.io_port, DMAC_INIT, 0);
392#ifdef USE_DMAC
393 dmac_write(host->dma.io_port, DMAC_INIT, INIT_8BIT);
394 dmac_write(host->dma.io_port, DMAC_CHANNEL, CHANNEL_0);
395 dmac_write(host->dma.io_port, DMAC_DEVCON0, INIT_DEVCON0);
396 dmac_write(host->dma.io_port, DMAC_DEVCON1, INIT_DEVCON1);
397#endif
398
399 host->SCpnt = NULL;
400 host->scsi.phase = PHASE_IDLE;
401 host->scsi.disconnectable = 0;
402
403 memset(host->busyluns, 0, sizeof(host->busyluns));
404
405 for (i = 0; i < 8; i++) {
406 host->device[i].sync_state = SYNC_NEGOCIATE;
407 host->device[i].disconnect_ok = 1;
408 }
409
410 /* wait 25 cs. SCSI standard says 250ms. */
411 acornscsi_csdelay(25);
412}
413
414/*=============================================================================================
415 * Utility routines (eg. debug)
416 */
417#ifdef CONFIG_ACORNSCSI_CONSTANTS
418static char *acornscsi_interrupttype[] = {
419 "rst", "suc", "p/a", "3",
420 "term", "5", "6", "7",
421 "serv", "9", "a", "b",
422 "c", "d", "e", "f"
423};
424
425static signed char acornscsi_map[] = {
426 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
427 -1, 2, -1, -1, -1, -1, 3, -1, 4, 5, 6, 7, 8, 9, 10, 11,
428 12, 13, 14, -1, -1, -1, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11,
429 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
430 15, 16, 17, 18, 19, -1, -1, 20, 4, 5, 6, 7, 8, 9, 10, 11,
431 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
432 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
433 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
434 21, 22, -1, -1, -1, 23, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11,
435 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
436 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
437 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
438 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
439 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
440 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
441 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
442};
443
444static char *acornscsi_interruptcode[] = {
445 /* 0 */
446 "reset - normal mode", /* 00 */
447 "reset - advanced mode", /* 01 */
448
449 /* 2 */
450 "sel", /* 11 */
451 "sel+xfer", /* 16 */
452 "data-out", /* 18 */
453 "data-in", /* 19 */
454 "cmd", /* 1A */
455 "stat", /* 1B */
456 "??-out", /* 1C */
457 "??-in", /* 1D */
458 "msg-out", /* 1E */
459 "msg-in", /* 1F */
460
461 /* 12 */
462 "/ACK asserted", /* 20 */
463 "save-data-ptr", /* 21 */
464 "{re}sel", /* 22 */
465
466 /* 15 */
467 "inv cmd", /* 40 */
468 "unexpected disconnect", /* 41 */
469 "sel timeout", /* 42 */
470 "P err", /* 43 */
471 "P err+ATN", /* 44 */
472 "bad status byte", /* 47 */
473
474 /* 21 */
475 "resel, no id", /* 80 */
476 "resel", /* 81 */
477 "discon", /* 85 */
478};
479
480static
481void print_scsi_status(unsigned int ssr)
482{
483 if (acornscsi_map[ssr] != -1)
484 printk("%s:%s",
485 acornscsi_interrupttype[(ssr >> 4)],
486 acornscsi_interruptcode[acornscsi_map[ssr]]);
487 else
488 printk("%X:%X", ssr >> 4, ssr & 0x0f);
489}
490#endif
491
492static
493void print_sbic_status(int asr, int ssr, int cmdphase)
494{
495#ifdef CONFIG_ACORNSCSI_CONSTANTS
496 printk("sbic: %c%c%c%c%c%c ",
497 asr & ASR_INT ? 'I' : 'i',
498 asr & ASR_LCI ? 'L' : 'l',
499 asr & ASR_BSY ? 'B' : 'b',
500 asr & ASR_CIP ? 'C' : 'c',
501 asr & ASR_PE ? 'P' : 'p',
502 asr & ASR_DBR ? 'D' : 'd');
503 printk("scsi: ");
504 print_scsi_status(ssr);
505 printk(" ph %02X\n", cmdphase);
506#else
507 printk("sbic: %02X scsi: %X:%X ph: %02X\n",
508 asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);
509#endif
510}
511
512static void
513acornscsi_dumplogline(AS_Host *host, int target, int line)
514{
515 unsigned long prev;
516 signed int ptr;
517
518 ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT;
519 if (ptr < 0)
520 ptr += STATUS_BUFFER_SIZE;
521
522 printk("%c: %3s:", target == 8 ? 'H' : '0' + target,
523 line == 0 ? "ph" : line == 1 ? "ssr" : "int");
524
525 prev = host->status[target][ptr].when;
526
527 for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
528 unsigned long time_diff;
529
530 if (!host->status[target][ptr].when)
531 continue;
532
533 switch (line) {
534 case 0:
535 printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ',
536 host->status[target][ptr].ph);
537 break;
538
539 case 1:
540 printk(" %02X", host->status[target][ptr].ssr);
541 break;
542
543 case 2:
544 time_diff = host->status[target][ptr].when - prev;
545 prev = host->status[target][ptr].when;
546 if (time_diff == 0)
547 printk("==^");
548 else if (time_diff >= 100)
549 printk(" ");
550 else
551 printk(" %02ld", time_diff);
552 break;
553 }
554 }
555
556 printk("\n");
557}
558
559static
560void acornscsi_dumplog(AS_Host *host, int target)
561{
562 do {
563 acornscsi_dumplogline(host, target, 0);
564 acornscsi_dumplogline(host, target, 1);
565 acornscsi_dumplogline(host, target, 2);
566
567 if (target == 8)
568 break;
569
570 target = 8;
571 } while (1);
572}
573
574static
575char acornscsi_target(AS_Host *host)
576{
577 if (host->SCpnt)
578 return '0' + host->SCpnt->device->id;
579 return 'H';
580}
581
582/*
583 * Prototype: cmdtype_t acornscsi_cmdtype(int command)
584 * Purpose : differentiate READ from WRITE from other commands
585 * Params : command - command to interpret
586 * Returns : CMD_READ - command reads data,
587 * CMD_WRITE - command writes data,
588 * CMD_MISC - everything else
589 */
590static inline
591cmdtype_t acornscsi_cmdtype(int command)
592{
593 switch (command) {
594 case WRITE_6: case WRITE_10: case WRITE_12:
595 return CMD_WRITE;
596 case READ_6: case READ_10: case READ_12:
597 return CMD_READ;
598 default:
599 return CMD_MISC;
600 }
601}
602
603/*
604 * Prototype: int acornscsi_datadirection(int command)
605 * Purpose : differentiate between commands that have a DATA IN phase
606 * and a DATA OUT phase
607 * Params : command - command to interpret
608 * Returns : DATADIR_OUT - data out phase expected
609 * DATADIR_IN - data in phase expected
610 */
611static
612datadir_t acornscsi_datadirection(int command)
613{
614 switch (command) {
615 case CHANGE_DEFINITION: case COMPARE: case COPY:
616 case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
617 case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
618 case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
619 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
620 case WRITE_6: case WRITE_10: case WRITE_VERIFY:
621 case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME:
622 case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12:
623 case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW:
624 case MEDIUM_SCAN: case SEND_VOLUME_TAG: case 0xea:
625 return DATADIR_OUT;
626 default:
627 return DATADIR_IN;
628 }
629}
630
631/*
632 * Purpose : provide values for synchronous transfers with 33C93.
633 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
634 * Modified by Russell King for 8MHz WD33C93A
635 */
636static struct sync_xfer_tbl {
637 unsigned int period_ns;
638 unsigned char reg_value;
639} sync_xfer_table[] = {
640 { 1, 0x20 }, { 249, 0x20 }, { 374, 0x30 },
641 { 499, 0x40 }, { 624, 0x50 }, { 749, 0x60 },
642 { 874, 0x70 }, { 999, 0x00 }, { 0, 0 }
643};
644
645/*
646 * Prototype: int acornscsi_getperiod(unsigned char syncxfer)
647 * Purpose : period for the synchronous transfer setting
648 * Params : syncxfer SYNCXFER register value
649 * Returns : period in ns.
650 */
651static
652int acornscsi_getperiod(unsigned char syncxfer)
653{
654 int i;
655
656 syncxfer &= 0xf0;
657 if (syncxfer == 0x10)
658 syncxfer = 0;
659
660 for (i = 1; sync_xfer_table[i].period_ns; i++)
661 if (syncxfer == sync_xfer_table[i].reg_value)
662 return sync_xfer_table[i].period_ns;
663 return 0;
664}
665
666/*
667 * Prototype: int round_period(unsigned int period)
668 * Purpose : return index into above table for a required REQ period
669 * Params : period - time (ns) for REQ
670 * Returns : table index
671 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
672 */
673static inline
674int round_period(unsigned int period)
675{
676 int i;
677
678 for (i = 1; sync_xfer_table[i].period_ns; i++) {
679 if ((period <= sync_xfer_table[i].period_ns) &&
680 (period > sync_xfer_table[i - 1].period_ns))
681 return i;
682 }
683 return 7;
684}
685
686/*
687 * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
688 * Purpose : calculate value for 33c93s SYNC register
689 * Params : period - time (ns) for REQ
690 * offset - offset in bytes between REQ/ACK
691 * Returns : value for SYNC register
692 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
693 */
694static
695unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
696{
697 return sync_xfer_table[round_period(period)].reg_value |
698 ((offset < SDTR_SIZE) ? offset : SDTR_SIZE);
699}
700
701/* ====================================================================================
702 * Command functions
703 */
704/*
705 * Function: acornscsi_kick(AS_Host *host)
706 * Purpose : kick next command to interface
707 * Params : host - host to send command to
708 * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING
709 * Notes : interrupts are always disabled!
710 */
711static
712intr_ret_t acornscsi_kick(AS_Host *host)
713{
714 int from_queue = 0;
715 Scsi_Cmnd *SCpnt;
716
717 /* first check to see if a command is waiting to be executed */
718 SCpnt = host->origSCpnt;
719 host->origSCpnt = NULL;
720
721 /* retrieve next command */
722 if (!SCpnt) {
723 SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns);
724 if (!SCpnt)
725 return INTR_IDLE;
726
727 from_queue = 1;
728 }
729
730 if (host->scsi.disconnectable && host->SCpnt) {
731 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
732 host->scsi.disconnectable = 0;
733#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
734 DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n",
735 host->host->host_no, acornscsi_target(host)));
736#endif
737 host->SCpnt = NULL;
738 }
739
740 /*
741 * If we have an interrupt pending, then we may have been reselected.
742 * In this case, we don't want to write to the registers
743 */
744 if (!(sbic_arm_read(host->scsi.io_port, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
745 sbic_arm_write(host->scsi.io_port, SBIC_DESTID, SCpnt->device->id);
746 sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_SELWITHATN);
747 }
748
749 /*
750 * claim host busy - all of these must happen atomically wrt
751 * our interrupt routine. Failure means command loss.
752 */
753 host->scsi.phase = PHASE_CONNECTING;
754 host->SCpnt = SCpnt;
755 host->scsi.SCp = SCpnt->SCp;
756 host->dma.xfer_setup = 0;
757 host->dma.xfer_required = 0;
758 host->dma.xfer_done = 0;
759
760#if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT))
761 DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n",
762 host->host->host_no, '0' + SCpnt->device->id,
763 SCpnt->cmnd[0]));
764#endif
765
766 if (from_queue) {
767#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
768 /*
769 * tagged queueing - allocate a new tag to this command
770 */
771 if (SCpnt->device->simple_tags) {
772 SCpnt->device->current_tag += 1;
773 if (SCpnt->device->current_tag == 0)
774 SCpnt->device->current_tag = 1;
775 SCpnt->tag = SCpnt->device->current_tag;
776 } else
777#endif
778 set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
779
780 host->stats.removes += 1;
781
782 switch (acornscsi_cmdtype(SCpnt->cmnd[0])) {
783 case CMD_WRITE:
784 host->stats.writes += 1;
785 break;
786 case CMD_READ:
787 host->stats.reads += 1;
788 break;
789 case CMD_MISC:
790 host->stats.miscs += 1;
791 break;
792 }
793 }
794
795 return INTR_PROCESSING;
796}
797
798/*
799 * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
800 * Purpose : complete processing for command
801 * Params : host - interface that completed
802 * result - driver byte of result
803 */
804static
805void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
806{
807 Scsi_Cmnd *SCpnt = *SCpntp;
808
809 /* clean up */
810 sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
811
812 host->stats.fins += 1;
813
814 if (SCpnt) {
815 *SCpntp = NULL;
816
817 acornscsi_dma_cleanup(host);
818
819 SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status;
820
821 /*
822 * In theory, this should not happen. In practice, it seems to.
823 * Only trigger an error if the device attempts to report all happy
824 * but with untransferred buffers... If we don't do something, then
825 * data loss will occur. Should we check SCpnt->underflow here?
826 * It doesn't appear to be set to something meaningful by the higher
827 * levels all the time.
828 */
829 if (result == DID_OK) {
830 int xfer_warn = 0;
831
832 if (SCpnt->underflow == 0) {
833 if (host->scsi.SCp.ptr &&
834 acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC)
835 xfer_warn = 1;
836 } else {
837 if (host->scsi.SCp.scsi_xferred < SCpnt->underflow ||
838 host->scsi.SCp.scsi_xferred != host->dma.transferred)
839 xfer_warn = 1;
840 }
841
842 /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6)
843 * Targets which break data transfers into multiple
844 * connections shall end each successful connection
845 * (except possibly the last) with a SAVE DATA
846 * POINTER - DISCONNECT message sequence.
847 *
848 * This makes it difficult to ensure that a transfer has
849 * completed. If we reach the end of a transfer during
850 * the command, then we can only have finished the transfer.
851 * therefore, if we seem to have some data remaining, this
852 * is not a problem.
853 */
854 if (host->dma.xfer_done)
855 xfer_warn = 0;
856
857 if (xfer_warn) {
858 switch (status_byte(SCpnt->result)) {
859 case CHECK_CONDITION:
860 case COMMAND_TERMINATED:
861 case BUSY:
862 case QUEUE_FULL:
863 case RESERVATION_CONFLICT:
864 break;
865
866 default:
867 printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
868 host->host->host_no, SCpnt->result);
869 print_command(SCpnt->cmnd);
870 acornscsi_dumpdma(host, "done");
871 acornscsi_dumplog(host, SCpnt->device->id);
872 SCpnt->result &= 0xffff;
873 SCpnt->result |= DID_ERROR << 16;
874 }
875 }
876 }
877
878 if (!SCpnt->scsi_done)
879 panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
880
881 clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
882
883 SCpnt->scsi_done(SCpnt);
884 } else
885 printk("scsi%d: null command in acornscsi_done", host->host->host_no);
886
887 host->scsi.phase = PHASE_IDLE;
888}
889
890/* ====================================================================================
891 * DMA routines
892 */
893/*
894 * Purpose : update SCSI Data Pointer
895 * Notes : this will only be one SG entry or less
896 */
897static
898void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
899{
900 SCp->ptr += length;
901 SCp->this_residual -= length;
902
903 if (SCp->this_residual == 0 && next_SCp(SCp) == 0)
904 host->dma.xfer_done = 1;
905}
906
907/*
908 * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
909 * unsigned int start_addr, unsigned int length)
910 * Purpose : read data from DMA RAM
911 * Params : host - host to transfer from
912 * ptr - DRAM address
913 * start_addr - host mem address
914 * length - number of bytes to transfer
915 * Notes : this will only be one SG entry or less
916 */
917static
918void acornscsi_data_read(AS_Host *host, char *ptr,
919 unsigned int start_addr, unsigned int length)
920{
921 extern void __acornscsi_in(int port, char *buf, int len);
922 unsigned int page, offset, len = length;
923
924 page = (start_addr >> 12);
925 offset = start_addr & ((1 << 12) - 1);
926
927 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
928
929 while (len > 0) {
930 unsigned int this_len;
931
932 if (len + offset > (1 << 12))
933 this_len = (1 << 12) - offset;
934 else
935 this_len = len;
936
937 __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
938
939 offset += this_len;
940 ptr += this_len;
941 len -= this_len;
942
943 if (offset == (1 << 12)) {
944 offset = 0;
945 page ++;
946 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
947 }
948 }
949 outb(host->card.page_reg, host->card.io_page);
950}
951
952/*
953 * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
954 * unsigned int start_addr, unsigned int length)
955 * Purpose : write data to DMA RAM
956 * Params : host - host to transfer from
957 * ptr - DRAM address
958 * start_addr - host mem address
959 * length - number of bytes to transfer
960 * Notes : this will only be one SG entry or less
961 */
962static
963void acornscsi_data_write(AS_Host *host, char *ptr,
964 unsigned int start_addr, unsigned int length)
965{
966 extern void __acornscsi_out(int port, char *buf, int len);
967 unsigned int page, offset, len = length;
968
969 page = (start_addr >> 12);
970 offset = start_addr & ((1 << 12) - 1);
971
972 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
973
974 while (len > 0) {
975 unsigned int this_len;
976
977 if (len + offset > (1 << 12))
978 this_len = (1 << 12) - offset;
979 else
980 this_len = len;
981
982 __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
983
984 offset += this_len;
985 ptr += this_len;
986 len -= this_len;
987
988 if (offset == (1 << 12)) {
989 offset = 0;
990 page ++;
991 outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
992 }
993 }
994 outb(host->card.page_reg, host->card.io_page);
995}
996
997/* =========================================================================================
998 * On-board DMA routines
999 */
1000#ifdef USE_DMAC
1001/*
1002 * Prototype: void acornscsi_dmastop(AS_Host *host)
1003 * Purpose : stop all DMA
1004 * Params : host - host on which to stop DMA
1005 * Notes : This is called when leaving DATA IN/OUT phase,
1006 * or when interface is RESET
1007 */
1008static inline
1009void acornscsi_dma_stop(AS_Host *host)
1010{
1011 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON);
1012 dmac_clearintr(host->dma.io_intr_clear);
1013
1014#if (DEBUG & DEBUG_DMA)
1015 DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
1016#endif
1017}
1018
1019/*
1020 * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1021 * Purpose : setup DMA controller for data transfer
1022 * Params : host - host to setup
1023 * direction - data transfer direction
1024 * Notes : This is called when entering DATA I/O phase, not
1025 * while we're in a DATA I/O phase
1026 */
1027static
1028void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
1029{
1030 unsigned int address, length, mode;
1031
1032 host->dma.direction = direction;
1033
1034 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON);
1035
1036 if (direction == DMA_OUT) {
1037#if (DEBUG & DEBUG_NO_WRITE)
1038 if (NO_WRITE & (1 << host->SCpnt->device->id)) {
1039 printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
1040 host->host->host_no, acornscsi_target(host));
1041 return;
1042 }
1043#endif
1044 mode = DMAC_WRITE;
1045 } else
1046 mode = DMAC_READ;
1047
1048 /*
1049 * Allocate some buffer space, limited to half the buffer size
1050 */
1051 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1052 if (length) {
1053 host->dma.start_addr = address = host->dma.free_addr;
1054 host->dma.free_addr = (host->dma.free_addr + length) &
1055 (DMAC_BUFFER_SIZE - 1);
1056
1057 /*
1058 * Transfer data to DMA memory
1059 */
1060 if (direction == DMA_OUT)
1061 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1062 length);
1063
1064 length -= 1;
1065 dmac_write(host->dma.io_port, DMAC_TXCNTLO, length);
1066 dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8);
1067 dmac_write(host->dma.io_port, DMAC_TXADRLO, address);
1068 dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8);
1069 dmac_write(host->dma.io_port, DMAC_TXADRHI, 0);
1070 dmac_write(host->dma.io_port, DMAC_MODECON, mode);
1071 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF);
1072
1073#if (DEBUG & DEBUG_DMA)
1074 DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
1075#endif
1076 host->dma.xfer_setup = 1;
1077 }
1078}
1079
1080/*
1081 * Function: void acornscsi_dma_cleanup(AS_Host *host)
1082 * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
1083 * Params : host - host to finish
1084 * Notes : This is called when a command is:
1085 * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT
1086 * : This must not return until all transfers are completed.
1087 */
1088static
1089void acornscsi_dma_cleanup(AS_Host *host)
1090{
1091 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON);
1092 dmac_clearintr(host->dma.io_intr_clear);
1093
1094 /*
1095 * Check for a pending transfer
1096 */
1097 if (host->dma.xfer_required) {
1098 host->dma.xfer_required = 0;
1099 if (host->dma.direction == DMA_IN)
1100 acornscsi_data_read(host, host->dma.xfer_ptr,
1101 host->dma.xfer_start, host->dma.xfer_length);
1102 }
1103
1104 /*
1105 * Has a transfer been setup?
1106 */
1107 if (host->dma.xfer_setup) {
1108 unsigned int transferred;
1109
1110 host->dma.xfer_setup = 0;
1111
1112#if (DEBUG & DEBUG_DMA)
1113 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
1114#endif
1115
1116 /*
1117 * Calculate number of bytes transferred from DMA.
1118 */
1119 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1120 host->dma.transferred += transferred;
1121
1122 if (host->dma.direction == DMA_IN)
1123 acornscsi_data_read(host, host->scsi.SCp.ptr,
1124 host->dma.start_addr, transferred);
1125
1126 /*
1127 * Update SCSI pointers
1128 */
1129 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1130#if (DEBUG & DEBUG_DMA)
1131 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
1132#endif
1133 }
1134}
1135
1136/*
1137 * Function: void acornscsi_dmacintr(AS_Host *host)
1138 * Purpose : handle interrupts from DMAC device
1139 * Params : host - host to process
1140 * Notes : If reading, we schedule the read to main memory &
1141 * allow the transfer to continue.
1142 * : If writing, we fill the onboard DMA memory from main
1143 * memory.
1144 * : Called whenever DMAC finished it's current transfer.
1145 */
1146static
1147void acornscsi_dma_intr(AS_Host *host)
1148{
1149 unsigned int address, length, transferred;
1150
1151#if (DEBUG & DEBUG_DMA)
1152 DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
1153#endif
1154
1155 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON);
1156 dmac_clearintr(host->dma.io_intr_clear);
1157
1158 /*
1159 * Calculate amount transferred via DMA
1160 */
1161 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
1162 host->dma.transferred += transferred;
1163
1164 /*
1165 * Schedule DMA transfer off board
1166 */
1167 if (host->dma.direction == DMA_IN) {
1168 host->dma.xfer_start = host->dma.start_addr;
1169 host->dma.xfer_length = transferred;
1170 host->dma.xfer_ptr = host->scsi.SCp.ptr;
1171 host->dma.xfer_required = 1;
1172 }
1173
1174 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
1175
1176 /*
1177 * Allocate some buffer space, limited to half the on-board RAM size
1178 */
1179 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
1180 if (length) {
1181 host->dma.start_addr = address = host->dma.free_addr;
1182 host->dma.free_addr = (host->dma.free_addr + length) &
1183 (DMAC_BUFFER_SIZE - 1);
1184
1185 /*
1186 * Transfer data to DMA memory
1187 */
1188 if (host->dma.direction == DMA_OUT)
1189 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
1190 length);
1191
1192 length -= 1;
1193 dmac_write(host->dma.io_port, DMAC_TXCNTLO, length);
1194 dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8);
1195 dmac_write(host->dma.io_port, DMAC_TXADRLO, address);
1196 dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8);
1197 dmac_write(host->dma.io_port, DMAC_TXADRHI, 0);
1198 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF);
1199
1200#if (DEBUG & DEBUG_DMA)
1201 DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
1202#endif
1203 } else {
1204 host->dma.xfer_setup = 0;
1205#if 0
1206 /*
1207 * If the interface still wants more, then this is an error.
1208 * We give it another byte, but we also attempt to raise an
1209 * attention condition. We continue giving one byte until
1210 * the device recognises the attention.
1211 */
1212 if (dmac_read(host->dma.io_port, DMAC_STATUS) & STATUS_RQ0) {
1213 acornscsi_abortcmd(host, host->SCpnt->tag);
1214
1215 dmac_write(host->dma.io_port, DMAC_TXCNTLO, 0);
1216 dmac_write(host->dma.io_port, DMAC_TXCNTHI, 0);
1217 dmac_write(host->dma.io_port, DMAC_TXADRLO, 0);
1218 dmac_write(host->dma.io_port, DMAC_TXADRMD, 0);
1219 dmac_write(host->dma.io_port, DMAC_TXADRHI, 0);
1220 dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF);
1221 }
1222#endif
1223 }
1224}
1225
1226/*
1227 * Function: void acornscsi_dma_xfer(AS_Host *host)
1228 * Purpose : transfer data between AcornSCSI and memory
1229 * Params : host - host to process
1230 */
1231static
1232void acornscsi_dma_xfer(AS_Host *host)
1233{
1234 host->dma.xfer_required = 0;
1235
1236 if (host->dma.direction == DMA_IN)
1237 acornscsi_data_read(host, host->dma.xfer_ptr,
1238 host->dma.xfer_start, host->dma.xfer_length);
1239}
1240
1241/*
1242 * Function: void acornscsi_dma_adjust(AS_Host *host)
1243 * Purpose : adjust DMA pointers & count for bytes transferred to
1244 * SBIC but not SCSI bus.
1245 * Params : host - host to adjust DMA count for
1246 */
1247static
1248void acornscsi_dma_adjust(AS_Host *host)
1249{
1250 if (host->dma.xfer_setup) {
1251 signed long transferred;
1252#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1253 DBG(host->SCpnt, acornscsi_dumpdma(host, "adji"));
1254#endif
1255 /*
1256 * Calculate correct DMA address - DMA is ahead of SCSI bus while
1257 * writing.
1258 * host->scsi.SCp.scsi_xferred is the number of bytes
1259 * actually transferred to/from the SCSI bus.
1260 * host->dma.transferred is the number of bytes transferred
1261 * over DMA since host->dma.start_addr was last set.
1262 *
1263 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
1264 * - host->dma.transferred
1265 */
1266 transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
1267 if (transferred < 0)
1268 printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
1269 host->host->host_no, acornscsi_target(host), transferred);
1270 else if (transferred == 0)
1271 host->dma.xfer_setup = 0;
1272 else {
1273 transferred += host->dma.start_addr;
1274 dmac_write(host->dma.io_port, DMAC_TXADRLO, transferred);
1275 dmac_write(host->dma.io_port, DMAC_TXADRMD, transferred >> 8);
1276 dmac_write(host->dma.io_port, DMAC_TXADRHI, transferred >> 16);
1277#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
1278 DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo"));
1279#endif
1280 }
1281 }
1282}
1283#endif
1284
1285/* =========================================================================================
1286 * Data I/O
1287 */
1288static int
1289acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
1290{
1291 unsigned int asr, timeout = max_timeout;
1292 int my_ptr = *ptr;
1293
1294 while (my_ptr < len) {
1295 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
1296
1297 if (asr & ASR_DBR) {
1298 timeout = max_timeout;
1299
1300 sbic_arm_write(host->scsi.io_port, SBIC_DATA, bytes[my_ptr++]);
1301 } else if (asr & ASR_INT)
1302 break;
1303 else if (--timeout == 0)
1304 break;
1305 udelay(1);
1306 }
1307
1308 *ptr = my_ptr;
1309
1310 return (timeout == 0) ? -1 : 0;
1311}
1312
1313/*
1314 * Function: void acornscsi_sendcommand(AS_Host *host)
1315 * Purpose : send a command to a target
1316 * Params : host - host which is connected to target
1317 */
1318static void
1319acornscsi_sendcommand(AS_Host *host)
1320{
1321 Scsi_Cmnd *SCpnt = host->SCpnt;
1322
1323 sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0);
1324 sbic_arm_writenext(host->scsi.io_port, 0);
1325 sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
1326
1327 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1328
1329 if (acornscsi_write_pio(host, SCpnt->cmnd,
1330 (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000))
1331 printk("scsi%d: timeout while sending command\n", host->host->host_no);
1332
1333 host->scsi.phase = PHASE_COMMAND;
1334}
1335
1336static
1337void acornscsi_sendmessage(AS_Host *host)
1338{
1339 unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
1340 unsigned int msgnr;
1341 struct message *msg;
1342
1343#if (DEBUG & DEBUG_MESSAGES)
1344 printk("scsi%d.%c: sending message ",
1345 host->host->host_no, acornscsi_target(host));
1346#endif
1347
1348 switch (message_length) {
1349 case 0:
1350 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1351
1352 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
1353
1354 sbic_arm_write(host->scsi.io_port, SBIC_DATA, NOP);
1355
1356 host->scsi.last_message = NOP;
1357#if (DEBUG & DEBUG_MESSAGES)
1358 printk("NOP");
1359#endif
1360 break;
1361
1362 case 1:
1363 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1364 msg = msgqueue_getmsg(&host->scsi.msgs, 0);
1365
1366 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
1367
1368 sbic_arm_write(host->scsi.io_port, SBIC_DATA, msg->msg[0]);
1369
1370 host->scsi.last_message = msg->msg[0];
1371#if (DEBUG & DEBUG_MESSAGES)
1372 print_msg(msg->msg);
1373#endif
1374 break;
1375
1376 default:
1377 /*
1378 * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14)
1379 * 'When a target sends this (MESSAGE_REJECT) message, it
1380 * shall change to MESSAGE IN phase and send this message
1381 * prior to requesting additional message bytes from the
1382 * initiator. This provides an interlock so that the
1383 * initiator can determine which message byte is rejected.
1384 */
1385 sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0);
1386 sbic_arm_writenext(host->scsi.io_port, 0);
1387 sbic_arm_writenext(host->scsi.io_port, message_length);
1388 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1389
1390 msgnr = 0;
1391 while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
1392 unsigned int i;
1393#if (DEBUG & DEBUG_MESSAGES)
1394 print_msg(msg);
1395#endif
1396 i = 0;
1397 if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
1398 printk("scsi%d: timeout while sending message\n", host->host->host_no);
1399
1400 host->scsi.last_message = msg->msg[0];
1401 if (msg->msg[0] == EXTENDED_MESSAGE)
1402 host->scsi.last_message |= msg->msg[2] << 8;
1403
1404 if (i != msg->length)
1405 break;
1406 }
1407 break;
1408 }
1409#if (DEBUG & DEBUG_MESSAGES)
1410 printk("\n");
1411#endif
1412}
1413
1414/*
1415 * Function: void acornscsi_readstatusbyte(AS_Host *host)
1416 * Purpose : Read status byte from connected target
1417 * Params : host - host connected to target
1418 */
1419static
1420void acornscsi_readstatusbyte(AS_Host *host)
1421{
1422 acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT);
1423 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte");
1424 host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, SBIC_DATA);
1425}
1426
1427/*
1428 * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
1429 * Purpose : Read one message byte from connected target
1430 * Params : host - host connected to target
1431 */
1432static
1433unsigned char acornscsi_readmessagebyte(AS_Host *host)
1434{
1435 unsigned char message;
1436
1437 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
1438
1439 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
1440
1441 message = sbic_arm_read(host->scsi.io_port, SBIC_DATA);
1442
1443 /* wait for MSGIN-XFER-PAUSED */
1444 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
1445
1446 sbic_arm_read(host->scsi.io_port, SBIC_SSR);
1447
1448 return message;
1449}
1450
1451/*
1452 * Function: void acornscsi_message(AS_Host *host)
1453 * Purpose : Read complete message from connected target & action message
1454 * Params : host - host connected to target
1455 */
1456static
1457void acornscsi_message(AS_Host *host)
1458{
1459 unsigned char message[16];
1460 unsigned int msgidx = 0, msglen = 1;
1461
1462 do {
1463 message[msgidx] = acornscsi_readmessagebyte(host);
1464
1465 switch (msgidx) {
1466 case 0:
1467 if (message[0] == EXTENDED_MESSAGE ||
1468 (message[0] >= 0x20 && message[0] <= 0x2f))
1469 msglen = 2;
1470 break;
1471
1472 case 1:
1473 if (message[0] == EXTENDED_MESSAGE)
1474 msglen += message[msgidx];
1475 break;
1476 }
1477 msgidx += 1;
1478 if (msgidx < msglen) {
1479 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1480
1481 /* wait for next msg-in */
1482 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack");
1483 sbic_arm_read(host->scsi.io_port, SBIC_SSR);
1484 }
1485 } while (msgidx < msglen);
1486
1487#if (DEBUG & DEBUG_MESSAGES)
1488 printk("scsi%d.%c: message in: ",
1489 host->host->host_no, acornscsi_target(host));
1490 print_msg(message);
1491 printk("\n");
1492#endif
1493
1494 if (host->scsi.phase == PHASE_RECONNECTED) {
1495 /*
1496 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1497 * 'Whenever a target reconnects to an initiator to continue
1498 * a tagged I/O process, the SIMPLE QUEUE TAG message shall
1499 * be sent immediately following the IDENTIFY message...'
1500 */
1501 if (message[0] == SIMPLE_QUEUE_TAG)
1502 host->scsi.reconnected.tag = message[1];
1503 if (acornscsi_reconnect_finish(host))
1504 host->scsi.phase = PHASE_MSGIN;
1505 }
1506
1507 switch (message[0]) {
1508 case ABORT:
1509 case ABORT_TAG:
1510 case COMMAND_COMPLETE:
1511 if (host->scsi.phase != PHASE_STATUSIN) {
1512 printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
1513 host->host->host_no, acornscsi_target(host));
1514 acornscsi_dumplog(host, host->SCpnt->device->id);
1515 }
1516 host->scsi.phase = PHASE_DONE;
1517 host->scsi.SCp.Message = message[0];
1518 break;
1519
1520 case SAVE_POINTERS:
1521 /*
1522 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20)
1523 * 'The SAVE DATA POINTER message is sent from a target to
1524 * direct the initiator to copy the active data pointer to
1525 * the saved data pointer for the current I/O process.
1526 */
1527 acornscsi_dma_cleanup(host);
1528 host->SCpnt->SCp = host->scsi.SCp;
1529 host->SCpnt->SCp.sent_command = 0;
1530 host->scsi.phase = PHASE_MSGIN;
1531 break;
1532
1533 case RESTORE_POINTERS:
1534 /*
1535 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19)
1536 * 'The RESTORE POINTERS message is sent from a target to
1537 * direct the initiator to copy the most recently saved
1538 * command, data, and status pointers for the I/O process
1539 * to the corresponding active pointers. The command and
1540 * status pointers shall be restored to the beginning of
1541 * the present command and status areas.'
1542 */
1543 acornscsi_dma_cleanup(host);
1544 host->scsi.SCp = host->SCpnt->SCp;
1545 host->scsi.phase = PHASE_MSGIN;
1546 break;
1547
1548 case DISCONNECT:
1549 /*
1550 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2)
1551 * 'On those occasions when an error or exception condition occurs
1552 * and the target elects to repeat the information transfer, the
1553 * target may repeat the transfer either issuing a RESTORE POINTERS
1554 * message or by disconnecting without issuing a SAVE POINTERS
1555 * message. When reconnection is completed, the most recent
1556 * saved pointer values are restored.'
1557 */
1558 acornscsi_dma_cleanup(host);
1559 host->scsi.phase = PHASE_DISCONNECT;
1560 break;
1561
1562 case MESSAGE_REJECT:
1563#if 0 /* this isn't needed any more */
1564 /*
1565 * If we were negociating sync transfer, we don't yet know if
1566 * this REJECT is for the sync transfer or for the tagged queue/wide
1567 * transfer. Re-initiate sync transfer negociation now, and if
1568 * we got a REJECT in response to SDTR, then it'll be set to DONE.
1569 */
1570 if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST)
1571 host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE;
1572#endif
1573
1574 /*
1575 * If we have any messages waiting to go out, then assert ATN now
1576 */
1577 if (msgqueue_msglength(&host->scsi.msgs))
1578 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1579
1580 switch (host->scsi.last_message) {
1581#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1582 case HEAD_OF_QUEUE_TAG:
1583 case ORDERED_QUEUE_TAG:
1584 case SIMPLE_QUEUE_TAG:
1585 /*
1586 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17)
1587 * If a target does not implement tagged queuing and a queue tag
1588 * message is received, it shall respond with a MESSAGE REJECT
1589 * message and accept the I/O process as if it were untagged.
1590 */
1591 printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
1592 host->host->host_no, acornscsi_target(host));
1593 host->SCpnt->device->simple_tags = 0;
1594 set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
1595 break;
1596#endif
1597 case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
1598 /*
1599 * Target can't handle synchronous transfers
1600 */
1601 printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
1602 host->host->host_no, acornscsi_target(host));
1603 host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA;
1604 host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS;
1605 sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1606 break;
1607
1608 default:
1609 break;
1610 }
1611 break;
1612
1613 case QUEUE_FULL:
1614 /* TODO: target queue is full */
1615 break;
1616
1617 case SIMPLE_QUEUE_TAG:
1618 /* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */
1619 printk("scsi%d.%c: reconnect queue tag %02X\n",
1620 host->host->host_no, acornscsi_target(host),
1621 message[1]);
1622 break;
1623
1624 case EXTENDED_MESSAGE:
1625 switch (message[2]) {
1626#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1627 case EXTENDED_SDTR:
1628 if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) {
1629 /*
1630 * We requested synchronous transfers. This isn't quite right...
1631 * We can only say if this succeeded if we proceed on to execute the
1632 * command from this message. If we get a MESSAGE PARITY ERROR,
1633 * and the target retries fail, then we fallback to asynchronous mode
1634 */
1635 host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED;
1636 printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
1637 host->host->host_no, acornscsi_target(host),
1638 message[4], message[3] * 4);
1639 host->device[host->SCpnt->device->id].sync_xfer =
1640 calc_sync_xfer(message[3] * 4, message[4]);
1641 } else {
1642 unsigned char period, length;
1643 /*
1644 * Target requested synchronous transfers. The agreement is only
1645 * to be in operation AFTER the target leaves message out phase.
1646 */
1647 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1648 period = max_t(unsigned int, message[3], sdtr_period / 4);
1649 length = min_t(unsigned int, message[4], sdtr_size);
1650 msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
1651 EXTENDED_SDTR, period, length);
1652 host->device[host->SCpnt->device->id].sync_xfer =
1653 calc_sync_xfer(period * 4, length);
1654 }
1655 sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1656 break;
1657#else
1658 /* We do not accept synchronous transfers. Respond with a
1659 * MESSAGE_REJECT.
1660 */
1661#endif
1662
1663 case EXTENDED_WDTR:
1664 /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT
1665 * to a wide data transfer request.
1666 */
1667 default:
1668 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1669 msgqueue_flush(&host->scsi.msgs);
1670 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1671 break;
1672 }
1673 break;
1674
1675#ifdef CONFIG_SCSI_ACORNSCSI_LINK
1676 case LINKED_CMD_COMPLETE:
1677 case LINKED_FLG_CMD_COMPLETE:
1678 /*
1679 * We don't support linked commands yet
1680 */
1681 if (0) {
1682#if (DEBUG & DEBUG_LINK)
1683 printk("scsi%d.%c: lun %d tag %d linked command complete\n",
1684 host->host->host_no, acornscsi_target(host), host->SCpnt->tag);
1685#endif
1686 /*
1687 * A linked command should only terminate with one of these messages
1688 * if there are more linked commands available.
1689 */
1690 if (!host->SCpnt->next_link) {
1691 printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
1692 instance->host_no, acornscsi_target(host), host->SCpnt->tag);
1693 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1694 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1695 } else {
1696 Scsi_Cmnd *SCpnt = host->SCpnt;
1697
1698 acornscsi_dma_cleanup(host);
1699
1700 host->SCpnt = host->SCpnt->next_link;
1701 host->SCpnt->tag = SCpnt->tag;
1702 SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;
1703 SCpnt->done(SCpnt);
1704
1705 /* initialise host->SCpnt->SCp */
1706 }
1707 break;
1708 }
1709#endif
1710
1711 default: /* reject message */
1712 printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
1713 host->host->host_no, acornscsi_target(host),
1714 message[0]);
1715 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
1716 msgqueue_flush(&host->scsi.msgs);
1717 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
1718 host->scsi.phase = PHASE_MSGIN;
1719 break;
1720 }
1721 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1722}
1723
1724/*
1725 * Function: int acornscsi_buildmessages(AS_Host *host)
1726 * Purpose : build the connection messages for a host
1727 * Params : host - host to add messages to
1728 */
1729static
1730void acornscsi_buildmessages(AS_Host *host)
1731{
1732#if 0
1733 /* does the device need resetting? */
1734 if (cmd_reset) {
1735 msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
1736 return;
1737 }
1738#endif
1739
1740 msgqueue_addmsg(&host->scsi.msgs, 1,
1741 IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok,
1742 host->SCpnt->device->lun));
1743
1744#if 0
1745 /* does the device need the current command aborted */
1746 if (cmd_aborted) {
1747 acornscsi_abortcmd(host->SCpnt->tag);
1748 return;
1749 }
1750#endif
1751
1752#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1753 if (host->SCpnt->tag) {
1754 unsigned int tag_type;
1755
1756 if (host->SCpnt->cmnd[0] == REQUEST_SENSE ||
1757 host->SCpnt->cmnd[0] == TEST_UNIT_READY ||
1758 host->SCpnt->cmnd[0] == INQUIRY)
1759 tag_type = HEAD_OF_QUEUE_TAG;
1760 else
1761 tag_type = SIMPLE_QUEUE_TAG;
1762 msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
1763 }
1764#endif
1765
1766#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
1767 if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) {
1768 host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST;
1769 msgqueue_addmsg(&host->scsi.msgs, 5,
1770 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1771 sdtr_period / 4, sdtr_size);
1772 }
1773#endif
1774}
1775
1776/*
1777 * Function: int acornscsi_starttransfer(AS_Host *host)
1778 * Purpose : transfer data to/from connected target
1779 * Params : host - host to which target is connected
1780 * Returns : 0 if failure
1781 */
1782static
1783int acornscsi_starttransfer(AS_Host *host)
1784{
1785 int residual;
1786
1787 if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {
1788 printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
1789 host->host->host_no, acornscsi_target(host));
1790 return 0;
1791 }
1792
1793 residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
1794
1795 sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
1796 sbic_arm_writenext(host->scsi.io_port, residual >> 16);
1797 sbic_arm_writenext(host->scsi.io_port, residual >> 8);
1798 sbic_arm_writenext(host->scsi.io_port, residual);
1799 acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
1800 return 1;
1801}
1802
1803/* =========================================================================================
1804 * Connection & Disconnection
1805 */
1806/*
1807 * Function : acornscsi_reconnect(AS_Host *host)
1808 * Purpose : reconnect a previously disconnected command
1809 * Params : host - host specific data
1810 * Remarks : SCSI spec says:
1811 * 'The set of active pointers is restored from the set
1812 * of saved pointers upon reconnection of the I/O process'
1813 */
1814static
1815int acornscsi_reconnect(AS_Host *host)
1816{
1817 unsigned int target, lun, ok = 0;
1818
1819 target = sbic_arm_read(host->scsi.io_port, SBIC_SOURCEID);
1820
1821 if (!(target & 8))
1822 printk(KERN_ERR "scsi%d: invalid source id after reselection "
1823 "- device fault?\n",
1824 host->host->host_no);
1825
1826 target &= 7;
1827
1828 if (host->SCpnt && !host->scsi.disconnectable) {
1829 printk(KERN_ERR "scsi%d.%d: reconnected while command in "
1830 "progress to target %d?\n",
1831 host->host->host_no, target, host->SCpnt->device->id);
1832 host->SCpnt = NULL;
1833 }
1834
1835 lun = sbic_arm_read(host->scsi.io_port, SBIC_DATA) & 7;
1836
1837 host->scsi.reconnected.target = target;
1838 host->scsi.reconnected.lun = lun;
1839 host->scsi.reconnected.tag = 0;
1840
1841 if (host->scsi.disconnectable && host->SCpnt &&
1842 host->SCpnt->device->id == target && host->SCpnt->device->lun == lun)
1843 ok = 1;
1844
1845 if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
1846 ok = 1;
1847
1848 ADD_STATUS(target, 0x81, host->scsi.phase, 0);
1849
1850 if (ok) {
1851 host->scsi.phase = PHASE_RECONNECTED;
1852 } else {
1853 /* this doesn't seem to work */
1854 printk(KERN_ERR "scsi%d.%c: reselected with no command "
1855 "to reconnect with\n",
1856 host->host->host_no, '0' + target);
1857 acornscsi_dumplog(host, target);
1858 acornscsi_abortcmd(host, 0);
1859 if (host->SCpnt) {
1860 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1861 host->SCpnt = NULL;
1862 }
1863 }
1864 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
1865 return !ok;
1866}
1867
1868/*
1869 * Function: int acornscsi_reconect_finish(AS_Host *host)
1870 * Purpose : finish reconnecting a command
1871 * Params : host - host to complete
1872 * Returns : 0 if failed
1873 */
1874static
1875int acornscsi_reconnect_finish(AS_Host *host)
1876{
1877 if (host->scsi.disconnectable && host->SCpnt) {
1878 host->scsi.disconnectable = 0;
1879 if (host->SCpnt->device->id == host->scsi.reconnected.target &&
1880 host->SCpnt->device->lun == host->scsi.reconnected.lun &&
1881 host->SCpnt->tag == host->scsi.reconnected.tag) {
1882#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1883 DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
1884 host->host->host_no, acornscsi_target(host)));
1885#endif
1886 } else {
1887 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
1888#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1889 DBG(host->SCpnt, printk("scsi%d.%c: had to move command "
1890 "to disconnected queue\n",
1891 host->host->host_no, acornscsi_target(host)));
1892#endif
1893 host->SCpnt = NULL;
1894 }
1895 }
1896 if (!host->SCpnt) {
1897 host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected,
1898 host->scsi.reconnected.target,
1899 host->scsi.reconnected.lun,
1900 host->scsi.reconnected.tag);
1901#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1902 DBG(host->SCpnt, printk("scsi%d.%c: had to get command",
1903 host->host->host_no, acornscsi_target(host)));
1904#endif
1905 }
1906
1907 if (!host->SCpnt)
1908 acornscsi_abortcmd(host, host->scsi.reconnected.tag);
1909 else {
1910 /*
1911 * Restore data pointer from SAVED pointers.
1912 */
1913 host->scsi.SCp = host->SCpnt->SCp;
1914#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1915 printk(", data pointers: [%p, %X]",
1916 host->scsi.SCp.ptr, host->scsi.SCp.this_residual);
1917#endif
1918 }
1919#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
1920 printk("\n");
1921#endif
1922
1923 host->dma.transferred = host->scsi.SCp.scsi_xferred;
1924
1925 return host->SCpnt != NULL;
1926}
1927
1928/*
1929 * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
1930 * Purpose : handle an unexpected disconnect
1931 * Params : host - host on which disconnect occurred
1932 */
1933static
1934void acornscsi_disconnect_unexpected(AS_Host *host)
1935{
1936 printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n",
1937 host->host->host_no, acornscsi_target(host));
1938#if (DEBUG & DEBUG_ABORT)
1939 acornscsi_dumplog(host, 8);
1940#endif
1941
1942 acornscsi_done(host, &host->SCpnt, DID_ERROR);
1943}
1944
1945/*
1946 * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
1947 * Purpose : abort a currently executing command
1948 * Params : host - host with connected command to abort
1949 * tag - tag to abort
1950 */
1951static
1952void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
1953{
1954 host->scsi.phase = PHASE_ABORTED;
1955 sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_ASSERTATN);
1956
1957 msgqueue_flush(&host->scsi.msgs);
1958#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
1959 if (tag)
1960 msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
1961 else
1962#endif
1963 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
1964}
1965
1966/* ==========================================================================================
1967 * Interrupt routines.
1968 */
1969/*
1970 * Function: int acornscsi_sbicintr(AS_Host *host)
1971 * Purpose : handle interrupts from SCSI device
1972 * Params : host - host to process
1973 * Returns : INTR_PROCESS if expecting another SBIC interrupt
1974 * INTR_IDLE if no interrupt
1975 * INTR_NEXT_COMMAND if we have finished processing the command
1976 */
1977static
1978intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
1979{
1980 unsigned int asr, ssr;
1981
1982 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
1983 if (!(asr & ASR_INT))
1984 return INTR_IDLE;
1985
1986 ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR);
1987
1988#if (DEBUG & DEBUG_PHASES)
1989 print_sbic_status(asr, ssr, host->scsi.phase);
1990#endif
1991
1992 ADD_STATUS(8, ssr, host->scsi.phase, in_irq);
1993
1994 if (host->SCpnt && !host->scsi.disconnectable)
1995 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
1996
1997 switch (ssr) {
1998 case 0x00: /* reset state - not advanced */
1999 printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
2000 host->host->host_no);
2001 /* setup sbic - WD33C93A */
2002 sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id);
2003 sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET);
2004 return INTR_IDLE;
2005
2006 case 0x01: /* reset state - advanced */
2007 sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI);
2008 sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME);
2009 sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
2010 sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP);
2011 msgqueue_flush(&host->scsi.msgs);
2012 return INTR_IDLE;
2013
2014 case 0x41: /* unexpected disconnect aborted command */
2015 acornscsi_disconnect_unexpected(host);
2016 return INTR_NEXT_COMMAND;
2017 }
2018
2019 switch (host->scsi.phase) {
2020 case PHASE_CONNECTING: /* STATE: command removed from issue queue */
2021 switch (ssr) {
2022 case 0x11: /* -> PHASE_CONNECTED */
2023 /* BUS FREE -> SELECTION */
2024 host->scsi.phase = PHASE_CONNECTED;
2025 msgqueue_flush(&host->scsi.msgs);
2026 host->dma.transferred = host->scsi.SCp.scsi_xferred;
2027 /* 33C93 gives next interrupt indicating bus phase */
2028 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
2029 if (!(asr & ASR_INT))
2030 break;
2031 ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR);
2032 ADD_STATUS(8, ssr, host->scsi.phase, 1);
2033 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1);
2034 goto connected;
2035
2036 case 0x42: /* select timed out */
2037 /* -> PHASE_IDLE */
2038 acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
2039 return INTR_NEXT_COMMAND;
2040
2041 case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2042 /* BUS FREE -> RESELECTION */
2043 host->origSCpnt = host->SCpnt;
2044 host->SCpnt = NULL;
2045 msgqueue_flush(&host->scsi.msgs);
2046 acornscsi_reconnect(host);
2047 break;
2048
2049 default:
2050 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
2051 host->host->host_no, acornscsi_target(host), ssr);
2052 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2053 acornscsi_abortcmd(host, host->SCpnt->tag);
2054 }
2055 return INTR_PROCESSING;
2056
2057 connected:
2058 case PHASE_CONNECTED: /* STATE: device selected ok */
2059 switch (ssr) {
2060#ifdef NONSTANDARD
2061 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2062 /* SELECTION -> COMMAND */
2063 acornscsi_sendcommand(host);
2064 break;
2065
2066 case 0x8b: /* -> PHASE_STATUS */
2067 /* SELECTION -> STATUS */
2068 acornscsi_readstatusbyte(host);
2069 host->scsi.phase = PHASE_STATUSIN;
2070 break;
2071#endif
2072
2073 case 0x8e: /* -> PHASE_MSGOUT */
2074 /* SELECTION ->MESSAGE OUT */
2075 host->scsi.phase = PHASE_MSGOUT;
2076 acornscsi_buildmessages(host);
2077 acornscsi_sendmessage(host);
2078 break;
2079
2080 /* these should not happen */
2081 case 0x85: /* target disconnected */
2082 acornscsi_done(host, &host->SCpnt, DID_ERROR);
2083 break;
2084
2085 default:
2086 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
2087 host->host->host_no, acornscsi_target(host), ssr);
2088 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2089 acornscsi_abortcmd(host, host->SCpnt->tag);
2090 }
2091 return INTR_PROCESSING;
2092
2093 case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */
2094 /*
2095 * SCSI standard says that MESSAGE OUT phases can be followed by a
2096 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
2097 */
2098 switch (ssr) {
2099 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2100 case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2101 /* MESSAGE OUT -> COMMAND */
2102 acornscsi_sendcommand(host);
2103 break;
2104
2105 case 0x8b: /* -> PHASE_STATUS */
2106 case 0x1b: /* -> PHASE_STATUS */
2107 /* MESSAGE OUT -> STATUS */
2108 acornscsi_readstatusbyte(host);
2109 host->scsi.phase = PHASE_STATUSIN;
2110 break;
2111
2112 case 0x8e: /* -> PHASE_MSGOUT */
2113 /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
2114 acornscsi_sendmessage(host);
2115 break;
2116
2117 case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2118 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2119 /* MESSAGE OUT -> MESSAGE IN */
2120 acornscsi_message(host);
2121 break;
2122
2123 default:
2124 printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
2125 host->host->host_no, acornscsi_target(host), ssr);
2126 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2127 }
2128 return INTR_PROCESSING;
2129
2130 case PHASE_COMMAND: /* STATE: connected & command sent */
2131 switch (ssr) {
2132 case 0x18: /* -> PHASE_DATAOUT */
2133 /* COMMAND -> DATA OUT */
2134 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2135 acornscsi_abortcmd(host, host->SCpnt->tag);
2136 acornscsi_dma_setup(host, DMA_OUT);
2137 if (!acornscsi_starttransfer(host))
2138 acornscsi_abortcmd(host, host->SCpnt->tag);
2139 host->scsi.phase = PHASE_DATAOUT;
2140 return INTR_IDLE;
2141
2142 case 0x19: /* -> PHASE_DATAIN */
2143 /* COMMAND -> DATA IN */
2144 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
2145 acornscsi_abortcmd(host, host->SCpnt->tag);
2146 acornscsi_dma_setup(host, DMA_IN);
2147 if (!acornscsi_starttransfer(host))
2148 acornscsi_abortcmd(host, host->SCpnt->tag);
2149 host->scsi.phase = PHASE_DATAIN;
2150 return INTR_IDLE;
2151
2152 case 0x1b: /* -> PHASE_STATUS */
2153 /* COMMAND -> STATUS */
2154 acornscsi_readstatusbyte(host);
2155 host->scsi.phase = PHASE_STATUSIN;
2156 break;
2157
2158 case 0x1e: /* -> PHASE_MSGOUT */
2159 /* COMMAND -> MESSAGE OUT */
2160 acornscsi_sendmessage(host);
2161 break;
2162
2163 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2164 /* COMMAND -> MESSAGE IN */
2165 acornscsi_message(host);
2166 break;
2167
2168 default:
2169 printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
2170 host->host->host_no, acornscsi_target(host), ssr);
2171 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2172 }
2173 return INTR_PROCESSING;
2174
2175 case PHASE_DISCONNECT: /* STATE: connected, received DISCONNECT msg */
2176 if (ssr == 0x85) { /* -> PHASE_IDLE */
2177 host->scsi.disconnectable = 1;
2178 host->scsi.reconnected.tag = 0;
2179 host->scsi.phase = PHASE_IDLE;
2180 host->stats.disconnects += 1;
2181 } else {
2182 printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
2183 host->host->host_no, acornscsi_target(host), ssr);
2184 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2185 }
2186 return INTR_NEXT_COMMAND;
2187
2188 case PHASE_IDLE: /* STATE: disconnected */
2189 if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */
2190 acornscsi_reconnect(host);
2191 else {
2192 printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
2193 host->host->host_no, acornscsi_target(host), ssr);
2194 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2195 }
2196 return INTR_PROCESSING;
2197
2198 case PHASE_RECONNECTED: /* STATE: device reconnected to initiator */
2199 /*
2200 * Command reconnected - if MESGIN, get message - it may be
2201 * the tag. If not, get command out of disconnected queue
2202 */
2203 /*
2204 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
2205 * reconnect I_T_L command
2206 */
2207 if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
2208 return INTR_IDLE;
2209 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
2210 switch (ssr) {
2211 case 0x88: /* data out phase */
2212 /* -> PHASE_DATAOUT */
2213 /* MESSAGE IN -> DATA OUT */
2214 acornscsi_dma_setup(host, DMA_OUT);
2215 if (!acornscsi_starttransfer(host))
2216 acornscsi_abortcmd(host, host->SCpnt->tag);
2217 host->scsi.phase = PHASE_DATAOUT;
2218 return INTR_IDLE;
2219
2220 case 0x89: /* data in phase */
2221 /* -> PHASE_DATAIN */
2222 /* MESSAGE IN -> DATA IN */
2223 acornscsi_dma_setup(host, DMA_IN);
2224 if (!acornscsi_starttransfer(host))
2225 acornscsi_abortcmd(host, host->SCpnt->tag);
2226 host->scsi.phase = PHASE_DATAIN;
2227 return INTR_IDLE;
2228
2229 case 0x8a: /* command out */
2230 /* MESSAGE IN -> COMMAND */
2231 acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
2232 break;
2233
2234 case 0x8b: /* status in */
2235 /* -> PHASE_STATUSIN */
2236 /* MESSAGE IN -> STATUS */
2237 acornscsi_readstatusbyte(host);
2238 host->scsi.phase = PHASE_STATUSIN;
2239 break;
2240
2241 case 0x8e: /* message out */
2242 /* -> PHASE_MSGOUT */
2243 /* MESSAGE IN -> MESSAGE OUT */
2244 acornscsi_sendmessage(host);
2245 break;
2246
2247 case 0x8f: /* message in */
2248 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2249 break;
2250
2251 default:
2252 printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
2253 host->host->host_no, acornscsi_target(host), ssr);
2254 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2255 }
2256 return INTR_PROCESSING;
2257
2258 case PHASE_DATAIN: /* STATE: transferred data in */
2259 /*
2260 * This is simple - if we disconnect then the DMA address & count is
2261 * correct.
2262 */
2263 switch (ssr) {
2264 case 0x19: /* -> PHASE_DATAIN */
2265 case 0x89: /* -> PHASE_DATAIN */
2266 acornscsi_abortcmd(host, host->SCpnt->tag);
2267 return INTR_IDLE;
2268
2269 case 0x1b: /* -> PHASE_STATUSIN */
2270 case 0x4b: /* -> PHASE_STATUSIN */
2271 case 0x8b: /* -> PHASE_STATUSIN */
2272 /* DATA IN -> STATUS */
2273 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2274 acornscsi_sbic_xfcount(host);
2275 acornscsi_dma_stop(host);
2276 acornscsi_readstatusbyte(host);
2277 host->scsi.phase = PHASE_STATUSIN;
2278 break;
2279
2280 case 0x1e: /* -> PHASE_MSGOUT */
2281 case 0x4e: /* -> PHASE_MSGOUT */
2282 case 0x8e: /* -> PHASE_MSGOUT */
2283 /* DATA IN -> MESSAGE OUT */
2284 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2285 acornscsi_sbic_xfcount(host);
2286 acornscsi_dma_stop(host);
2287 acornscsi_sendmessage(host);
2288 break;
2289
2290 case 0x1f: /* message in */
2291 case 0x4f: /* message in */
2292 case 0x8f: /* message in */
2293 /* DATA IN -> MESSAGE IN */
2294 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2295 acornscsi_sbic_xfcount(host);
2296 acornscsi_dma_stop(host);
2297 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2298 break;
2299
2300 default:
2301 printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
2302 host->host->host_no, acornscsi_target(host), ssr);
2303 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2304 }
2305 return INTR_PROCESSING;
2306
2307 case PHASE_DATAOUT: /* STATE: transferred data out */
2308 /*
2309 * This is more complicated - if we disconnect, the DMA could be 12
2310 * bytes ahead of us. We need to correct this.
2311 */
2312 switch (ssr) {
2313 case 0x18: /* -> PHASE_DATAOUT */
2314 case 0x88: /* -> PHASE_DATAOUT */
2315 acornscsi_abortcmd(host, host->SCpnt->tag);
2316 return INTR_IDLE;
2317
2318 case 0x1b: /* -> PHASE_STATUSIN */
2319 case 0x4b: /* -> PHASE_STATUSIN */
2320 case 0x8b: /* -> PHASE_STATUSIN */
2321 /* DATA OUT -> STATUS */
2322 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2323 acornscsi_sbic_xfcount(host);
2324 acornscsi_dma_stop(host);
2325 acornscsi_dma_adjust(host);
2326 acornscsi_readstatusbyte(host);
2327 host->scsi.phase = PHASE_STATUSIN;
2328 break;
2329
2330 case 0x1e: /* -> PHASE_MSGOUT */
2331 case 0x4e: /* -> PHASE_MSGOUT */
2332 case 0x8e: /* -> PHASE_MSGOUT */
2333 /* DATA OUT -> MESSAGE OUT */
2334 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2335 acornscsi_sbic_xfcount(host);
2336 acornscsi_dma_stop(host);
2337 acornscsi_dma_adjust(host);
2338 acornscsi_sendmessage(host);
2339 break;
2340
2341 case 0x1f: /* message in */
2342 case 0x4f: /* message in */
2343 case 0x8f: /* message in */
2344 /* DATA OUT -> MESSAGE IN */
2345 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
2346 acornscsi_sbic_xfcount(host);
2347 acornscsi_dma_stop(host);
2348 acornscsi_dma_adjust(host);
2349 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
2350 break;
2351
2352 default:
2353 printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
2354 host->host->host_no, acornscsi_target(host), ssr);
2355 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2356 }
2357 return INTR_PROCESSING;
2358
2359 case PHASE_STATUSIN: /* STATE: status in complete */
2360 switch (ssr) {
2361 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2362 case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2363 /* STATUS -> MESSAGE IN */
2364 acornscsi_message(host);
2365 break;
2366
2367 case 0x1e: /* -> PHASE_MSGOUT */
2368 case 0x8e: /* -> PHASE_MSGOUT */
2369 /* STATUS -> MESSAGE OUT */
2370 acornscsi_sendmessage(host);
2371 break;
2372
2373 default:
2374 printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
2375 host->host->host_no, acornscsi_target(host), ssr);
2376 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2377 }
2378 return INTR_PROCESSING;
2379
2380 case PHASE_MSGIN: /* STATE: message in */
2381 switch (ssr) {
2382 case 0x1e: /* -> PHASE_MSGOUT */
2383 case 0x4e: /* -> PHASE_MSGOUT */
2384 case 0x8e: /* -> PHASE_MSGOUT */
2385 /* MESSAGE IN -> MESSAGE OUT */
2386 acornscsi_sendmessage(host);
2387 break;
2388
2389 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
2390 case 0x2f:
2391 case 0x4f:
2392 case 0x8f:
2393 acornscsi_message(host);
2394 break;
2395
2396 case 0x85:
2397 printk("scsi%d.%c: strange message in disconnection\n",
2398 host->host->host_no, acornscsi_target(host));
2399 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2400 acornscsi_done(host, &host->SCpnt, DID_ERROR);
2401 break;
2402
2403 default:
2404 printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
2405 host->host->host_no, acornscsi_target(host), ssr);
2406 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2407 }
2408 return INTR_PROCESSING;
2409
2410 case PHASE_DONE: /* STATE: received status & message */
2411 switch (ssr) {
2412 case 0x85: /* -> PHASE_IDLE */
2413 acornscsi_done(host, &host->SCpnt, DID_OK);
2414 return INTR_NEXT_COMMAND;
2415
2416 case 0x1e:
2417 case 0x8e:
2418 acornscsi_sendmessage(host);
2419 break;
2420
2421 default:
2422 printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
2423 host->host->host_no, acornscsi_target(host), ssr);
2424 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2425 }
2426 return INTR_PROCESSING;
2427
2428 case PHASE_ABORTED:
2429 switch (ssr) {
2430 case 0x85:
2431 if (host->SCpnt)
2432 acornscsi_done(host, &host->SCpnt, DID_ABORT);
2433 else {
2434 clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
2435 host->busyluns);
2436 host->scsi.phase = PHASE_IDLE;
2437 }
2438 return INTR_NEXT_COMMAND;
2439
2440 case 0x1e:
2441 case 0x2e:
2442 case 0x4e:
2443 case 0x8e:
2444 acornscsi_sendmessage(host);
2445 break;
2446
2447 default:
2448 printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
2449 host->host->host_no, acornscsi_target(host), ssr);
2450 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2451 }
2452 return INTR_PROCESSING;
2453
2454 default:
2455 printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
2456 host->host->host_no, acornscsi_target(host), ssr);
2457 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
2458 }
2459 return INTR_PROCESSING;
2460}
2461
2462/*
2463 * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
2464 * Purpose : handle interrupts from Acorn SCSI card
2465 * Params : irq - interrupt number
2466 * dev_id - device specific data (AS_Host structure)
2467 * regs - processor registers when interrupt occurred
2468 */
2469static irqreturn_t
2470acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
2471{
2472 AS_Host *host = (AS_Host *)dev_id;
2473 intr_ret_t ret;
2474 int iostatus;
2475 int in_irq = 0;
2476
2477 do {
2478 ret = INTR_IDLE;
2479
2480 iostatus = inb(host->card.io_intr);
2481
2482 if (iostatus & 2) {
2483 acornscsi_dma_intr(host);
2484 iostatus = inb(host->card.io_intr);
2485 }
2486
2487 if (iostatus & 8)
2488 ret = acornscsi_sbicintr(host, in_irq);
2489
2490 /*
2491 * If we have a transfer pending, start it.
2492 * Only start it if the interface has already started transferring
2493 * it's data
2494 */
2495 if (host->dma.xfer_required)
2496 acornscsi_dma_xfer(host);
2497
2498 if (ret == INTR_NEXT_COMMAND)
2499 ret = acornscsi_kick(host);
2500
2501 in_irq = 1;
2502 } while (ret != INTR_IDLE);
2503
2504 return IRQ_HANDLED;
2505}
2506
2507/*=============================================================================================
2508 * Interfaces between interrupt handler and rest of scsi code
2509 */
2510
2511/*
2512 * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
2513 * Purpose : queues a SCSI command
2514 * Params : cmd - SCSI command
2515 * done - function called on completion, with pointer to command descriptor
2516 * Returns : 0, or < 0 on error.
2517 */
2518int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2519{
2520 AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
2521
2522 if (!done) {
2523 /* there should be some way of rejecting errors like this without panicing... */
2524 panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
2525 host->host->host_no, SCpnt);
2526 return -EINVAL;
2527 }
2528
2529#if (DEBUG & DEBUG_NO_WRITE)
2530 if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) {
2531 printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
2532 host->host->host_no, '0' + SCpnt->device->id);
2533 SCpnt->result = DID_NO_CONNECT << 16;
2534 done(SCpnt);
2535 return 0;
2536 }
2537#endif
2538
2539 SCpnt->scsi_done = done;
2540 SCpnt->host_scribble = NULL;
2541 SCpnt->result = 0;
2542 SCpnt->tag = 0;
2543 SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
2544 SCpnt->SCp.sent_command = 0;
2545 SCpnt->SCp.scsi_xferred = 0;
2546
2547 init_SCp(SCpnt);
2548
2549 host->stats.queues += 1;
2550
2551 {
2552 unsigned long flags;
2553
2554 if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
2555 SCpnt->result = DID_ERROR << 16;
2556 done(SCpnt);
2557 return 0;
2558 }
2559 local_irq_save(flags);
2560 if (host->scsi.phase == PHASE_IDLE)
2561 acornscsi_kick(host);
2562 local_irq_restore(flags);
2563 }
2564 return 0;
2565}
2566
2567/*
2568 * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
2569 * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
2570 * Params : SCpntp1 - pointer to command to return
2571 * SCpntp2 - pointer to command to check
2572 * result - result to pass back to mid-level done function
2573 * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
2574 */
2575static inline
2576void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
2577{
2578 Scsi_Cmnd *SCpnt = *SCpntp1;
2579
2580 if (SCpnt) {
2581 *SCpntp1 = NULL;
2582
2583 SCpnt->result = result;
2584 SCpnt->scsi_done(SCpnt);
2585 }
2586
2587 if (SCpnt == *SCpntp2)
2588 *SCpntp2 = NULL;
2589}
2590
2591enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
2592
2593/*
2594 * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt)
2595 * Purpose : abort a command on this host
2596 * Params : SCpnt - command to abort
2597 * Returns : our abort status
2598 */
2599static enum res_abort
2600acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
2601{
2602 enum res_abort res = res_not_running;
2603
2604 if (queue_remove_cmd(&host->queues.issue, SCpnt)) {
2605 /*
2606 * The command was on the issue queue, and has not been
2607 * issued yet. We can remove the command from the queue,
2608 * and acknowledge the abort. Neither the devices nor the
2609 * interface know about the command.
2610 */
2611//#if (DEBUG & DEBUG_ABORT)
2612 printk("on issue queue ");
2613//#endif
2614 res = res_success;
2615 } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) {
2616 /*
2617 * The command was on the disconnected queue. Simply
2618 * acknowledge the abort condition, and when the target
2619 * reconnects, we will give it an ABORT message. The
2620 * target should then disconnect, and we will clear
2621 * the busylun bit.
2622 */
2623//#if (DEBUG & DEBUG_ABORT)
2624 printk("on disconnected queue ");
2625//#endif
2626 res = res_success;
2627 } else if (host->SCpnt == SCpnt) {
2628 unsigned long flags;
2629
2630//#if (DEBUG & DEBUG_ABORT)
2631 printk("executing ");
2632//#endif
2633
2634 local_irq_save(flags);
2635 switch (host->scsi.phase) {
2636 /*
2637 * If the interface is idle, and the command is 'disconnectable',
2638 * then it is the same as on the disconnected queue. We simply
2639 * remove all traces of the command. When the target reconnects,
2640 * we will give it an ABORT message since the command could not
2641 * be found. When the target finally disconnects, we will clear
2642 * the busylun bit.
2643 */
2644 case PHASE_IDLE:
2645 if (host->scsi.disconnectable) {
2646 host->scsi.disconnectable = 0;
2647 host->SCpnt = NULL;
2648 res = res_success;
2649 }
2650 break;
2651
2652 /*
2653 * If the command has connected and done nothing further,
2654 * simply force a disconnect. We also need to clear the
2655 * busylun bit.
2656 */
2657 case PHASE_CONNECTED:
2658 sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_DISCONNECT);
2659 host->SCpnt = NULL;
2660 res = res_success_clear;
2661 break;
2662
2663 default:
2664 acornscsi_abortcmd(host, host->SCpnt->tag);
2665 res = res_snooze;
2666 }
2667 local_irq_restore(flags);
2668 } else if (host->origSCpnt == SCpnt) {
2669 /*
2670 * The command will be executed next, but a command
2671 * is currently using the interface. This is similar to
2672 * being on the issue queue, except the busylun bit has
2673 * been set.
2674 */
2675 host->origSCpnt = NULL;
2676//#if (DEBUG & DEBUG_ABORT)
2677 printk("waiting for execution ");
2678//#endif
2679 res = res_success_clear;
2680 } else
2681 printk("unknown ");
2682
2683 return res;
2684}
2685
2686/*
2687 * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt)
2688 * Purpose : abort a command on this host
2689 * Params : SCpnt - command to abort
2690 * Returns : one of SCSI_ABORT_ macros
2691 */
2692int acornscsi_abort(Scsi_Cmnd *SCpnt)
2693{
2694 AS_Host *host = (AS_Host *) SCpnt->device->host->hostdata;
2695 int result;
2696
2697 host->stats.aborts += 1;
2698
2699#if (DEBUG & DEBUG_ABORT)
2700 {
2701 int asr, ssr;
2702 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
2703 ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR);
2704
2705 printk(KERN_WARNING "acornscsi_abort: ");
2706 print_sbic_status(asr, ssr, host->scsi.phase);
2707 acornscsi_dumplog(host, SCpnt->device->id);
2708 }
2709#endif
2710
2711 printk("scsi%d: ", host->host->host_no);
2712
2713 switch (acornscsi_do_abort(host, SCpnt)) {
2714 /*
2715 * We managed to find the command and cleared it out.
2716 * We do not expect the command to be executing on the
2717 * target, but we have set the busylun bit.
2718 */
2719 case res_success_clear:
2720//#if (DEBUG & DEBUG_ABORT)
2721 printk("clear ");
2722//#endif
2723 clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
2724
2725 /*
2726 * We found the command, and cleared it out. Either
2727 * the command is still known to be executing on the
2728 * target, or the busylun bit is not set.
2729 */
2730 case res_success:
2731//#if (DEBUG & DEBUG_ABORT)
2732 printk("success\n");
2733//#endif
2734 SCpnt->result = DID_ABORT << 16;
2735 SCpnt->scsi_done(SCpnt);
2736 result = SCSI_ABORT_SUCCESS;
2737 break;
2738
2739 /*
2740 * We did find the command, but unfortunately we couldn't
2741 * unhook it from ourselves. Wait some more, and if it
2742 * still doesn't complete, reset the interface.
2743 */
2744 case res_snooze:
2745//#if (DEBUG & DEBUG_ABORT)
2746 printk("snooze\n");
2747//#endif
2748 result = SCSI_ABORT_SNOOZE;
2749 break;
2750
2751 /*
2752 * The command could not be found (either because it completed,
2753 * or it got dropped.
2754 */
2755 default:
2756 case res_not_running:
2757 acornscsi_dumplog(host, SCpnt->device->id);
2758#if (DEBUG & DEBUG_ABORT)
2759 result = SCSI_ABORT_SNOOZE;
2760#else
2761 result = SCSI_ABORT_NOT_RUNNING;
2762#endif
2763//#if (DEBUG & DEBUG_ABORT)
2764 printk("not running\n");
2765//#endif
2766 break;
2767 }
2768
2769 return result;
2770}
2771
2772/*
2773 * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2774 * Purpose : reset a command on this host/reset this host
2775 * Params : SCpnt - command causing reset
2776 * result - what type of reset to perform
2777 * Returns : one of SCSI_RESET_ macros
2778 */
2779int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2780{
2781 AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
2782 Scsi_Cmnd *SCptr;
2783
2784 host->stats.resets += 1;
2785
2786#if (DEBUG & DEBUG_RESET)
2787 {
2788 int asr, ssr;
2789
2790 asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);
2791 ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR);
2792
2793 printk(KERN_WARNING "acornscsi_reset: ");
2794 print_sbic_status(asr, ssr, host->scsi.phase);
2795 acornscsi_dumplog(host, SCpnt->device->id);
2796 }
2797#endif
2798
2799 acornscsi_dma_stop(host);
2800
2801 SCptr = host->SCpnt;
2802
2803 /*
2804 * do hard reset. This resets all devices on this host, and so we
2805 * must set the reset status on all commands.
2806 */
2807 acornscsi_resetcard(host);
2808
2809 /*
2810 * report reset on commands current connected/disconnected
2811 */
2812 acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET);
2813
2814 while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
2815 acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET);
2816
2817 if (SCpnt) {
2818 SCpnt->result = DID_RESET << 16;
2819 SCpnt->scsi_done(SCpnt);
2820 }
2821
2822 return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
2823}
2824
2825/*==============================================================================================
2826 * initialisation & miscellaneous support
2827 */
2828
2829/*
2830 * Function: char *acornscsi_info(struct Scsi_Host *host)
2831 * Purpose : return a string describing this interface
2832 * Params : host - host to give information on
2833 * Returns : a constant string
2834 */
2835const
2836char *acornscsi_info(struct Scsi_Host *host)
2837{
2838 static char string[100], *p;
2839
2840 p = string;
2841
2842 p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d"
2843#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
2844 " SYNC"
2845#endif
2846#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
2847 " TAG"
2848#endif
2849#ifdef CONFIG_SCSI_ACORNSCSI_LINK
2850 " LINK"
2851#endif
2852#if (DEBUG & DEBUG_NO_WRITE)
2853 " NOWRITE ("NO_WRITE_STR")"
2854#endif
2855 , host->hostt->name, host->io_port, host->irq,
2856 VER_MAJOR, VER_MINOR, VER_PATCH);
2857 return string;
2858}
2859
2860int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
2861 int length, int inout)
2862{
2863 int pos, begin = 0, devidx;
2864 Scsi_Device *scd;
2865 AS_Host *host;
2866 char *p = buffer;
2867
2868 if (inout == 1)
2869 return -EINVAL;
2870
2871 host = (AS_Host *)instance->hostdata;
2872
2873 p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
2874#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
2875 " SYNC"
2876#endif
2877#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
2878 " TAG"
2879#endif
2880#ifdef CONFIG_SCSI_ACORNSCSI_LINK
2881 " LINK"
2882#endif
2883#if (DEBUG & DEBUG_NO_WRITE)
2884 " NOWRITE ("NO_WRITE_STR")"
2885#endif
2886 "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
2887
2888 p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n",
2889 host->scsi.io_port, host->scsi.irq);
2890#ifdef USE_DMAC
2891 p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n",
2892 host->dma.io_port, host->scsi.irq);
2893#endif
2894
2895 p += sprintf(p, "Statistics:\n"
2896 "Queued commands: %-10u Issued commands: %-10u\n"
2897 "Done commands : %-10u Reads : %-10u\n"
2898 "Writes : %-10u Others : %-10u\n"
2899 "Disconnects : %-10u Aborts : %-10u\n"
2900 "Resets : %-10u\n\nLast phases:",
2901 host->stats.queues, host->stats.removes,
2902 host->stats.fins, host->stats.reads,
2903 host->stats.writes, host->stats.miscs,
2904 host->stats.disconnects, host->stats.aborts,
2905 host->stats.resets);
2906
2907 for (devidx = 0; devidx < 9; devidx ++) {
2908 unsigned int statptr, prev;
2909
2910 p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
2911 statptr = host->status_ptr[devidx] - 10;
2912
2913 if ((signed int)statptr < 0)
2914 statptr += STATUS_BUFFER_SIZE;
2915
2916 prev = host->status[devidx][statptr].when;
2917
2918 for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
2919 if (host->status[devidx][statptr].when) {
2920 p += sprintf(p, "%c%02X:%02X+%2ld",
2921 host->status[devidx][statptr].irq ? '-' : ' ',
2922 host->status[devidx][statptr].ph,
2923 host->status[devidx][statptr].ssr,
2924 (host->status[devidx][statptr].when - prev) < 100 ?
2925 (host->status[devidx][statptr].when - prev) : 99);
2926 prev = host->status[devidx][statptr].when;
2927 }
2928 }
2929 }
2930
2931 p += sprintf(p, "\nAttached devices:\n");
2932
2933 shost_for_each_device(scd, instance) {
2934 p += sprintf(p, "Device/Lun TaggedQ Sync\n");
2935 p += sprintf(p, " %d/%d ", scd->id, scd->lun);
2936 if (scd->tagged_supported)
2937 p += sprintf(p, "%3sabled(%3d) ",
2938 scd->simple_tags ? "en" : "dis",
2939 scd->current_tag);
2940 else
2941 p += sprintf(p, "unsupported ");
2942
2943 if (host->device[scd->id].sync_xfer & 15)
2944 p += sprintf(p, "offset %d, %d ns\n",
2945 host->device[scd->id].sync_xfer & 15,
2946 acornscsi_getperiod(host->device[scd->id].sync_xfer));
2947 else
2948 p += sprintf(p, "async\n");
2949
2950 pos = p - buffer;
2951 if (pos + begin < offset) {
2952 begin += pos;
2953 p = buffer;
2954 }
2955 pos = p - buffer;
2956 if (pos + begin > offset + length) {
2957 scsi_device_put(scd);
2958 break;
2959 }
2960 }
2961
2962 pos = p - buffer;
2963
2964 *start = buffer + (offset - begin);
2965 pos -= offset - begin;
2966
2967 if (pos > length)
2968 pos = length;
2969
2970 return pos;
2971}
2972
2973static Scsi_Host_Template acornscsi_template = {
2974 .module = THIS_MODULE,
2975 .proc_info = acornscsi_proc_info,
2976 .name = "AcornSCSI",
2977 .info = acornscsi_info,
2978 .queuecommand = acornscsi_queuecmd,
2979#warning fixme
2980 .abort = acornscsi_abort,
2981 .reset = acornscsi_reset,
2982 .can_queue = 16,
2983 .this_id = 7,
2984 .sg_tablesize = SG_ALL,
2985 .cmd_per_lun = 2,
2986 .unchecked_isa_dma = 0,
2987 .use_clustering = DISABLE_CLUSTERING,
2988 .proc_name = "acornscsi",
2989};
2990
2991static int __devinit
2992acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
2993{
2994 struct Scsi_Host *host;
2995 AS_Host *ashost;
2996 int ret = -ENOMEM;
2997
2998 host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host));
2999 if (!host)
3000 goto out;
3001
3002 ashost = (AS_Host *)host->hostdata;
3003
3004 host->io_port = ecard_address(ec, ECARD_MEMC, 0);
3005 host->irq = ec->irq;
3006
3007 ashost->host = host;
3008 ashost->scsi.io_port = ioaddr(host->io_port + 0x800);
3009 ashost->scsi.irq = host->irq;
3010 ashost->card.io_intr = POD_SPACE(host->io_port) + 0x800;
3011 ashost->card.io_page = POD_SPACE(host->io_port) + 0xc00;
3012 ashost->card.io_ram = ioaddr(host->io_port);
3013 ashost->dma.io_port = host->io_port + 0xc00;
3014 ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800;
3015
3016 ec->irqaddr = (char *)ioaddr(ashost->card.io_intr);
3017 ec->irqmask = 0x0a;
3018
3019 ret = -EBUSY;
3020 if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)"))
3021 goto err_1;
3022 if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)"))
3023 goto err_2;
3024 if (!request_region(ashost->card.io_page, 1, "acornscsi(page)"))
3025 goto err_3;
3026#ifdef USE_DMAC
3027 if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)"))
3028 goto err_4;
3029#endif
3030 if (!request_region(host->io_port, 2048, "acornscsi(ram)"))
3031 goto err_5;
3032
3033 ret = request_irq(host->irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", ashost);
3034 if (ret) {
3035 printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n",
3036 host->host_no, ashost->scsi.irq, ret);
3037 goto err_6;
3038 }
3039
3040 memset(&ashost->stats, 0, sizeof (ashost->stats));
3041 queue_initialise(&ashost->queues.issue);
3042 queue_initialise(&ashost->queues.disconnected);
3043 msgqueue_initialise(&ashost->scsi.msgs);
3044
3045 acornscsi_resetcard(ashost);
3046
3047 ret = scsi_add_host(host, &ec->dev);
3048 if (ret)
3049 goto err_7;
3050
3051 scsi_scan_host(host);
3052 goto out;
3053
3054 err_7:
3055 free_irq(host->irq, ashost);
3056 err_6:
3057 release_region(host->io_port, 2048);
3058 err_5:
3059#ifdef USE_DMAC
3060 release_region(ashost->dma.io_port, 256);
3061#endif
3062 err_4:
3063 release_region(ashost->card.io_page, 1);
3064 err_3:
3065 release_region(ashost->card.io_intr, 1);
3066 err_2:
3067 release_region(host->io_port + 0x800, 2);
3068 err_1:
3069 scsi_host_put(host);
3070 out:
3071 return ret;
3072}
3073
3074static void __devexit acornscsi_remove(struct expansion_card *ec)
3075{
3076 struct Scsi_Host *host = ecard_get_drvdata(ec);
3077 AS_Host *ashost = (AS_Host *)host->hostdata;
3078
3079 ecard_set_drvdata(ec, NULL);
3080 scsi_remove_host(host);
3081
3082 /*
3083 * Put card into RESET state
3084 */
3085 outb(0x80, ashost->card.io_page);
3086
3087 free_irq(host->irq, ashost);
3088
3089 release_region(host->io_port + 0x800, 2);
3090 release_region(ashost->card.io_intr, 1);
3091 release_region(ashost->card.io_page, 1);
3092 release_region(ashost->dma.io_port, 256);
3093 release_region(host->io_port, 2048);
3094
3095 msgqueue_free(&ashost->scsi.msgs);
3096 queue_free(&ashost->queues.disconnected);
3097 queue_free(&ashost->queues.issue);
3098 scsi_host_put(host);
3099}
3100
3101static const struct ecard_id acornscsi_cids[] = {
3102 { MANU_ACORN, PROD_ACORN_SCSI },
3103 { 0xffff, 0xffff },
3104};
3105
3106static struct ecard_driver acornscsi_driver = {
3107 .probe = acornscsi_probe,
3108 .remove = __devexit_p(acornscsi_remove),
3109 .id_table = acornscsi_cids,
3110 .drv = {
3111 .name = "acornscsi",
3112 },
3113};
3114
3115static int __init acornscsi_init(void)
3116{
3117 return ecard_register_driver(&acornscsi_driver);
3118}
3119
3120static void __exit acornscsi_exit(void)
3121{
3122 ecard_remove_driver(&acornscsi_driver);
3123}
3124
3125module_init(acornscsi_init);
3126module_exit(acornscsi_exit);
3127
3128MODULE_AUTHOR("Russell King");
3129MODULE_DESCRIPTION("AcornSCSI driver");
3130MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/acornscsi.h b/drivers/scsi/arm/acornscsi.h
new file mode 100644
index 000000000000..03881f091645
--- /dev/null
+++ b/drivers/scsi/arm/acornscsi.h
@@ -0,0 +1,358 @@
1/*
2 * linux/drivers/acorn/scsi/acornscsi.h
3 *
4 * Copyright (C) 1997 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Acorn SCSI driver
11 */
12#ifndef ACORNSCSI_H
13#define ACORNSCSI_H
14
15/* SBIC registers */
16#define SBIC_OWNID 0
17#define OWNID_FS1 (1<<7)
18#define OWNID_FS2 (1<<6)
19#define OWNID_EHP (1<<4)
20#define OWNID_EAF (1<<3)
21
22#define SBIC_CTRL 1
23#define CTRL_DMAMODE (1<<7)
24#define CTRL_DMADBAMODE (1<<6)
25#define CTRL_DMABURST (1<<5)
26#define CTRL_DMAPOLLED 0
27#define CTRL_HHP (1<<4)
28#define CTRL_EDI (1<<3)
29#define CTRL_IDI (1<<2)
30#define CTRL_HA (1<<1)
31#define CTRL_HSP (1<<0)
32
33#define SBIC_TIMEOUT 2
34#define SBIC_TOTSECTS 3
35#define SBIC_TOTHEADS 4
36#define SBIC_TOTCYLH 5
37#define SBIC_TOTCYLL 6
38#define SBIC_LOGADDRH 7
39#define SBIC_LOGADDRM2 8
40#define SBIC_LOGADDRM1 9
41#define SBIC_LOGADDRL 10
42#define SBIC_SECTORNUM 11
43#define SBIC_HEADNUM 12
44#define SBIC_CYLH 13
45#define SBIC_CYLL 14
46#define SBIC_TARGETLUN 15
47#define TARGETLUN_TLV (1<<7)
48#define TARGETLUN_DOK (1<<6)
49
50#define SBIC_CMNDPHASE 16
51#define SBIC_SYNCHTRANSFER 17
52#define SYNCHTRANSFER_OF0 0x00
53#define SYNCHTRANSFER_OF1 0x01
54#define SYNCHTRANSFER_OF2 0x02
55#define SYNCHTRANSFER_OF3 0x03
56#define SYNCHTRANSFER_OF4 0x04
57#define SYNCHTRANSFER_OF5 0x05
58#define SYNCHTRANSFER_OF6 0x06
59#define SYNCHTRANSFER_OF7 0x07
60#define SYNCHTRANSFER_OF8 0x08
61#define SYNCHTRANSFER_OF9 0x09
62#define SYNCHTRANSFER_OF10 0x0A
63#define SYNCHTRANSFER_OF11 0x0B
64#define SYNCHTRANSFER_OF12 0x0C
65#define SYNCHTRANSFER_8DBA 0x00
66#define SYNCHTRANSFER_2DBA 0x20
67#define SYNCHTRANSFER_3DBA 0x30
68#define SYNCHTRANSFER_4DBA 0x40
69#define SYNCHTRANSFER_5DBA 0x50
70#define SYNCHTRANSFER_6DBA 0x60
71#define SYNCHTRANSFER_7DBA 0x70
72
73#define SBIC_TRANSCNTH 18
74#define SBIC_TRANSCNTM 19
75#define SBIC_TRANSCNTL 20
76#define SBIC_DESTID 21
77#define DESTID_SCC (1<<7)
78#define DESTID_DPD (1<<6)
79
80#define SBIC_SOURCEID 22
81#define SOURCEID_ER (1<<7)
82#define SOURCEID_ES (1<<6)
83#define SOURCEID_DSP (1<<5)
84#define SOURCEID_SIV (1<<4)
85
86#define SBIC_SSR 23
87#define SBIC_CMND 24
88#define CMND_RESET 0x00
89#define CMND_ABORT 0x01
90#define CMND_ASSERTATN 0x02
91#define CMND_NEGATEACK 0x03
92#define CMND_DISCONNECT 0x04
93#define CMND_RESELECT 0x05
94#define CMND_SELWITHATN 0x06
95#define CMND_SELECT 0x07
96#define CMND_SELECTATNTRANSFER 0x08
97#define CMND_SELECTTRANSFER 0x09
98#define CMND_RESELECTRXDATA 0x0A
99#define CMND_RESELECTTXDATA 0x0B
100#define CMND_WAITFORSELRECV 0x0C
101#define CMND_SENDSTATCMD 0x0D
102#define CMND_SENDDISCONNECT 0x0E
103#define CMND_SETIDI 0x0F
104#define CMND_RECEIVECMD 0x10
105#define CMND_RECEIVEDTA 0x11
106#define CMND_RECEIVEMSG 0x12
107#define CMND_RECEIVEUSP 0x13
108#define CMND_SENDCMD 0x14
109#define CMND_SENDDATA 0x15
110#define CMND_SENDMSG 0x16
111#define CMND_SENDUSP 0x17
112#define CMND_TRANSLATEADDR 0x18
113#define CMND_XFERINFO 0x20
114#define CMND_SBT (1<<7)
115
116#define SBIC_DATA 25
117#define SBIC_ASR 26
118#define ASR_INT (1<<7)
119#define ASR_LCI (1<<6)
120#define ASR_BSY (1<<5)
121#define ASR_CIP (1<<4)
122#define ASR_PE (1<<1)
123#define ASR_DBR (1<<0)
124
125/* DMAC registers */
126#define DMAC_INIT 0x00
127#define INIT_8BIT (1)
128
129#define DMAC_CHANNEL 0x80
130#define CHANNEL_0 0x00
131#define CHANNEL_1 0x01
132#define CHANNEL_2 0x02
133#define CHANNEL_3 0x03
134
135#define DMAC_TXCNTLO 0x01
136#define DMAC_TXCNTHI 0x81
137#define DMAC_TXADRLO 0x02
138#define DMAC_TXADRMD 0x82
139#define DMAC_TXADRHI 0x03
140
141#define DMAC_DEVCON0 0x04
142#define DEVCON0_AKL (1<<7)
143#define DEVCON0_RQL (1<<6)
144#define DEVCON0_EXW (1<<5)
145#define DEVCON0_ROT (1<<4)
146#define DEVCON0_CMP (1<<3)
147#define DEVCON0_DDMA (1<<2)
148#define DEVCON0_AHLD (1<<1)
149#define DEVCON0_MTM (1<<0)
150
151#define DMAC_DEVCON1 0x84
152#define DEVCON1_WEV (1<<1)
153#define DEVCON1_BHLD (1<<0)
154
155#define DMAC_MODECON 0x05
156#define MODECON_WOED 0x01
157#define MODECON_VERIFY 0x00
158#define MODECON_READ 0x04
159#define MODECON_WRITE 0x08
160#define MODECON_AUTOINIT 0x10
161#define MODECON_ADDRDIR 0x20
162#define MODECON_DEMAND 0x00
163#define MODECON_SINGLE 0x40
164#define MODECON_BLOCK 0x80
165#define MODECON_CASCADE 0xC0
166
167#define DMAC_STATUS 0x85
168#define STATUS_TC0 (1<<0)
169#define STATUS_RQ0 (1<<4)
170
171#define DMAC_TEMPLO 0x06
172#define DMAC_TEMPHI 0x86
173#define DMAC_REQREG 0x07
174#define DMAC_MASKREG 0x87
175#define MASKREG_M0 0x01
176#define MASKREG_M1 0x02
177#define MASKREG_M2 0x04
178#define MASKREG_M3 0x08
179
180/* miscellaneous internal variables */
181
182#define POD_SPACE(x) ((x) + 0xd0000)
183#define MASK_ON (MASKREG_M3|MASKREG_M2|MASKREG_M1|MASKREG_M0)
184#define MASK_OFF (MASKREG_M3|MASKREG_M2|MASKREG_M1)
185
186/*
187 * SCSI driver phases
188 */
189typedef enum {
190 PHASE_IDLE, /* we're not planning on doing anything */
191 PHASE_CONNECTING, /* connecting to a target */
192 PHASE_CONNECTED, /* connected to a target */
193 PHASE_MSGOUT, /* message out to device */
194 PHASE_RECONNECTED, /* reconnected */
195 PHASE_COMMANDPAUSED, /* command partly sent */
196 PHASE_COMMAND, /* command all sent */
197 PHASE_DATAOUT, /* data out to device */
198 PHASE_DATAIN, /* data in from device */
199 PHASE_STATUSIN, /* status in from device */
200 PHASE_MSGIN, /* message in from device */
201 PHASE_DONE, /* finished */
202 PHASE_ABORTED, /* aborted */
203 PHASE_DISCONNECT, /* disconnecting */
204} phase_t;
205
206/*
207 * After interrupt, what to do now
208 */
209typedef enum {
210 INTR_IDLE, /* not expecting another IRQ */
211 INTR_NEXT_COMMAND, /* start next command */
212 INTR_PROCESSING, /* interrupt routine still processing */
213} intr_ret_t;
214
215/*
216 * DMA direction
217 */
218typedef enum {
219 DMA_OUT, /* DMA from memory to chip */
220 DMA_IN /* DMA from chip to memory */
221} dmadir_t;
222
223/*
224 * Synchronous transfer state
225 */
226typedef enum { /* Synchronous transfer state */
227 SYNC_ASYNCHRONOUS, /* don't negociate synchronous transfers*/
228 SYNC_NEGOCIATE, /* start negociation */
229 SYNC_SENT_REQUEST, /* sent SDTR message */
230 SYNC_COMPLETED, /* received SDTR reply */
231} syncxfer_t;
232
233/*
234 * Command type
235 */
236typedef enum { /* command type */
237 CMD_READ, /* READ_6, READ_10, READ_12 */
238 CMD_WRITE, /* WRITE_6, WRITE_10, WRITE_12 */
239 CMD_MISC, /* Others */
240} cmdtype_t;
241
242/*
243 * Data phase direction
244 */
245typedef enum { /* Data direction */
246 DATADIR_IN, /* Data in phase expected */
247 DATADIR_OUT /* Data out phase expected */
248} datadir_t;
249
250#include "queue.h"
251#include "msgqueue.h"
252
253#define STATUS_BUFFER_SIZE 32
254/*
255 * This is used to dump the previous states of the SBIC
256 */
257struct status_entry {
258 unsigned long when;
259 unsigned char ssr;
260 unsigned char ph;
261 unsigned char irq;
262 unsigned char unused;
263};
264
265#define ADD_STATUS(_q,_ssr,_ph,_irq) \
266({ \
267 host->status[(_q)][host->status_ptr[(_q)]].when = jiffies; \
268 host->status[(_q)][host->status_ptr[(_q)]].ssr = (_ssr); \
269 host->status[(_q)][host->status_ptr[(_q)]].ph = (_ph); \
270 host->status[(_q)][host->status_ptr[(_q)]].irq = (_irq); \
271 host->status_ptr[(_q)] = (host->status_ptr[(_q)] + 1) & (STATUS_BUFFER_SIZE - 1); \
272})
273
274/*
275 * AcornSCSI host specific data
276 */
277typedef struct acornscsi_hostdata {
278 /* miscellaneous */
279 struct Scsi_Host *host; /* host */
280 Scsi_Cmnd *SCpnt; /* currently processing command */
281 Scsi_Cmnd *origSCpnt; /* original connecting command */
282
283 /* driver information */
284 struct {
285 unsigned int io_port; /* base address of WD33C93 */
286 unsigned int irq; /* interrupt */
287 phase_t phase; /* current phase */
288
289 struct {
290 unsigned char target; /* reconnected target */
291 unsigned char lun; /* reconnected lun */
292 unsigned char tag; /* reconnected tag */
293 } reconnected;
294
295 Scsi_Pointer SCp; /* current commands data pointer */
296
297 MsgQueue_t msgs;
298
299 unsigned short last_message; /* last message to be sent */
300 unsigned char disconnectable:1; /* this command can be disconnected */
301 } scsi;
302
303 /* statistics information */
304 struct {
305 unsigned int queues;
306 unsigned int removes;
307 unsigned int fins;
308 unsigned int reads;
309 unsigned int writes;
310 unsigned int miscs;
311 unsigned int disconnects;
312 unsigned int aborts;
313 unsigned int resets;
314 } stats;
315
316 /* queue handling */
317 struct {
318 Queue_t issue; /* issue queue */
319 Queue_t disconnected; /* disconnected command queue */
320 } queues;
321
322 /* per-device info */
323 struct {
324 unsigned char sync_xfer; /* synchronous transfer (SBIC value) */
325 syncxfer_t sync_state; /* sync xfer negociation state */
326 unsigned char disconnect_ok:1; /* device can disconnect */
327 } device[8];
328 unsigned long busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy */
329
330 /* DMA info */
331 struct {
332 unsigned int io_port; /* base address of DMA controller */
333 unsigned int io_intr_clear; /* address of DMA interrupt clear */
334 unsigned int free_addr; /* next free address */
335 unsigned int start_addr; /* start address of current transfer */
336 dmadir_t direction; /* dma direction */
337 unsigned int transferred; /* number of bytes transferred */
338 unsigned int xfer_start; /* scheduled DMA transfer start */
339 unsigned int xfer_length; /* scheduled DMA transfer length */
340 char *xfer_ptr; /* pointer to area */
341 unsigned char xfer_required:1; /* set if we need to transfer something */
342 unsigned char xfer_setup:1; /* set if DMA is setup */
343 unsigned char xfer_done:1; /* set if DMA reached end of BH list */
344 } dma;
345
346 /* card info */
347 struct {
348 unsigned int io_intr; /* base address of interrupt id reg */
349 unsigned int io_page; /* base address of page reg */
350 unsigned int io_ram; /* base address of RAM access */
351 unsigned char page_reg; /* current setting of page reg */
352 } card;
353
354 unsigned char status_ptr[9];
355 struct status_entry status[9][STATUS_BUFFER_SIZE];
356} AS_Host;
357
358#endif /* ACORNSCSI_H */
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
new file mode 100644
index 000000000000..29811f5891ee
--- /dev/null
+++ b/drivers/scsi/arm/arxescsi.c
@@ -0,0 +1,395 @@
1/*
2 * linux/arch/arm/drivers/scsi/arxescsi.c
3 *
4 * Copyright (C) 1997-2000 Russell King, Stefan Hanske
5 *
6 * This driver is based on experimentation. Hence, it may have made
7 * assumptions about the particular card that I have available, and
8 * may not be reliable!
9 *
10 * Changelog:
11 * 30-08-1997 RMK 0.0.0 Created, READONLY version as cumana_2.c
12 * 22-01-1998 RMK 0.0.1 Updated to 2.1.80
13 * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it.
14 * 11-06-1998 SH 0.0.2 Changed to support ARXE 16-bit SCSI card
15 * enabled writing
16 * 01-01-2000 SH 0.1.0 Added *real* pseudo dma writing
17 * (arxescsi_pseudo_dma_write)
18 * 02-04-2000 RMK 0.1.1 Updated for new error handling code.
19 * 22-10-2000 SH Updated for new registering scheme.
20 */
21#include <linux/module.h>
22#include <linux/blkdev.h>
23#include <linux/kernel.h>
24#include <linux/string.h>
25#include <linux/ioport.h>
26#include <linux/sched.h>
27#include <linux/proc_fs.h>
28#include <linux/unistd.h>
29#include <linux/stat.h>
30#include <linux/delay.h>
31#include <linux/init.h>
32#include <linux/interrupt.h>
33
34#include <asm/dma.h>
35#include <asm/io.h>
36#include <asm/irq.h>
37#include <asm/ecard.h>
38
39#include "../scsi.h"
40#include <scsi/scsi_host.h>
41#include "fas216.h"
42
43struct arxescsi_info {
44 FAS216_Info info;
45 struct expansion_card *ec;
46 void __iomem *base;
47};
48
49#define DMADATA_OFFSET (0x200)
50
51#define DMASTAT_OFFSET (0x600)
52#define DMASTAT_DRQ (1 << 0)
53
54#define CSTATUS_IRQ (1 << 0)
55
56#define VERSION "1.10 (23/01/2003 2.5.57)"
57
58/*
59 * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type)
60 * Purpose : initialises DMA/PIO
61 * Params : host - host
62 * SCpnt - command
63 * direction - DMA on to/off of card
64 * min_type - minimum DMA support that we must have for this transfer
65 * Returns : 0 if we should not set CMD_WITHDMA for transfer info command
66 */
67static fasdmatype_t
68arxescsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
69 fasdmadir_t direction, fasdmatype_t min_type)
70{
71 /*
72 * We don't do real DMA
73 */
74 return fasdma_pseudo;
75}
76
77static void arxescsi_pseudo_dma_write(unsigned char *addr, void __iomem *base)
78{
79 __asm__ __volatile__(
80 " stmdb sp!, {r0-r12}\n"
81 " mov r3, %0\n"
82 " mov r1, %1\n"
83 " add r2, r1, #512\n"
84 " mov r4, #256\n"
85 ".loop_1: ldmia r3!, {r6, r8, r10, r12}\n"
86 " mov r5, r6, lsl #16\n"
87 " mov r7, r8, lsl #16\n"
88 ".loop_2: ldrb r0, [r1, #1536]\n"
89 " tst r0, #1\n"
90 " beq .loop_2\n"
91 " stmia r2, {r5-r8}\n\t"
92 " mov r9, r10, lsl #16\n"
93 " mov r11, r12, lsl #16\n"
94 ".loop_3: ldrb r0, [r1, #1536]\n"
95 " tst r0, #1\n"
96 " beq .loop_3\n"
97 " stmia r2, {r9-r12}\n"
98 " subs r4, r4, #16\n"
99 " bne .loop_1\n"
100 " ldmia sp!, {r0-r12}\n"
101 :
102 : "r" (addr), "r" (base));
103}
104
105/*
106 * Function: int arxescsi_dma_pseudo(host, SCpnt, direction, transfer)
107 * Purpose : handles pseudo DMA
108 * Params : host - host
109 * SCpnt - command
110 * direction - DMA on to/off of card
111 * transfer - minimum number of bytes we expect to transfer
112 */
113static void
114arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
115 fasdmadir_t direction, int transfer)
116{
117 struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
118 unsigned int length, error = 0;
119 void __iomem *base = info->info.scsi.io_base;
120 unsigned char *addr;
121
122 length = SCp->this_residual;
123 addr = SCp->ptr;
124
125 if (direction == DMA_OUT) {
126 unsigned int word;
127 while (length > 256) {
128 if (readb(base + 0x80) & STAT_INT) {
129 error = 1;
130 break;
131 }
132 arxescsi_pseudo_dma_write(addr, base);
133 addr += 256;
134 length -= 256;
135 }
136
137 if (!error)
138 while (length > 0) {
139 if (readb(base + 0x80) & STAT_INT)
140 break;
141
142 if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ))
143 continue;
144
145 word = *addr | *(addr + 1) << 8;
146
147 writew(word, base + DMADATA_OFFSET);
148 if (length > 1) {
149 addr += 2;
150 length -= 2;
151 } else {
152 addr += 1;
153 length -= 1;
154 }
155 }
156 }
157 else {
158 if (transfer && (transfer & 255)) {
159 while (length >= 256) {
160 if (readb(base + 0x80) & STAT_INT) {
161 error = 1;
162 break;
163 }
164
165 if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ))
166 continue;
167
168 readsw(base + DMADATA_OFFSET, addr, 256 >> 1);
169 addr += 256;
170 length -= 256;
171 }
172 }
173
174 if (!(error))
175 while (length > 0) {
176 unsigned long word;
177
178 if (readb(base + 0x80) & STAT_INT)
179 break;
180
181 if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ))
182 continue;
183
184 word = readw(base + DMADATA_OFFSET);
185 *addr++ = word;
186 if (--length > 0) {
187 *addr++ = word >> 8;
188 length --;
189 }
190 }
191 }
192}
193
194/*
195 * Function: int arxescsi_dma_stop(host, SCpnt)
196 * Purpose : stops DMA/PIO
197 * Params : host - host
198 * SCpnt - command
199 */
200static void arxescsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
201{
202 /*
203 * no DMA to stop
204 */
205}
206
207/*
208 * Function: const char *arxescsi_info(struct Scsi_Host * host)
209 * Purpose : returns a descriptive string about this interface,
210 * Params : host - driver host structure to return info for.
211 * Returns : pointer to a static buffer containing null terminated string.
212 */
213static const char *arxescsi_info(struct Scsi_Host *host)
214{
215 struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
216 static char string[150];
217
218 sprintf(string, "%s (%s) in slot %d v%s",
219 host->hostt->name, info->info.scsi.type, info->ec->slot_no,
220 VERSION);
221
222 return string;
223}
224
225/*
226 * Function: int arxescsi_proc_info(char *buffer, char **start, off_t offset,
227 * int length, int host_no, int inout)
228 * Purpose : Return information about the driver to a user process accessing
229 * the /proc filesystem.
230 * Params : buffer - a buffer to write information to
231 * start - a pointer into this buffer set by this routine to the start
232 * of the required information.
233 * offset - offset into information that we have read upto.
234 * length - length of buffer
235 * host_no - host number to return information for
236 * inout - 0 for reading, 1 for writing.
237 * Returns : length of data written to buffer.
238 */
239static int
240arxescsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length,
241 int inout)
242{
243 struct arxescsi_info *info;
244 char *p = buffer;
245 int pos;
246
247 info = (struct arxescsi_info *)host->hostdata;
248 if (inout == 1)
249 return -EINVAL;
250
251 p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION);
252 p += fas216_print_host(&info->info, p);
253 p += fas216_print_stats(&info->info, p);
254 p += fas216_print_devices(&info->info, p);
255
256 *start = buffer + offset;
257 pos = p - buffer - offset;
258 if (pos > length)
259 pos = length;
260
261 return pos;
262}
263
264static Scsi_Host_Template arxescsi_template = {
265 .proc_info = arxescsi_proc_info,
266 .name = "ARXE SCSI card",
267 .info = arxescsi_info,
268 .queuecommand = fas216_noqueue_command,
269 .eh_host_reset_handler = fas216_eh_host_reset,
270 .eh_bus_reset_handler = fas216_eh_bus_reset,
271 .eh_device_reset_handler = fas216_eh_device_reset,
272 .eh_abort_handler = fas216_eh_abort,
273 .can_queue = 0,
274 .this_id = 7,
275 .sg_tablesize = SG_ALL,
276 .cmd_per_lun = 1,
277 .use_clustering = DISABLE_CLUSTERING,
278 .proc_name = "arxescsi",
279};
280
281static int __devinit
282arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
283{
284 struct Scsi_Host *host;
285 struct arxescsi_info *info;
286 unsigned long resbase, reslen;
287 void __iomem *base;
288 int ret;
289
290 ret = ecard_request_resources(ec);
291 if (ret)
292 goto out;
293
294 resbase = ecard_resource_start(ec, ECARD_RES_MEMC);
295 reslen = ecard_resource_len(ec, ECARD_RES_MEMC);
296 base = ioremap(resbase, reslen);
297 if (!base) {
298 ret = -ENOMEM;
299 goto out_region;
300 }
301
302 host = scsi_host_alloc(&arxescsi_template, sizeof(struct arxescsi_info));
303 if (!host) {
304 ret = -ENOMEM;
305 goto out_unmap;
306 }
307
308 info = (struct arxescsi_info *)host->hostdata;
309 info->ec = ec;
310 info->base = base;
311
312 info->info.scsi.io_base = base + 0x2000;
313 info->info.scsi.irq = NO_IRQ;
314 info->info.scsi.dma = NO_DMA;
315 info->info.scsi.io_shift = 5;
316 info->info.ifcfg.clockrate = 24; /* MHz */
317 info->info.ifcfg.select_timeout = 255;
318 info->info.ifcfg.asyncperiod = 200; /* ns */
319 info->info.ifcfg.sync_max_depth = 0;
320 info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK;
321 info->info.ifcfg.disconnect_ok = 0;
322 info->info.ifcfg.wide_max_size = 0;
323 info->info.ifcfg.capabilities = FASCAP_PSEUDODMA;
324 info->info.dma.setup = arxescsi_dma_setup;
325 info->info.dma.pseudo = arxescsi_dma_pseudo;
326 info->info.dma.stop = arxescsi_dma_stop;
327
328 ec->irqaddr = base;
329 ec->irqmask = CSTATUS_IRQ;
330
331 ret = fas216_init(host);
332 if (ret)
333 goto out_unregister;
334
335 ret = fas216_add(host, &ec->dev);
336 if (ret == 0)
337 goto out;
338
339 fas216_release(host);
340 out_unregister:
341 scsi_host_put(host);
342 out_unmap:
343 iounmap(base);
344 out_region:
345 ecard_release_resources(ec);
346 out:
347 return ret;
348}
349
350static void __devexit arxescsi_remove(struct expansion_card *ec)
351{
352 struct Scsi_Host *host = ecard_get_drvdata(ec);
353 struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
354
355 ecard_set_drvdata(ec, NULL);
356 fas216_remove(host);
357
358 iounmap(info->base);
359
360 fas216_release(host);
361 scsi_host_put(host);
362 ecard_release_resources(ec);
363}
364
365static const struct ecard_id arxescsi_cids[] = {
366 { MANU_ARXE, PROD_ARXE_SCSI },
367 { 0xffff, 0xffff },
368};
369
370static struct ecard_driver arxescsi_driver = {
371 .probe = arxescsi_probe,
372 .remove = __devexit_p(arxescsi_remove),
373 .id_table = arxescsi_cids,
374 .drv = {
375 .name = "arxescsi",
376 },
377};
378
379static int __init init_arxe_scsi_driver(void)
380{
381 return ecard_register_driver(&arxescsi_driver);
382}
383
384static void __exit exit_arxe_scsi_driver(void)
385{
386 ecard_remove_driver(&arxescsi_driver);
387}
388
389module_init(init_arxe_scsi_driver);
390module_exit(exit_arxe_scsi_driver);
391
392MODULE_AUTHOR("Stefan Hanske");
393MODULE_DESCRIPTION("ARXESCSI driver for Acorn machines");
394MODULE_LICENSE("GPL");
395
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
new file mode 100644
index 000000000000..27271bfc01d7
--- /dev/null
+++ b/drivers/scsi/arm/cumana_1.c
@@ -0,0 +1,357 @@
1/*
2 * Generic Generic NCR5380 driver
3 *
4 * Copyright 1995-2002, Russell King
5 */
6#include <linux/module.h>
7#include <linux/signal.h>
8#include <linux/sched.h>
9#include <linux/ioport.h>
10#include <linux/delay.h>
11#include <linux/blkdev.h>
12#include <linux/init.h>
13
14#include <asm/ecard.h>
15#include <asm/io.h>
16#include <asm/irq.h>
17#include <asm/system.h>
18
19#include "../scsi.h"
20#include <scsi/scsi_host.h>
21
22#include <scsi/scsicam.h>
23
24#define AUTOSENSE
25#define PSEUDO_DMA
26
27#define CUMANASCSI_PUBLIC_RELEASE 1
28
29#define NCR5380_implementation_fields int port, ctrl
30#define NCR5380_local_declare() struct Scsi_Host *_instance
31#define NCR5380_setup(instance) _instance = instance
32#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
33#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
34#define NCR5380_intr cumanascsi_intr
35#define NCR5380_queue_command cumanascsi_queue_command
36#define NCR5380_proc_info cumanascsi_proc_info
37
38#define BOARD_NORMAL 0
39#define BOARD_NCR53C400 1
40
41#include "../NCR5380.h"
42
43void cumanascsi_setup(char *str, int *ints)
44{
45}
46
47const char *cumanascsi_info(struct Scsi_Host *spnt)
48{
49 return "";
50}
51
52#ifdef NOT_EFFICIENT
53#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
54#define STAT(p) inb((p)+1)
55#define IN(p) inb((p))
56#define OUT(v,p) outb((v), (p))
57#else
58#define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
59#define STAT(p) (p[4])
60#define IN(p) (*(p))
61#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
62#define OUT(v,p) (*(p) = (v))
63#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
64#endif
65#define L(v) (((v)<<16)|((v) & 0x0000ffff))
66#define H(v) (((v)>>16)|((v) & 0xffff0000))
67
68static inline int
69NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len)
70{
71 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
72 int oldctrl = *ctrl;
73 unsigned long *laddr;
74#ifdef NOT_EFFICIENT
75 int iobase = instance->io_port;
76 int dma_io = iobase & ~(0x3C0000>>2);
77#else
78 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
79 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
80#endif
81
82 if(!len) return 0;
83
84 CTRL(iobase, 0x02);
85 laddr = (unsigned long *)addr;
86 while(len >= 32)
87 {
88 int status;
89 unsigned long v;
90 status = STAT(iobase);
91 if(status & 0x80)
92 goto end;
93 if(!(status & 0x40))
94 continue;
95 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
96 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
97 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
98 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
99 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
100 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
101 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
102 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
103 len -= 32;
104 if(len == 0)
105 break;
106 }
107
108 addr = (unsigned char *)laddr;
109 CTRL(iobase, 0x12);
110 while(len > 0)
111 {
112 int status;
113 status = STAT(iobase);
114 if(status & 0x80)
115 goto end;
116 if(status & 0x40)
117 {
118 OUT(*addr++, dma_io);
119 if(--len == 0)
120 break;
121 }
122
123 status = STAT(iobase);
124 if(status & 0x80)
125 goto end;
126 if(status & 0x40)
127 {
128 OUT(*addr++, dma_io);
129 if(--len == 0)
130 break;
131 }
132 }
133end:
134 CTRL(iobase, oldctrl|0x40);
135 return len;
136}
137
138static inline int
139NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len)
140{
141 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
142 int oldctrl = *ctrl;
143 unsigned long *laddr;
144#ifdef NOT_EFFICIENT
145 int iobase = instance->io_port;
146 int dma_io = iobase & ~(0x3C0000>>2);
147#else
148 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
149 volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
150#endif
151
152 if(!len) return 0;
153
154 CTRL(iobase, 0x00);
155 laddr = (unsigned long *)addr;
156 while(len >= 32)
157 {
158 int status;
159 status = STAT(iobase);
160 if(status & 0x80)
161 goto end;
162 if(!(status & 0x40))
163 continue;
164 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
165 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
166 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
167 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
168 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
169 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
170 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
171 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
172 len -= 32;
173 if(len == 0)
174 break;
175 }
176
177 addr = (unsigned char *)laddr;
178 CTRL(iobase, 0x10);
179 while(len > 0)
180 {
181 int status;
182 status = STAT(iobase);
183 if(status & 0x80)
184 goto end;
185 if(status & 0x40)
186 {
187 *addr++ = IN(dma_io);
188 if(--len == 0)
189 break;
190 }
191
192 status = STAT(iobase);
193 if(status & 0x80)
194 goto end;
195 if(status & 0x40)
196 {
197 *addr++ = IN(dma_io);
198 if(--len == 0)
199 break;
200 }
201 }
202end:
203 CTRL(iobase, oldctrl|0x40);
204 return len;
205}
206
207#undef STAT
208#undef CTRL
209#undef IN
210#undef OUT
211
212#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
213
214static char cumanascsi_read(struct Scsi_Host *instance, int reg)
215{
216 unsigned int iobase = instance->io_port;
217 int i;
218 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
219
220 CTRL(iobase, 0);
221 i = inb(iobase + 64 + reg);
222 CTRL(iobase, 0x40);
223
224 return i;
225}
226
227static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
228{
229 int iobase = instance->io_port;
230 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
231
232 CTRL(iobase, 0);
233 outb(value, iobase + 64 + reg);
234 CTRL(iobase, 0x40);
235}
236
237#undef CTRL
238
239#include "../NCR5380.c"
240
241static Scsi_Host_Template cumanascsi_template = {
242 .module = THIS_MODULE,
243 .name = "Cumana 16-bit SCSI",
244 .info = cumanascsi_info,
245 .queuecommand = cumanascsi_queue_command,
246 .eh_abort_handler = NCR5380_abort,
247 .eh_device_reset_handler= NCR5380_device_reset,
248 .eh_bus_reset_handler = NCR5380_bus_reset,
249 .eh_host_reset_handler = NCR5380_host_reset,
250 .can_queue = 16,
251 .this_id = 7,
252 .sg_tablesize = SG_ALL,
253 .cmd_per_lun = 2,
254 .unchecked_isa_dma = 0,
255 .use_clustering = DISABLE_CLUSTERING,
256 .proc_name = "CumanaSCSI-1",
257};
258
259static int __devinit
260cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
261{
262 struct Scsi_Host *host;
263 int ret = -ENOMEM;
264
265 host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata));
266 if (!host)
267 goto out;
268
269 host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800;
270 host->irq = ec->irq;
271
272 NCR5380_init(host, 0);
273
274 host->n_io_port = 255;
275 if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) {
276 ret = -EBUSY;
277 goto out_free;
278 }
279
280 ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0;
281 outb(0x00, host->io_port - 577);
282
283 ret = request_irq(host->irq, cumanascsi_intr, SA_INTERRUPT,
284 "CumanaSCSI-1", host);
285 if (ret) {
286 printk("scsi%d: IRQ%d not free: %d\n",
287 host->host_no, host->irq, ret);
288 goto out_release;
289 }
290
291 printk("scsi%d: at port 0x%08lx irq %d",
292 host->host_no, host->io_port, host->irq);
293 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
294 host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
295 printk("\nscsi%d:", host->host_no);
296 NCR5380_print_options(host);
297 printk("\n");
298
299 ret = scsi_add_host(host, &ec->dev);
300 if (ret)
301 goto out_free_irq;
302
303 scsi_scan_host(host);
304 goto out;
305
306 out_free_irq:
307 free_irq(host->irq, host);
308 out_release:
309 release_region(host->io_port, host->n_io_port);
310 out_free:
311 scsi_host_put(host);
312 out:
313 return ret;
314}
315
316static void __devexit cumanascsi1_remove(struct expansion_card *ec)
317{
318 struct Scsi_Host *host = ecard_get_drvdata(ec);
319
320 ecard_set_drvdata(ec, NULL);
321
322 scsi_remove_host(host);
323 free_irq(host->irq, host);
324 NCR5380_exit(host);
325 release_region(host->io_port, host->n_io_port);
326 scsi_host_put(host);
327}
328
329static const struct ecard_id cumanascsi1_cids[] = {
330 { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
331 { 0xffff, 0xffff }
332};
333
334static struct ecard_driver cumanascsi1_driver = {
335 .probe = cumanascsi1_probe,
336 .remove = __devexit_p(cumanascsi1_remove),
337 .id_table = cumanascsi1_cids,
338 .drv = {
339 .name = "cumanascsi1",
340 },
341};
342
343static int __init cumanascsi_init(void)
344{
345 return ecard_register_driver(&cumanascsi1_driver);
346}
347
348static void __exit cumanascsi_exit(void)
349{
350 ecard_remove_driver(&cumanascsi1_driver);
351}
352
353module_init(cumanascsi_init);
354module_exit(cumanascsi_exit);
355
356MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines");
357MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
new file mode 100644
index 000000000000..0ef0644eeb29
--- /dev/null
+++ b/drivers/scsi/arm/cumana_2.c
@@ -0,0 +1,556 @@
1/*
2 * linux/drivers/acorn/scsi/cumana_2.c
3 *
4 * Copyright (C) 1997-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Changelog:
11 * 30-08-1997 RMK 0.0.0 Created, READONLY version.
12 * 22-01-1998 RMK 0.0.1 Updated to 2.1.80.
13 * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it.
14 * 02-05-1998 RMK 0.0.2 Updated & added DMA support.
15 * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
16 * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth.
17 * 02-04-2000 RMK 0.0.4 Updated for new error handling code.
18 */
19#include <linux/module.h>
20#include <linux/blkdev.h>
21#include <linux/kernel.h>
22#include <linux/string.h>
23#include <linux/ioport.h>
24#include <linux/sched.h>
25#include <linux/proc_fs.h>
26#include <linux/delay.h>
27#include <linux/interrupt.h>
28#include <linux/init.h>
29#include <linux/dma-mapping.h>
30
31#include <asm/dma.h>
32#include <asm/ecard.h>
33#include <asm/io.h>
34#include <asm/irq.h>
35#include <asm/pgtable.h>
36
37#include "../scsi.h"
38#include <scsi/scsi_host.h>
39#include "fas216.h"
40#include "scsi.h"
41
42#include <scsi/scsicam.h>
43
44#define CUMANASCSI2_STATUS (0x0000)
45#define STATUS_INT (1 << 0)
46#define STATUS_DRQ (1 << 1)
47#define STATUS_LATCHED (1 << 3)
48
49#define CUMANASCSI2_ALATCH (0x0014)
50#define ALATCH_ENA_INT (3)
51#define ALATCH_DIS_INT (2)
52#define ALATCH_ENA_TERM (5)
53#define ALATCH_DIS_TERM (4)
54#define ALATCH_ENA_BIT32 (11)
55#define ALATCH_DIS_BIT32 (10)
56#define ALATCH_ENA_DMA (13)
57#define ALATCH_DIS_DMA (12)
58#define ALATCH_DMA_OUT (15)
59#define ALATCH_DMA_IN (14)
60
61#define CUMANASCSI2_PSEUDODMA (0x0200)
62
63#define CUMANASCSI2_FAS216_OFFSET (0x0300)
64#define CUMANASCSI2_FAS216_SHIFT 2
65
66/*
67 * Version
68 */
69#define VERSION "1.00 (13/11/2002 2.5.47)"
70
71/*
72 * Use term=0,1,0,0,0 to turn terminators on/off
73 */
74static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
75
76#define NR_SG 256
77
78struct cumanascsi2_info {
79 FAS216_Info info;
80 struct expansion_card *ec;
81 void __iomem *base;
82 unsigned int terms; /* Terminator state */
83 struct scatterlist sg[NR_SG]; /* Scatter DMA list */
84};
85
86#define CSTATUS_IRQ (1 << 0)
87#define CSTATUS_DRQ (1 << 1)
88
89/* Prototype: void cumanascsi_2_irqenable(ec, irqnr)
90 * Purpose : Enable interrupts on Cumana SCSI 2 card
91 * Params : ec - expansion card structure
92 * : irqnr - interrupt number
93 */
94static void
95cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
96{
97 struct cumanascsi2_info *info = ec->irq_data;
98 writeb(ALATCH_ENA_INT, info->base + CUMANASCSI2_ALATCH);
99}
100
101/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr)
102 * Purpose : Disable interrupts on Cumana SCSI 2 card
103 * Params : ec - expansion card structure
104 * : irqnr - interrupt number
105 */
106static void
107cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr)
108{
109 struct cumanascsi2_info *info = ec->irq_data;
110 writeb(ALATCH_DIS_INT, info->base + CUMANASCSI2_ALATCH);
111}
112
113static const expansioncard_ops_t cumanascsi_2_ops = {
114 .irqenable = cumanascsi_2_irqenable,
115 .irqdisable = cumanascsi_2_irqdisable,
116};
117
118/* Prototype: void cumanascsi_2_terminator_ctl(host, on_off)
119 * Purpose : Turn the Cumana SCSI 2 terminators on or off
120 * Params : host - card to turn on/off
121 * : on_off - !0 to turn on, 0 to turn off
122 */
123static void
124cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off)
125{
126 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
127
128 if (on_off) {
129 info->terms = 1;
130 writeb(ALATCH_ENA_TERM, info->base + CUMANASCSI2_ALATCH);
131 } else {
132 info->terms = 0;
133 writeb(ALATCH_DIS_TERM, info->base + CUMANASCSI2_ALATCH);
134 }
135}
136
137/* Prototype: void cumanascsi_2_intr(irq, *dev_id, *regs)
138 * Purpose : handle interrupts from Cumana SCSI 2 card
139 * Params : irq - interrupt number
140 * dev_id - user-defined (Scsi_Host structure)
141 * regs - processor registers at interrupt
142 */
143static irqreturn_t
144cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
145{
146 struct cumanascsi2_info *info = dev_id;
147
148 return fas216_intr(&info->info);
149}
150
151/* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type)
152 * Purpose : initialises DMA/PIO
153 * Params : host - host
154 * SCpnt - command
155 * direction - DMA on to/off of card
156 * min_type - minimum DMA support that we must have for this transfer
157 * Returns : type of transfer to be performed
158 */
159static fasdmatype_t
160cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
161 fasdmadir_t direction, fasdmatype_t min_type)
162{
163 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
164 struct device *dev = scsi_get_device(host);
165 int dmach = info->info.scsi.dma;
166
167 writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
168
169 if (dmach != NO_DMA &&
170 (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
171 int bufs, map_dir, dma_dir, alatch_dir;
172
173 bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
174
175 if (direction == DMA_OUT)
176 map_dir = DMA_TO_DEVICE,
177 dma_dir = DMA_MODE_WRITE,
178 alatch_dir = ALATCH_DMA_OUT;
179 else
180 map_dir = DMA_FROM_DEVICE,
181 dma_dir = DMA_MODE_READ,
182 alatch_dir = ALATCH_DMA_IN;
183
184 dma_map_sg(dev, info->sg, bufs + 1, map_dir);
185
186 disable_dma(dmach);
187 set_dma_sg(dmach, info->sg, bufs + 1);
188 writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH);
189 set_dma_mode(dmach, dma_dir);
190 enable_dma(dmach);
191 writeb(ALATCH_ENA_DMA, info->base + CUMANASCSI2_ALATCH);
192 writeb(ALATCH_DIS_BIT32, info->base + CUMANASCSI2_ALATCH);
193 return fasdma_real_all;
194 }
195
196 /*
197 * If we're not doing DMA,
198 * we'll do pseudo DMA
199 */
200 return fasdma_pio;
201}
202
203/*
204 * Prototype: void cumanascsi_2_dma_pseudo(host, SCpnt, direction, transfer)
205 * Purpose : handles pseudo DMA
206 * Params : host - host
207 * SCpnt - command
208 * direction - DMA on to/off of card
209 * transfer - minimum number of bytes we expect to transfer
210 */
211static void
212cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
213 fasdmadir_t direction, int transfer)
214{
215 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
216 unsigned int length;
217 unsigned char *addr;
218
219 length = SCp->this_residual;
220 addr = SCp->ptr;
221
222 if (direction == DMA_OUT)
223#if 0
224 while (length > 1) {
225 unsigned long word;
226 unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
227
228 if (status & STATUS_INT)
229 goto end;
230
231 if (!(status & STATUS_DRQ))
232 continue;
233
234 word = *addr | *(addr + 1) << 8;
235 writew(word, info->base + CUMANASCSI2_PSEUDODMA);
236 addr += 2;
237 length -= 2;
238 }
239#else
240 printk ("PSEUDO_OUT???\n");
241#endif
242 else {
243 if (transfer && (transfer & 255)) {
244 while (length >= 256) {
245 unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
246
247 if (status & STATUS_INT)
248 return;
249
250 if (!(status & STATUS_DRQ))
251 continue;
252
253 readsw(info->base + CUMANASCSI2_PSEUDODMA,
254 addr, 256 >> 1);
255 addr += 256;
256 length -= 256;
257 }
258 }
259
260 while (length > 0) {
261 unsigned long word;
262 unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
263
264 if (status & STATUS_INT)
265 return;
266
267 if (!(status & STATUS_DRQ))
268 continue;
269
270 word = readw(info->base + CUMANASCSI2_PSEUDODMA);
271 *addr++ = word;
272 if (--length > 0) {
273 *addr++ = word >> 8;
274 length --;
275 }
276 }
277 }
278}
279
280/* Prototype: int cumanascsi_2_dma_stop(host, SCpnt)
281 * Purpose : stops DMA/PIO
282 * Params : host - host
283 * SCpnt - command
284 */
285static void
286cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
287{
288 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
289 if (info->info.scsi.dma != NO_DMA) {
290 writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
291 disable_dma(info->info.scsi.dma);
292 }
293}
294
295/* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host)
296 * Purpose : returns a descriptive string about this interface,
297 * Params : host - driver host structure to return info for.
298 * Returns : pointer to a static buffer containing null terminated string.
299 */
300const char *cumanascsi_2_info(struct Scsi_Host *host)
301{
302 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
303 static char string[150];
304
305 sprintf(string, "%s (%s) in slot %d v%s terminators o%s",
306 host->hostt->name, info->info.scsi.type, info->ec->slot_no,
307 VERSION, info->terms ? "n" : "ff");
308
309 return string;
310}
311
312/* Prototype: int cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
313 * Purpose : Set a driver specific function
314 * Params : host - host to setup
315 * : buffer - buffer containing string describing operation
316 * : length - length of string
317 * Returns : -EINVAL, or 0
318 */
319static int
320cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
321{
322 int ret = length;
323
324 if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) {
325 buffer += 11;
326 length -= 11;
327
328 if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
329 if (buffer[5] == '1')
330 cumanascsi_2_terminator_ctl(host, 1);
331 else if (buffer[5] == '0')
332 cumanascsi_2_terminator_ctl(host, 0);
333 else
334 ret = -EINVAL;
335 } else
336 ret = -EINVAL;
337 } else
338 ret = -EINVAL;
339
340 return ret;
341}
342
343/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset,
344 * int length, int host_no, int inout)
345 * Purpose : Return information about the driver to a user process accessing
346 * the /proc filesystem.
347 * Params : buffer - a buffer to write information to
348 * start - a pointer into this buffer set by this routine to the start
349 * of the required information.
350 * offset - offset into information that we have read upto.
351 * length - length of buffer
352 * host_no - host number to return information for
353 * inout - 0 for reading, 1 for writing.
354 * Returns : length of data written to buffer.
355 */
356int cumanascsi_2_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset,
357 int length, int inout)
358{
359 struct cumanascsi2_info *info;
360 char *p = buffer;
361 int pos;
362
363 if (inout == 1)
364 return cumanascsi_2_set_proc_info(host, buffer, length);
365
366 info = (struct cumanascsi2_info *)host->hostdata;
367
368 p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION);
369 p += fas216_print_host(&info->info, p);
370 p += sprintf(p, "Term : o%s\n",
371 info->terms ? "n" : "ff");
372
373 p += fas216_print_stats(&info->info, p);
374 p += fas216_print_devices(&info->info, p);
375
376 *start = buffer + offset;
377 pos = p - buffer - offset;
378 if (pos > length)
379 pos = length;
380
381 return pos;
382}
383
384static Scsi_Host_Template cumanascsi2_template = {
385 .module = THIS_MODULE,
386 .proc_info = cumanascsi_2_proc_info,
387 .name = "Cumana SCSI II",
388 .info = cumanascsi_2_info,
389 .queuecommand = fas216_queue_command,
390 .eh_host_reset_handler = fas216_eh_host_reset,
391 .eh_bus_reset_handler = fas216_eh_bus_reset,
392 .eh_device_reset_handler = fas216_eh_device_reset,
393 .eh_abort_handler = fas216_eh_abort,
394 .can_queue = 1,
395 .this_id = 7,
396 .sg_tablesize = SG_ALL,
397 .cmd_per_lun = 1,
398 .use_clustering = DISABLE_CLUSTERING,
399 .proc_name = "cumanascsi2",
400};
401
402static int __devinit
403cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
404{
405 struct Scsi_Host *host;
406 struct cumanascsi2_info *info;
407 unsigned long resbase, reslen;
408 void __iomem *base;
409 int ret;
410
411 ret = ecard_request_resources(ec);
412 if (ret)
413 goto out;
414
415 resbase = ecard_resource_start(ec, ECARD_RES_MEMC);
416 reslen = ecard_resource_len(ec, ECARD_RES_MEMC);
417 base = ioremap(resbase, reslen);
418 if (!base) {
419 ret = -ENOMEM;
420 goto out_region;
421 }
422
423 host = scsi_host_alloc(&cumanascsi2_template,
424 sizeof(struct cumanascsi2_info));
425 if (!host) {
426 ret = -ENOMEM;
427 goto out_unmap;
428 }
429
430 ecard_set_drvdata(ec, host);
431
432 info = (struct cumanascsi2_info *)host->hostdata;
433 info->ec = ec;
434 info->base = base;
435
436 cumanascsi_2_terminator_ctl(host, term[ec->slot_no]);
437
438 info->info.scsi.io_base = base + CUMANASCSI2_FAS216_OFFSET;
439 info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT;
440 info->info.scsi.irq = ec->irq;
441 info->info.scsi.dma = ec->dma;
442 info->info.ifcfg.clockrate = 40; /* MHz */
443 info->info.ifcfg.select_timeout = 255;
444 info->info.ifcfg.asyncperiod = 200; /* ns */
445 info->info.ifcfg.sync_max_depth = 7;
446 info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
447 info->info.ifcfg.disconnect_ok = 1;
448 info->info.ifcfg.wide_max_size = 0;
449 info->info.ifcfg.capabilities = FASCAP_PSEUDODMA;
450 info->info.dma.setup = cumanascsi_2_dma_setup;
451 info->info.dma.pseudo = cumanascsi_2_dma_pseudo;
452 info->info.dma.stop = cumanascsi_2_dma_stop;
453
454 ec->irqaddr = info->base + CUMANASCSI2_STATUS;
455 ec->irqmask = STATUS_INT;
456 ec->irq_data = info;
457 ec->ops = &cumanascsi_2_ops;
458
459 ret = fas216_init(host);
460 if (ret)
461 goto out_free;
462
463 ret = request_irq(ec->irq, cumanascsi_2_intr,
464 SA_INTERRUPT, "cumanascsi2", info);
465 if (ret) {
466 printk("scsi%d: IRQ%d not free: %d\n",
467 host->host_no, ec->irq, ret);
468 goto out_release;
469 }
470
471 if (info->info.scsi.dma != NO_DMA) {
472 if (request_dma(info->info.scsi.dma, "cumanascsi2")) {
473 printk("scsi%d: DMA%d not free, using PIO\n",
474 host->host_no, info->info.scsi.dma);
475 info->info.scsi.dma = NO_DMA;
476 } else {
477 set_dma_speed(info->info.scsi.dma, 180);
478 info->info.ifcfg.capabilities |= FASCAP_DMA;
479 }
480 }
481
482 ret = fas216_add(host, &ec->dev);
483 if (ret == 0)
484 goto out;
485
486 if (info->info.scsi.dma != NO_DMA)
487 free_dma(info->info.scsi.dma);
488 free_irq(ec->irq, host);
489
490 out_release:
491 fas216_release(host);
492
493 out_free:
494 scsi_host_put(host);
495
496 out_unmap:
497 iounmap(base);
498
499 out_region:
500 ecard_release_resources(ec);
501
502 out:
503 return ret;
504}
505
506static void __devexit cumanascsi2_remove(struct expansion_card *ec)
507{
508 struct Scsi_Host *host = ecard_get_drvdata(ec);
509 struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
510
511 ecard_set_drvdata(ec, NULL);
512 fas216_remove(host);
513
514 if (info->info.scsi.dma != NO_DMA)
515 free_dma(info->info.scsi.dma);
516 free_irq(ec->irq, info);
517
518 iounmap(info->base);
519
520 fas216_release(host);
521 scsi_host_put(host);
522 ecard_release_resources(ec);
523}
524
525static const struct ecard_id cumanascsi2_cids[] = {
526 { MANU_CUMANA, PROD_CUMANA_SCSI_2 },
527 { 0xffff, 0xffff },
528};
529
530static struct ecard_driver cumanascsi2_driver = {
531 .probe = cumanascsi2_probe,
532 .remove = __devexit_p(cumanascsi2_remove),
533 .id_table = cumanascsi2_cids,
534 .drv = {
535 .name = "cumanascsi2",
536 },
537};
538
539static int __init cumanascsi2_init(void)
540{
541 return ecard_register_driver(&cumanascsi2_driver);
542}
543
544static void __exit cumanascsi2_exit(void)
545{
546 ecard_remove_driver(&cumanascsi2_driver);
547}
548
549module_init(cumanascsi2_init);
550module_exit(cumanascsi2_exit);
551
552MODULE_AUTHOR("Russell King");
553MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines");
554MODULE_PARM(term, "1-8i");
555MODULE_PARM_DESC(term, "SCSI bus termination");
556MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
new file mode 100644
index 000000000000..303648a84709
--- /dev/null
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -0,0 +1,239 @@
1#define AUTOSENSE
2/* #define PSEUDO_DMA */
3
4/*
5 * EcoSCSI Generic NCR5380 driver
6 *
7 * Copyright 1995, Russell King
8 *
9 * ALPHA RELEASE 1.
10 *
11 * For more information, please consult
12 *
13 * NCR 5380 Family
14 * SCSI Protocol Controller
15 * Databook
16 *
17 * NCR Microelectronics
18 * 1635 Aeroplaza Drive
19 * Colorado Springs, CO 80916
20 * 1+ (719) 578-3400
21 * 1+ (800) 334-5454
22 */
23
24#include <linux/module.h>
25#include <linux/signal.h>
26#include <linux/sched.h>
27#include <linux/ioport.h>
28#include <linux/delay.h>
29#include <linux/init.h>
30#include <linux/blkdev.h>
31
32#include <asm/io.h>
33#include <asm/system.h>
34
35#include "../scsi.h"
36#include <scsi/scsi_host.h>
37
38#define NCR5380_implementation_fields int port, ctrl
39#define NCR5380_local_declare() struct Scsi_Host *_instance
40#define NCR5380_setup(instance) _instance = instance
41
42#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
43#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
44
45#define NCR5380_intr ecoscsi_intr
46#define NCR5380_queue_command ecoscsi_queue_command
47#define NCR5380_proc_info ecoscsi_proc_info
48
49#include "../NCR5380.h"
50
51#define ECOSCSI_PUBLIC_RELEASE 1
52
53static char ecoscsi_read(struct Scsi_Host *instance, int reg)
54{
55 int iobase = instance->io_port;
56 outb(reg | 8, iobase);
57 return inb(iobase + 1);
58}
59
60static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value)
61{
62 int iobase = instance->io_port;
63 outb(reg | 8, iobase);
64 outb(value, iobase + 1);
65}
66
67/*
68 * Function : ecoscsi_setup(char *str, int *ints)
69 *
70 * Purpose : LILO command line initialization of the overrides array,
71 *
72 * Inputs : str - unused, ints - array of integer parameters with ints[0]
73 * equal to the number of ints.
74 *
75 */
76
77void ecoscsi_setup(char *str, int *ints)
78{
79}
80
81const char * ecoscsi_info (struct Scsi_Host *spnt)
82{
83 return "";
84}
85
86#if 0
87#define STAT(p) inw(p + 144)
88
89static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr,
90 int len)
91{
92 int iobase = host->io_port;
93printk("writing %p len %d\n",addr, len);
94 if(!len) return -1;
95
96 while(1)
97 {
98 int status;
99 while(((status = STAT(iobase)) & 0x100)==0);
100 }
101}
102
103static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr,
104 int len)
105{
106 int iobase = host->io_port;
107 int iobase2= host->io_port + 0x100;
108 unsigned char *start = addr;
109 int s;
110printk("reading %p len %d\n",addr, len);
111 outb(inb(iobase + 128), iobase + 135);
112 while(len > 0)
113 {
114 int status,b,i, timeout;
115 timeout = 0x07FFFFFF;
116 while(((status = STAT(iobase)) & 0x100)==0)
117 {
118 timeout--;
119 if(status & 0x200 || !timeout)
120 {
121 printk("status = %p\n",status);
122 outb(0, iobase + 135);
123 return 1;
124 }
125 }
126 if(len >= 128)
127 {
128 for(i=0; i<64; i++)
129 {
130 b = inw(iobase + 136);
131 *addr++ = b;
132 *addr++ = b>>8;
133 }
134 len -= 128;
135 }
136 else
137 {
138 b = inw(iobase + 136);
139 *addr ++ = b;
140 len -= 1;
141 if(len)
142 *addr ++ = b>>8;
143 len -= 1;
144 }
145 }
146 outb(0, iobase + 135);
147 printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]);
148 return 1;
149}
150#endif
151#undef STAT
152
153#define BOARD_NORMAL 0
154#define BOARD_NCR53C400 1
155
156#include "../NCR5380.c"
157
158static Scsi_Host_Template ecoscsi_template = {
159 .module = THIS_MODULE,
160 .name = "Serial Port EcoSCSI NCR5380",
161 .proc_name = "ecoscsi",
162 .info = ecoscsi_info,
163 .queuecommand = ecoscsi_queue_command,
164 .eh_abort_handler = NCR5380_abort,
165 .eh_device_reset_handler= NCR5380_device_reset,
166 .eh_bus_reset_handler = NCR5380_bus_reset,
167 .eh_host_reset_handler = NCR5380_host_reset,
168 .can_queue = 16,
169 .this_id = 7,
170 .sg_tablesize = SG_ALL,
171 .cmd_per_lun = 2,
172 .use_clustering = DISABLE_CLUSTERING
173};
174
175static struct Scsi_Host *host;
176
177static int __init ecoscsi_init(void)
178{
179
180 host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
181 if (!host)
182 return 0;
183
184 host->io_port = 0x80ce8000;
185 host->n_io_port = 144;
186 host->irq = IRQ_NONE;
187
188 if (!(request_region(host->io_port, host->n_io_port, "ecoscsi")) )
189 goto unregister_scsi;
190
191 ecoscsi_write(host, MODE_REG, 0x20); /* Is it really SCSI? */
192 if (ecoscsi_read(host, MODE_REG) != 0x20) /* Write to a reg. */
193 goto release_reg;
194
195 ecoscsi_write(host, MODE_REG, 0x00 ); /* it back. */
196 if (ecoscsi_read(host, MODE_REG) != 0x00)
197 goto release_reg;
198
199 NCR5380_init(host, 0);
200
201 printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port);
202 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
203 host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE);
204 printk("\nscsi%d:", host->host_no);
205 NCR5380_print_options(host);
206 printk("\n");
207
208 scsi_add_host(host, NULL); /* XXX handle failure */
209 scsi_scan_host(host);
210 return 0;
211
212release_reg:
213 release_region(host->io_port, host->n_io_port);
214unregister_scsi:
215 scsi_host_put(host);
216 return -ENODEV;
217}
218
219static void __exit ecoscsi_exit(void)
220{
221 scsi_remove_host(host);
222
223 if (shpnt->irq != IRQ_NONE)
224 free_irq(shpnt->irq, NULL);
225 NCR5380_exit(host);
226 if (shpnt->io_port)
227 release_region(shpnt->io_port, shpnt->n_io_port);
228
229 scsi_host_put(host);
230 return 0;
231}
232
233module_init(ecoscsi_init);
234module_exit(ecoscsi_exit);
235
236MODULE_AUTHOR("Russell King");
237MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines");
238MODULE_LICENSE("GPL");
239
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
new file mode 100644
index 000000000000..78b7e543471b
--- /dev/null
+++ b/drivers/scsi/arm/eesox.c
@@ -0,0 +1,680 @@
1/*
2 * linux/drivers/acorn/scsi/eesox.c
3 *
4 * Copyright (C) 1997-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This driver is based on experimentation. Hence, it may have made
11 * assumptions about the particular card that I have available, and
12 * may not be reliable!
13 *
14 * Changelog:
15 * 01-10-1997 RMK Created, READONLY version
16 * 15-02-1998 RMK READ/WRITE version
17 * added DMA support and hardware definitions
18 * 14-03-1998 RMK Updated DMA support
19 * Added terminator control
20 * 15-04-1998 RMK Only do PIO if FAS216 will allow it.
21 * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
22 * 02-04-2000 RMK 0.0.3 Fixed NO_IRQ/NO_DMA problem, updated for new
23 * error handling code.
24 */
25#include <linux/module.h>
26#include <linux/blkdev.h>
27#include <linux/kernel.h>
28#include <linux/string.h>
29#include <linux/ioport.h>
30#include <linux/sched.h>
31#include <linux/proc_fs.h>
32#include <linux/delay.h>
33#include <linux/interrupt.h>
34#include <linux/init.h>
35#include <linux/dma-mapping.h>
36
37#include <asm/io.h>
38#include <asm/irq.h>
39#include <asm/dma.h>
40#include <asm/ecard.h>
41#include <asm/pgtable.h>
42
43#include "../scsi.h"
44#include <scsi/scsi_host.h>
45#include "fas216.h"
46#include "scsi.h"
47
48#include <scsi/scsicam.h>
49
50#define EESOX_FAS216_OFFSET 0x3000
51#define EESOX_FAS216_SHIFT 5
52
53#define EESOX_DMASTAT 0x2800
54#define EESOX_STAT_INTR 0x01
55#define EESOX_STAT_DMA 0x02
56
57#define EESOX_CONTROL 0x2800
58#define EESOX_INTR_ENABLE 0x04
59#define EESOX_TERM_ENABLE 0x02
60#define EESOX_RESET 0x01
61
62#define EESOX_DMADATA 0x3800
63
64#define VERSION "1.10 (17/01/2003 2.5.59)"
65
66/*
67 * Use term=0,1,0,0,0 to turn terminators on/off
68 */
69static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
70
71#define NR_SG 256
72
73struct eesoxscsi_info {
74 FAS216_Info info;
75 struct expansion_card *ec;
76 void __iomem *base;
77 void __iomem *ctl_port;
78 unsigned int control;
79 struct scatterlist sg[NR_SG]; /* Scatter DMA list */
80};
81
82/* Prototype: void eesoxscsi_irqenable(ec, irqnr)
83 * Purpose : Enable interrupts on EESOX SCSI card
84 * Params : ec - expansion card structure
85 * : irqnr - interrupt number
86 */
87static void
88eesoxscsi_irqenable(struct expansion_card *ec, int irqnr)
89{
90 struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data;
91
92 info->control |= EESOX_INTR_ENABLE;
93
94 writeb(info->control, info->ctl_port);
95}
96
97/* Prototype: void eesoxscsi_irqdisable(ec, irqnr)
98 * Purpose : Disable interrupts on EESOX SCSI card
99 * Params : ec - expansion card structure
100 * : irqnr - interrupt number
101 */
102static void
103eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr)
104{
105 struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data;
106
107 info->control &= ~EESOX_INTR_ENABLE;
108
109 writeb(info->control, info->ctl_port);
110}
111
112static const expansioncard_ops_t eesoxscsi_ops = {
113 .irqenable = eesoxscsi_irqenable,
114 .irqdisable = eesoxscsi_irqdisable,
115};
116
117/* Prototype: void eesoxscsi_terminator_ctl(*host, on_off)
118 * Purpose : Turn the EESOX SCSI terminators on or off
119 * Params : host - card to turn on/off
120 * : on_off - !0 to turn on, 0 to turn off
121 */
122static void
123eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
124{
125 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
126 unsigned long flags;
127
128 spin_lock_irqsave(host->host_lock, flags);
129 if (on_off)
130 info->control |= EESOX_TERM_ENABLE;
131 else
132 info->control &= ~EESOX_TERM_ENABLE;
133
134 writeb(info->control, info->ctl_port);
135 spin_unlock_irqrestore(host->host_lock, flags);
136}
137
138/* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs)
139 * Purpose : handle interrupts from EESOX SCSI card
140 * Params : irq - interrupt number
141 * dev_id - user-defined (Scsi_Host structure)
142 * regs - processor registers at interrupt
143 */
144static irqreturn_t
145eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
146{
147 struct eesoxscsi_info *info = dev_id;
148
149 return fas216_intr(&info->info);
150}
151
152/* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type)
153 * Purpose : initialises DMA/PIO
154 * Params : host - host
155 * SCpnt - command
156 * direction - DMA on to/off of card
157 * min_type - minimum DMA support that we must have for this transfer
158 * Returns : type of transfer to be performed
159 */
160static fasdmatype_t
161eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
162 fasdmadir_t direction, fasdmatype_t min_type)
163{
164 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
165 struct device *dev = scsi_get_device(host);
166 int dmach = info->info.scsi.dma;
167
168 if (dmach != NO_DMA &&
169 (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
170 int bufs, map_dir, dma_dir;
171
172 bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
173
174 if (direction == DMA_OUT)
175 map_dir = DMA_TO_DEVICE,
176 dma_dir = DMA_MODE_WRITE;
177 else
178 map_dir = DMA_FROM_DEVICE,
179 dma_dir = DMA_MODE_READ;
180
181 dma_map_sg(dev, info->sg, bufs + 1, map_dir);
182
183 disable_dma(dmach);
184 set_dma_sg(dmach, info->sg, bufs + 1);
185 set_dma_mode(dmach, dma_dir);
186 enable_dma(dmach);
187 return fasdma_real_all;
188 }
189 /*
190 * We don't do DMA, we only do slow PIO
191 *
192 * Some day, we will do Pseudo DMA
193 */
194 return fasdma_pseudo;
195}
196
197static void eesoxscsi_buffer_in(void *buf, int length, void __iomem *base)
198{
199 const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
200 const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
201 const void __iomem *reg_dmadata = base + EESOX_DMADATA;
202 const register unsigned long mask = 0xffff;
203
204 do {
205 unsigned int status;
206
207 /*
208 * Interrupt request?
209 */
210 status = readb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT));
211 if (status & STAT_INT)
212 break;
213
214 /*
215 * DMA request active?
216 */
217 status = readb(reg_dmastat);
218 if (!(status & EESOX_STAT_DMA))
219 continue;
220
221 /*
222 * Get number of bytes in FIFO
223 */
224 status = readb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF;
225 if (status > 16)
226 status = 16;
227 if (status > length)
228 status = length;
229
230 /*
231 * Align buffer.
232 */
233 if (((u32)buf) & 2 && status >= 2) {
234 *(u16 *)buf = readl(reg_dmadata);
235 buf += 2;
236 status -= 2;
237 length -= 2;
238 }
239
240 if (status >= 8) {
241 unsigned long l1, l2;
242
243 l1 = readl(reg_dmadata) & mask;
244 l1 |= readl(reg_dmadata) << 16;
245 l2 = readl(reg_dmadata) & mask;
246 l2 |= readl(reg_dmadata) << 16;
247 *(u32 *)buf = l1;
248 buf += 4;
249 *(u32 *)buf = l2;
250 buf += 4;
251 length -= 8;
252 continue;
253 }
254
255 if (status >= 4) {
256 unsigned long l1;
257
258 l1 = readl(reg_dmadata) & mask;
259 l1 |= readl(reg_dmadata) << 16;
260
261 *(u32 *)buf = l1;
262 buf += 4;
263 length -= 4;
264 continue;
265 }
266
267 if (status >= 2) {
268 *(u16 *)buf = readl(reg_dmadata);
269 buf += 2;
270 length -= 2;
271 }
272 } while (length);
273}
274
275static void eesoxscsi_buffer_out(void *buf, int length, void __iomem *base)
276{
277 const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
278 const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
279 const void __iomem *reg_dmadata = base + EESOX_DMADATA;
280
281 do {
282 unsigned int status;
283
284 /*
285 * Interrupt request?
286 */
287 status = readb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT));
288 if (status & STAT_INT)
289 break;
290
291 /*
292 * DMA request active?
293 */
294 status = readb(reg_dmastat);
295 if (!(status & EESOX_STAT_DMA))
296 continue;
297
298 /*
299 * Get number of bytes in FIFO
300 */
301 status = readb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF;
302 if (status > 16)
303 status = 16;
304 status = 16 - status;
305 if (status > length)
306 status = length;
307 status &= ~1;
308
309 /*
310 * Align buffer.
311 */
312 if (((u32)buf) & 2 && status >= 2) {
313 writel(*(u16 *)buf << 16, reg_dmadata);
314 buf += 2;
315 status -= 2;
316 length -= 2;
317 }
318
319 if (status >= 8) {
320 unsigned long l1, l2;
321
322 l1 = *(u32 *)buf;
323 buf += 4;
324 l2 = *(u32 *)buf;
325 buf += 4;
326
327 writel(l1 << 16, reg_dmadata);
328 writel(l1, reg_dmadata);
329 writel(l2 << 16, reg_dmadata);
330 writel(l2, reg_dmadata);
331 length -= 8;
332 continue;
333 }
334
335 if (status >= 4) {
336 unsigned long l1;
337
338 l1 = *(u32 *)buf;
339 buf += 4;
340
341 writel(l1 << 16, reg_dmadata);
342 writel(l1, reg_dmadata);
343 length -= 4;
344 continue;
345 }
346
347 if (status >= 2) {
348 writel(*(u16 *)buf << 16, reg_dmadata);
349 buf += 2;
350 length -= 2;
351 }
352 } while (length);
353}
354
355static void
356eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
357 fasdmadir_t dir, int transfer_size)
358{
359 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
360 if (dir == DMA_IN) {
361 eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, info->base);
362 } else {
363 eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, info->base);
364 }
365}
366
367/* Prototype: int eesoxscsi_dma_stop(host, SCpnt)
368 * Purpose : stops DMA/PIO
369 * Params : host - host
370 * SCpnt - command
371 */
372static void
373eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
374{
375 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
376 if (info->info.scsi.dma != NO_DMA)
377 disable_dma(info->info.scsi.dma);
378}
379
380/* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host)
381 * Purpose : returns a descriptive string about this interface,
382 * Params : host - driver host structure to return info for.
383 * Returns : pointer to a static buffer containing null terminated string.
384 */
385const char *eesoxscsi_info(struct Scsi_Host *host)
386{
387 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
388 static char string[150];
389
390 sprintf(string, "%s (%s) in slot %d v%s terminators o%s",
391 host->hostt->name, info->info.scsi.type, info->ec->slot_no,
392 VERSION, info->control & EESOX_TERM_ENABLE ? "n" : "ff");
393
394 return string;
395}
396
397/* Prototype: int eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
398 * Purpose : Set a driver specific function
399 * Params : host - host to setup
400 * : buffer - buffer containing string describing operation
401 * : length - length of string
402 * Returns : -EINVAL, or 0
403 */
404static int
405eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
406{
407 int ret = length;
408
409 if (length >= 9 && strncmp(buffer, "EESOXSCSI", 9) == 0) {
410 buffer += 9;
411 length -= 9;
412
413 if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
414 if (buffer[5] == '1')
415 eesoxscsi_terminator_ctl(host, 1);
416 else if (buffer[5] == '0')
417 eesoxscsi_terminator_ctl(host, 0);
418 else
419 ret = -EINVAL;
420 } else
421 ret = -EINVAL;
422 } else
423 ret = -EINVAL;
424
425 return ret;
426}
427
428/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
429 * int length, int host_no, int inout)
430 * Purpose : Return information about the driver to a user process accessing
431 * the /proc filesystem.
432 * Params : buffer - a buffer to write information to
433 * start - a pointer into this buffer set by this routine to the start
434 * of the required information.
435 * offset - offset into information that we have read upto.
436 * length - length of buffer
437 * host_no - host number to return information for
438 * inout - 0 for reading, 1 for writing.
439 * Returns : length of data written to buffer.
440 */
441int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
442 int length, int inout)
443{
444 struct eesoxscsi_info *info;
445 char *p = buffer;
446 int pos;
447
448 if (inout == 1)
449 return eesoxscsi_set_proc_info(host, buffer, length);
450
451 info = (struct eesoxscsi_info *)host->hostdata;
452
453 p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION);
454 p += fas216_print_host(&info->info, p);
455 p += sprintf(p, "Term : o%s\n",
456 info->control & EESOX_TERM_ENABLE ? "n" : "ff");
457
458 p += fas216_print_stats(&info->info, p);
459 p += fas216_print_devices(&info->info, p);
460
461 *start = buffer + offset;
462 pos = p - buffer - offset;
463 if (pos > length)
464 pos = length;
465
466 return pos;
467}
468
469static ssize_t eesoxscsi_show_term(struct device *dev, char *buf)
470{
471 struct expansion_card *ec = ECARD_DEV(dev);
472 struct Scsi_Host *host = ecard_get_drvdata(ec);
473 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
474
475 return sprintf(buf, "%d\n", info->control & EESOX_TERM_ENABLE ? 1 : 0);
476}
477
478static ssize_t eesoxscsi_store_term(struct device *dev, const char *buf, size_t len)
479{
480 struct expansion_card *ec = ECARD_DEV(dev);
481 struct Scsi_Host *host = ecard_get_drvdata(ec);
482 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
483 unsigned long flags;
484
485 if (len > 1) {
486 spin_lock_irqsave(host->host_lock, flags);
487 if (buf[0] != '0') {
488 info->control |= EESOX_TERM_ENABLE;
489 } else {
490 info->control &= ~EESOX_TERM_ENABLE;
491 }
492 writeb(info->control, info->ctl_port);
493 spin_unlock_irqrestore(host->host_lock, flags);
494 }
495
496 return len;
497}
498
499static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
500 eesoxscsi_show_term, eesoxscsi_store_term);
501
502static Scsi_Host_Template eesox_template = {
503 .module = THIS_MODULE,
504 .proc_info = eesoxscsi_proc_info,
505 .name = "EESOX SCSI",
506 .info = eesoxscsi_info,
507 .queuecommand = fas216_queue_command,
508 .eh_host_reset_handler = fas216_eh_host_reset,
509 .eh_bus_reset_handler = fas216_eh_bus_reset,
510 .eh_device_reset_handler = fas216_eh_device_reset,
511 .eh_abort_handler = fas216_eh_abort,
512 .can_queue = 1,
513 .this_id = 7,
514 .sg_tablesize = SG_ALL,
515 .cmd_per_lun = 1,
516 .use_clustering = DISABLE_CLUSTERING,
517 .proc_name = "eesox",
518};
519
520static int __devinit
521eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
522{
523 struct Scsi_Host *host;
524 struct eesoxscsi_info *info;
525 unsigned long resbase, reslen;
526 void __iomem *base;
527 int ret;
528
529 ret = ecard_request_resources(ec);
530 if (ret)
531 goto out;
532
533 resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
534 reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
535 base = ioremap(resbase, reslen);
536 if (!base) {
537 ret = -ENOMEM;
538 goto out_region;
539 }
540
541 host = scsi_host_alloc(&eesox_template,
542 sizeof(struct eesoxscsi_info));
543 if (!host) {
544 ret = -ENOMEM;
545 goto out_unmap;
546 }
547
548 ecard_set_drvdata(ec, host);
549
550 info = (struct eesoxscsi_info *)host->hostdata;
551 info->ec = ec;
552 info->base = base;
553 info->ctl_port = base + EESOX_CONTROL;
554 info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0;
555 writeb(info->control, info->ctl_port);
556
557 info->info.scsi.io_base = base + EESOX_FAS216_OFFSET;
558 info->info.scsi.io_shift = EESOX_FAS216_SHIFT;
559 info->info.scsi.irq = ec->irq;
560 info->info.scsi.dma = ec->dma;
561 info->info.ifcfg.clockrate = 40; /* MHz */
562 info->info.ifcfg.select_timeout = 255;
563 info->info.ifcfg.asyncperiod = 200; /* ns */
564 info->info.ifcfg.sync_max_depth = 7;
565 info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK;
566 info->info.ifcfg.disconnect_ok = 1;
567 info->info.ifcfg.wide_max_size = 0;
568 info->info.ifcfg.capabilities = FASCAP_PSEUDODMA;
569 info->info.dma.setup = eesoxscsi_dma_setup;
570 info->info.dma.pseudo = eesoxscsi_dma_pseudo;
571 info->info.dma.stop = eesoxscsi_dma_stop;
572
573 ec->irqaddr = base + EESOX_DMASTAT;
574 ec->irqmask = EESOX_STAT_INTR;
575 ec->irq_data = info;
576 ec->ops = &eesoxscsi_ops;
577
578 device_create_file(&ec->dev, &dev_attr_bus_term);
579
580 ret = fas216_init(host);
581 if (ret)
582 goto out_free;
583
584 ret = request_irq(ec->irq, eesoxscsi_intr, 0, "eesoxscsi", info);
585 if (ret) {
586 printk("scsi%d: IRQ%d not free: %d\n",
587 host->host_no, ec->irq, ret);
588 goto out_remove;
589 }
590
591 if (info->info.scsi.dma != NO_DMA) {
592 if (request_dma(info->info.scsi.dma, "eesox")) {
593 printk("scsi%d: DMA%d not free, DMA disabled\n",
594 host->host_no, info->info.scsi.dma);
595 info->info.scsi.dma = NO_DMA;
596 } else {
597 set_dma_speed(info->info.scsi.dma, 180);
598 info->info.ifcfg.capabilities |= FASCAP_DMA;
599 info->info.ifcfg.cntl3 |= CNTL3_BS8;
600 }
601 }
602
603 ret = fas216_add(host, &ec->dev);
604 if (ret == 0)
605 goto out;
606
607 if (info->info.scsi.dma != NO_DMA)
608 free_dma(info->info.scsi.dma);
609 free_irq(ec->irq, host);
610
611 out_remove:
612 fas216_remove(host);
613
614 out_free:
615 device_remove_file(&ec->dev, &dev_attr_bus_term);
616 scsi_host_put(host);
617
618 out_unmap:
619 iounmap(base);
620
621 out_region:
622 ecard_release_resources(ec);
623
624 out:
625 return ret;
626}
627
628static void __devexit eesoxscsi_remove(struct expansion_card *ec)
629{
630 struct Scsi_Host *host = ecard_get_drvdata(ec);
631 struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
632
633 ecard_set_drvdata(ec, NULL);
634 fas216_remove(host);
635
636 if (info->info.scsi.dma != NO_DMA)
637 free_dma(info->info.scsi.dma);
638 free_irq(ec->irq, info);
639
640 device_remove_file(&ec->dev, &dev_attr_bus_term);
641
642 iounmap(info->base);
643
644 fas216_release(host);
645 scsi_host_put(host);
646 ecard_release_resources(ec);
647}
648
649static const struct ecard_id eesoxscsi_cids[] = {
650 { MANU_EESOX, PROD_EESOX_SCSI2 },
651 { 0xffff, 0xffff },
652};
653
654static struct ecard_driver eesoxscsi_driver = {
655 .probe = eesoxscsi_probe,
656 .remove = __devexit_p(eesoxscsi_remove),
657 .id_table = eesoxscsi_cids,
658 .drv = {
659 .name = "eesoxscsi",
660 },
661};
662
663static int __init eesox_init(void)
664{
665 return ecard_register_driver(&eesoxscsi_driver);
666}
667
668static void __exit eesox_exit(void)
669{
670 ecard_remove_driver(&eesoxscsi_driver);
671}
672
673module_init(eesox_init);
674module_exit(eesox_exit);
675
676MODULE_AUTHOR("Russell King");
677MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines");
678MODULE_PARM(term, "1-8i");
679MODULE_PARM_DESC(term, "SCSI bus termination");
680MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
new file mode 100644
index 000000000000..5411e850c833
--- /dev/null
+++ b/drivers/scsi/arm/fas216.c
@@ -0,0 +1,3043 @@
1/*
2 * linux/drivers/acorn/scsi/fas216.c
3 *
4 * Copyright (C) 1997-2003 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and
11 * other sources, including:
12 * the AMD Am53CF94 data sheet
13 * the AMD Am53C94 data sheet
14 *
15 * This is a generic driver. To use it, have a look at cumana_2.c. You
16 * should define your own structure that overlays FAS216_Info, eg:
17 * struct my_host_data {
18 * FAS216_Info info;
19 * ... my host specific data ...
20 * };
21 *
22 * Changelog:
23 * 30-08-1997 RMK Created
24 * 14-09-1997 RMK Started disconnect support
25 * 08-02-1998 RMK Corrected real DMA support
26 * 15-02-1998 RMK Started sync xfer support
27 * 06-04-1998 RMK Tightened conditions for printing incomplete
28 * transfers
29 * 02-05-1998 RMK Added extra checks in fas216_reset
30 * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns
31 * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
32 * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT
33 * 02-04-2000 RMK Converted to use the new error handling, and
34 * automatically request sense data upon check
35 * condition status from targets.
36 */
37#include <linux/module.h>
38#include <linux/blkdev.h>
39#include <linux/kernel.h>
40#include <linux/string.h>
41#include <linux/ioport.h>
42#include <linux/sched.h>
43#include <linux/proc_fs.h>
44#include <linux/delay.h>
45#include <linux/bitops.h>
46#include <linux/init.h>
47#include <linux/interrupt.h>
48
49#include <asm/dma.h>
50#include <asm/io.h>
51#include <asm/irq.h>
52#include <asm/ecard.h>
53
54#include "../scsi.h"
55#include <scsi/scsi_host.h>
56#include "fas216.h"
57#include "scsi.h"
58
59/* NOTE: SCSI2 Synchronous transfers *require* DMA according to
60 * the data sheet. This restriction is crazy, especially when
61 * you only want to send 16 bytes! What were the guys who
62 * designed this chip on at that time? Did they read the SCSI2
63 * spec at all? The following sections are taken from the SCSI2
64 * standard (s2r10) concerning this:
65 *
66 * > IMPLEMENTORS NOTES:
67 * > (1) Re-negotiation at every selection is not recommended, since a
68 * > significant performance impact is likely.
69 *
70 * > The implied synchronous agreement shall remain in effect until a BUS DEVICE
71 * > RESET message is received, until a hard reset condition occurs, or until one
72 * > of the two SCSI devices elects to modify the agreement. The default data
73 * > transfer mode is asynchronous data transfer mode. The default data transfer
74 * > mode is entered at power on, after a BUS DEVICE RESET message, or after a hard
75 * > reset condition.
76 *
77 * In total, this means that once you have elected to use synchronous
78 * transfers, you must always use DMA.
79 *
80 * I was thinking that this was a good chip until I found this restriction ;(
81 */
82#define SCSI2_SYNC
83#undef SCSI2_TAG
84
85#undef DEBUG_CONNECT
86#undef DEBUG_MESSAGES
87
88#undef CHECK_STRUCTURE
89
90#define LOG_CONNECT (1 << 0)
91#define LOG_BUSSERVICE (1 << 1)
92#define LOG_FUNCTIONDONE (1 << 2)
93#define LOG_MESSAGES (1 << 3)
94#define LOG_BUFFER (1 << 4)
95#define LOG_ERROR (1 << 8)
96
97static int level_mask = LOG_ERROR;
98
99module_param(level_mask, int, 0644);
100
101static int __init fas216_log_setup(char *str)
102{
103 char *s;
104
105 level_mask = 0;
106
107 while ((s = strsep(&str, ",")) != NULL) {
108 switch (s[0]) {
109 case 'a':
110 if (strcmp(s, "all") == 0)
111 level_mask |= -1;
112 break;
113 case 'b':
114 if (strncmp(s, "bus", 3) == 0)
115 level_mask |= LOG_BUSSERVICE;
116 if (strncmp(s, "buf", 3) == 0)
117 level_mask |= LOG_BUFFER;
118 break;
119 case 'c':
120 level_mask |= LOG_CONNECT;
121 break;
122 case 'e':
123 level_mask |= LOG_ERROR;
124 break;
125 case 'm':
126 level_mask |= LOG_MESSAGES;
127 break;
128 case 'n':
129 if (strcmp(s, "none") == 0)
130 level_mask = 0;
131 break;
132 case 's':
133 level_mask |= LOG_FUNCTIONDONE;
134 break;
135 }
136 }
137 return 1;
138}
139
140__setup("fas216_logging=", fas216_log_setup);
141
142static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
143{
144 unsigned int off = reg << info->scsi.io_shift;
145 return readb(info->scsi.io_base + off);
146}
147
148static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val)
149{
150 unsigned int off = reg << info->scsi.io_shift;
151 writeb(val, info->scsi.io_base + off);
152}
153
154static void fas216_dumpstate(FAS216_Info *info)
155{
156 unsigned char is, stat, inst;
157
158 is = fas216_readb(info, REG_IS);
159 stat = fas216_readb(info, REG_STAT);
160 inst = fas216_readb(info, REG_INST);
161
162 printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
163 " INST=%02X IS=%02X CFIS=%02X",
164 fas216_readb(info, REG_CTCL),
165 fas216_readb(info, REG_CTCM),
166 fas216_readb(info, REG_CMD), stat, inst, is,
167 fas216_readb(info, REG_CFIS));
168 printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",
169 fas216_readb(info, REG_CNTL1),
170 fas216_readb(info, REG_CNTL2),
171 fas216_readb(info, REG_CNTL3),
172 fas216_readb(info, REG_CTCH));
173}
174
175static void print_SCp(Scsi_Pointer *SCp, const char *prefix, const char *suffix)
176{
177 printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s",
178 prefix, SCp->ptr, SCp->this_residual, SCp->buffer,
179 SCp->buffers_residual, suffix);
180}
181
182static void fas216_dumpinfo(FAS216_Info *info)
183{
184 static int used = 0;
185 int i;
186
187 if (used++)
188 return;
189
190 printk("FAS216_Info=\n");
191 printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
192 info->magic_start, info->host, info->SCpnt,
193 info->origSCpnt);
194 printk(" scsi={ io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
195 info->scsi.io_shift, info->scsi.irq,
196 info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
197 info->scsi.cfg[3]);
198 printk(" type=%p phase=%X\n",
199 info->scsi.type, info->scsi.phase);
200 print_SCp(&info->scsi.SCp, " SCp={ ", " }\n");
201 printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n",
202 info->scsi.async_stp,
203 info->scsi.disconnectable, info->scsi.aborting);
204 printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"
205 " disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n",
206 info->stats.queues, info->stats.removes, info->stats.fins,
207 info->stats.reads, info->stats.writes, info->stats.miscs,
208 info->stats.disconnects, info->stats.aborts, info->stats.bus_resets,
209 info->stats.host_resets);
210 printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n",
211 info->ifcfg.clockrate, info->ifcfg.select_timeout,
212 info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
213 for (i = 0; i < 8; i++) {
214 printk(" busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
215 i, info->busyluns[i], i,
216 info->device[i].disconnect_ok, info->device[i].stp,
217 info->device[i].sof, info->device[i].sync_state);
218 }
219 printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
220 info->dma.transfer_type, info->dma.setup,
221 info->dma.pseudo, info->dma.stop);
222 printk(" internal_done=%X magic_end=%lX }\n",
223 info->internal_done, info->magic_end);
224}
225
226#ifdef CHECK_STRUCTURE
227static void __fas216_checkmagic(FAS216_Info *info, const char *func)
228{
229 int corruption = 0;
230 if (info->magic_start != MAGIC) {
231 printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n");
232 corruption++;
233 }
234 if (info->magic_end != MAGIC) {
235 printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n");
236 corruption++;
237 }
238 if (corruption) {
239 fas216_dumpinfo(info);
240 panic("scsi memory space corrupted in %s", func);
241 }
242}
243#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__)
244#else
245#define fas216_checkmagic(info)
246#endif
247
248static const char *fas216_bus_phase(int stat)
249{
250 static const char *phases[] = {
251 "DATA OUT", "DATA IN",
252 "COMMAND", "STATUS",
253 "MISC OUT", "MISC IN",
254 "MESG OUT", "MESG IN"
255 };
256
257 return phases[stat & STAT_BUSMASK];
258}
259
260static const char *fas216_drv_phase(FAS216_Info *info)
261{
262 static const char *phases[] = {
263 [PHASE_IDLE] = "idle",
264 [PHASE_SELECTION] = "selection",
265 [PHASE_COMMAND] = "command",
266 [PHASE_DATAOUT] = "data out",
267 [PHASE_DATAIN] = "data in",
268 [PHASE_MSGIN] = "message in",
269 [PHASE_MSGIN_DISCONNECT]= "disconnect",
270 [PHASE_MSGOUT_EXPECT] = "expect message out",
271 [PHASE_MSGOUT] = "message out",
272 [PHASE_STATUS] = "status",
273 [PHASE_DONE] = "done",
274 };
275
276 if (info->scsi.phase < ARRAY_SIZE(phases) &&
277 phases[info->scsi.phase])
278 return phases[info->scsi.phase];
279 return "???";
280}
281
282static char fas216_target(FAS216_Info *info)
283{
284 if (info->SCpnt)
285 return '0' + info->SCpnt->device->id;
286 else
287 return 'H';
288}
289
290static void
291fas216_do_log(FAS216_Info *info, char target, char *fmt, va_list ap)
292{
293 static char buf[1024];
294
295 vsnprintf(buf, sizeof(buf), fmt, ap);
296 printk("scsi%d.%c: %s", info->host->host_no, target, buf);
297}
298
299static void
300fas216_log_command(FAS216_Info *info, int level, Scsi_Cmnd *SCpnt, char *fmt, ...)
301{
302 va_list args;
303
304 if (level != 0 && !(level & level_mask))
305 return;
306
307 va_start(args, fmt);
308 fas216_do_log(info, '0' + SCpnt->device->id, fmt, args);
309 va_end(args);
310
311 printk(" CDB: ");
312 print_command(SCpnt->cmnd);
313}
314
315static void
316fas216_log_target(FAS216_Info *info, int level, int target, char *fmt, ...)
317{
318 va_list args;
319
320 if (level != 0 && !(level & level_mask))
321 return;
322
323 if (target < 0)
324 target = 'H';
325 else
326 target += '0';
327
328 va_start(args, fmt);
329 fas216_do_log(info, target, fmt, args);
330 va_end(args);
331
332 printk("\n");
333}
334
335static void fas216_log(FAS216_Info *info, int level, char *fmt, ...)
336{
337 va_list args;
338
339 if (level != 0 && !(level & level_mask))
340 return;
341
342 va_start(args, fmt);
343 fas216_do_log(info, fas216_target(info), fmt, args);
344 va_end(args);
345
346 printk("\n");
347}
348
349#define PH_SIZE 32
350
351static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE];
352static int ph_ptr;
353
354static void add_debug_list(int stat, int ssr, int isr, int ph)
355{
356 ph_list[ph_ptr].stat = stat;
357 ph_list[ph_ptr].ssr = ssr;
358 ph_list[ph_ptr].isr = isr;
359 ph_list[ph_ptr].ph = ph;
360
361 ph_ptr = (ph_ptr + 1) & (PH_SIZE-1);
362}
363
364static struct { int command; void *from; } cmd_list[8];
365static int cmd_ptr;
366
367static void fas216_cmd(FAS216_Info *info, unsigned int command)
368{
369 cmd_list[cmd_ptr].command = command;
370 cmd_list[cmd_ptr].from = __builtin_return_address(0);
371
372 cmd_ptr = (cmd_ptr + 1) & 7;
373
374 fas216_writeb(info, REG_CMD, command);
375}
376
377static void print_debug_list(void)
378{
379 int i;
380
381 i = ph_ptr;
382
383 printk(KERN_ERR "SCSI IRQ trail\n");
384 do {
385 printk(" %02x:%02x:%02x:%1x",
386 ph_list[i].stat, ph_list[i].ssr,
387 ph_list[i].isr, ph_list[i].ph);
388 i = (i + 1) & (PH_SIZE - 1);
389 if (((i ^ ph_ptr) & 7) == 0)
390 printk("\n");
391 } while (i != ph_ptr);
392 if ((i ^ ph_ptr) & 7)
393 printk("\n");
394
395 i = cmd_ptr;
396 printk(KERN_ERR "FAS216 commands: ");
397 do {
398 printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from);
399 i = (i + 1) & 7;
400 } while (i != cmd_ptr);
401 printk("\n");
402}
403
404static void fas216_done(FAS216_Info *info, unsigned int result);
405
406/**
407 * fas216_get_last_msg - retrive last message from the list
408 * @info: interface to search
409 * @pos: current fifo position
410 *
411 * Retrieve a last message from the list, using position in fifo.
412 */
413static inline unsigned short
414fas216_get_last_msg(FAS216_Info *info, int pos)
415{
416 unsigned short packed_msg = NOP;
417 struct message *msg;
418 int msgnr = 0;
419
420 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
421 if (pos >= msg->fifo)
422 break;
423 }
424
425 if (msg) {
426 if (msg->msg[0] == EXTENDED_MESSAGE)
427 packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8;
428 else
429 packed_msg = msg->msg[0];
430 }
431
432 fas216_log(info, LOG_MESSAGES,
433 "Message: %04x found at position %02x\n", packed_msg, pos);
434
435 return packed_msg;
436}
437
438/**
439 * fas216_syncperiod - calculate STP register value
440 * @info: state structure for interface connected to device
441 * @ns: period in ns (between subsequent bytes)
442 *
443 * Calculate value to be loaded into the STP register for a given period
444 * in ns. Returns a value suitable for REG_STP.
445 */
446static int fas216_syncperiod(FAS216_Info *info, int ns)
447{
448 int value = (info->ifcfg.clockrate * ns) / 1000;
449
450 fas216_checkmagic(info);
451
452 if (value < 4)
453 value = 4;
454 else if (value > 35)
455 value = 35;
456
457 return value & 31;
458}
459
460/**
461 * fas216_set_sync - setup FAS216 chip for specified transfer period.
462 * @info: state structure for interface connected to device
463 * @target: target
464 *
465 * Correctly setup FAS216 chip for specified transfer period.
466 * Notes : we need to switch the chip out of FASTSCSI mode if we have
467 * a transfer period >= 200ns - otherwise the chip will violate
468 * the SCSI timings.
469 */
470static void fas216_set_sync(FAS216_Info *info, int target)
471{
472 unsigned int cntl3;
473
474 fas216_writeb(info, REG_SOF, info->device[target].sof);
475 fas216_writeb(info, REG_STP, info->device[target].stp);
476
477 cntl3 = info->scsi.cfg[2];
478 if (info->device[target].period >= (200 / 4))
479 cntl3 = cntl3 & ~CNTL3_FASTSCSI;
480
481 fas216_writeb(info, REG_CNTL3, cntl3);
482}
483
484/* Synchronous transfer support
485 *
486 * Note: The SCSI II r10 spec says (5.6.12):
487 *
488 * (2) Due to historical problems with early host adapters that could
489 * not accept an SDTR message, some targets may not initiate synchronous
490 * negotiation after a power cycle as required by this standard. Host
491 * adapters that support synchronous mode may avoid the ensuing failure
492 * modes when the target is independently power cycled by initiating a
493 * synchronous negotiation on each REQUEST SENSE and INQUIRY command.
494 * This approach increases the SCSI bus overhead and is not recommended
495 * for new implementations. The correct method is to respond to an
496 * SDTR message with a MESSAGE REJECT message if the either the
497 * initiator or target devices does not support synchronous transfers
498 * or does not want to negotiate for synchronous transfers at the time.
499 * Using the correct method assures compatibility with wide data
500 * transfers and future enhancements.
501 *
502 * We will always initiate a synchronous transfer negotiation request on
503 * every INQUIRY or REQUEST SENSE message, unless the target itself has
504 * at some point performed a synchronous transfer negotiation request, or
505 * we have synchronous transfers disabled for this device.
506 */
507
508/**
509 * fas216_handlesync - Handle a synchronous transfer message
510 * @info: state structure for interface
511 * @msg: message from target
512 *
513 * Handle a synchronous transfer message from the target
514 */
515static void fas216_handlesync(FAS216_Info *info, char *msg)
516{
517 struct fas216_device *dev = &info->device[info->SCpnt->device->id];
518 enum { sync, async, none, reject } res = none;
519
520#ifdef SCSI2_SYNC
521 switch (msg[0]) {
522 case MESSAGE_REJECT:
523 /* Synchronous transfer request failed.
524 * Note: SCSI II r10:
525 *
526 * SCSI devices that are capable of synchronous
527 * data transfers shall not respond to an SDTR
528 * message with a MESSAGE REJECT message.
529 *
530 * Hence, if we get this condition, we disable
531 * negotiation for this device.
532 */
533 if (dev->sync_state == neg_inprogress) {
534 dev->sync_state = neg_invalid;
535 res = async;
536 }
537 break;
538
539 case EXTENDED_MESSAGE:
540 switch (dev->sync_state) {
541 /* We don't accept synchronous transfer requests.
542 * Respond with a MESSAGE_REJECT to prevent a
543 * synchronous transfer agreement from being reached.
544 */
545 case neg_invalid:
546 res = reject;
547 break;
548
549 /* We were not negotiating a synchronous transfer,
550 * but the device sent us a negotiation request.
551 * Honour the request by sending back a SDTR
552 * message containing our capability, limited by
553 * the targets capability.
554 */
555 default:
556 fas216_cmd(info, CMD_SETATN);
557 if (msg[4] > info->ifcfg.sync_max_depth)
558 msg[4] = info->ifcfg.sync_max_depth;
559 if (msg[3] < 1000 / info->ifcfg.clockrate)
560 msg[3] = 1000 / info->ifcfg.clockrate;
561
562 msgqueue_flush(&info->scsi.msgs);
563 msgqueue_addmsg(&info->scsi.msgs, 5,
564 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
565 msg[3], msg[4]);
566 info->scsi.phase = PHASE_MSGOUT_EXPECT;
567
568 /* This is wrong. The agreement is not in effect
569 * until this message is accepted by the device
570 */
571 dev->sync_state = neg_targcomplete;
572 res = sync;
573 break;
574
575 /* We initiated the synchronous transfer negotiation,
576 * and have successfully received a response from the
577 * target. The synchronous transfer agreement has been
578 * reached. Note: if the values returned are out of our
579 * bounds, we must reject the message.
580 */
581 case neg_inprogress:
582 res = reject;
583 if (msg[4] <= info->ifcfg.sync_max_depth &&
584 msg[3] >= 1000 / info->ifcfg.clockrate) {
585 dev->sync_state = neg_complete;
586 res = sync;
587 }
588 break;
589 }
590 }
591#else
592 res = reject;
593#endif
594
595 switch (res) {
596 case sync:
597 dev->period = msg[3];
598 dev->sof = msg[4];
599 dev->stp = fas216_syncperiod(info, msg[3] * 4);
600 fas216_set_sync(info, info->SCpnt->device->id);
601 break;
602
603 case reject:
604 fas216_cmd(info, CMD_SETATN);
605 msgqueue_flush(&info->scsi.msgs);
606 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
607 info->scsi.phase = PHASE_MSGOUT_EXPECT;
608
609 case async:
610 dev->period = info->ifcfg.asyncperiod / 4;
611 dev->sof = 0;
612 dev->stp = info->scsi.async_stp;
613 fas216_set_sync(info, info->SCpnt->device->id);
614 break;
615
616 case none:
617 break;
618 }
619}
620
621/**
622 * fas216_updateptrs - update data pointers after transfer suspended/paused
623 * @info: interface's local pointer to update
624 * @bytes_transferred: number of bytes transferred
625 *
626 * Update data pointers after transfer suspended/paused
627 */
628static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
629{
630 Scsi_Pointer *SCp = &info->scsi.SCp;
631
632 fas216_checkmagic(info);
633
634 BUG_ON(bytes_transferred < 0);
635
636 info->SCpnt->request_bufflen -= bytes_transferred;
637
638 while (bytes_transferred != 0) {
639 if (SCp->this_residual > bytes_transferred)
640 break;
641 /*
642 * We have used up this buffer. Move on to the
643 * next buffer.
644 */
645 bytes_transferred -= SCp->this_residual;
646 if (!next_SCp(SCp) && bytes_transferred) {
647 printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
648 info->host->host_no, '0' + info->SCpnt->device->id);
649 return;
650 }
651 }
652
653 SCp->this_residual -= bytes_transferred;
654 if (SCp->this_residual)
655 SCp->ptr += bytes_transferred;
656 else
657 SCp->ptr = NULL;
658}
659
660/**
661 * fas216_pio - transfer data off of/on to card using programmed IO
662 * @info: interface to transfer data to/from
663 * @direction: direction to transfer data (DMA_OUT/DMA_IN)
664 *
665 * Transfer data off of/on to card using programmed IO.
666 * Notes: this is incredibly slow.
667 */
668static void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
669{
670 Scsi_Pointer *SCp = &info->scsi.SCp;
671
672 fas216_checkmagic(info);
673
674 if (direction == DMA_OUT)
675 fas216_writeb(info, REG_FF, get_next_SCp_byte(SCp));
676 else
677 put_next_SCp_byte(SCp, fas216_readb(info, REG_FF));
678
679 if (SCp->this_residual == 0)
680 next_SCp(SCp);
681}
682
683static void fas216_set_stc(FAS216_Info *info, unsigned int length)
684{
685 fas216_writeb(info, REG_STCL, length);
686 fas216_writeb(info, REG_STCM, length >> 8);
687 fas216_writeb(info, REG_STCH, length >> 16);
688}
689
690static unsigned int fas216_get_ctc(FAS216_Info *info)
691{
692 return fas216_readb(info, REG_CTCL) +
693 (fas216_readb(info, REG_CTCM) << 8) +
694 (fas216_readb(info, REG_CTCH) << 16);
695}
696
697/**
698 * fas216_cleanuptransfer - clean up after a transfer has completed.
699 * @info: interface to clean up
700 *
701 * Update the data pointers according to the number of bytes transferred
702 * on the SCSI bus.
703 */
704static void fas216_cleanuptransfer(FAS216_Info *info)
705{
706 unsigned long total, residual, fifo;
707 fasdmatype_t dmatype = info->dma.transfer_type;
708
709 info->dma.transfer_type = fasdma_none;
710
711 /*
712 * PIO transfers do not need to be cleaned up.
713 */
714 if (dmatype == fasdma_pio || dmatype == fasdma_none)
715 return;
716
717 if (dmatype == fasdma_real_all)
718 total = info->SCpnt->request_bufflen;
719 else
720 total = info->scsi.SCp.this_residual;
721
722 residual = fas216_get_ctc(info);
723
724 fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
725
726 fas216_log(info, LOG_BUFFER, "cleaning up from previous "
727 "transfer: length 0x%06x, residual 0x%x, fifo %d",
728 total, residual, fifo);
729
730 /*
731 * If we were performing Data-Out, the transfer counter
732 * counts down each time a byte is transferred by the
733 * host to the FIFO. This means we must include the
734 * bytes left in the FIFO from the transfer counter.
735 */
736 if (info->scsi.phase == PHASE_DATAOUT)
737 residual += fifo;
738
739 fas216_updateptrs(info, total - residual);
740}
741
742/**
743 * fas216_transfer - Perform a DMA/PIO transfer off of/on to card
744 * @info: interface from which device disconnected from
745 *
746 * Start a DMA/PIO transfer off of/on to card
747 */
748static void fas216_transfer(FAS216_Info *info)
749{
750 fasdmadir_t direction;
751 fasdmatype_t dmatype;
752
753 fas216_log(info, LOG_BUFFER,
754 "starttransfer: buffer %p length 0x%06x reqlen 0x%06x",
755 info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
756 info->SCpnt->request_bufflen);
757
758 if (!info->scsi.SCp.ptr) {
759 fas216_log(info, LOG_ERROR, "null buffer passed to "
760 "fas216_starttransfer");
761 print_SCp(&info->scsi.SCp, "SCp: ", "\n");
762 print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n");
763 return;
764 }
765
766 /*
767 * If we have a synchronous transfer agreement in effect, we must
768 * use DMA mode. If we are using asynchronous transfers, we may
769 * use DMA mode or PIO mode.
770 */
771 if (info->device[info->SCpnt->device->id].sof)
772 dmatype = fasdma_real_all;
773 else
774 dmatype = fasdma_pio;
775
776 if (info->scsi.phase == PHASE_DATAOUT)
777 direction = DMA_OUT;
778 else
779 direction = DMA_IN;
780
781 if (info->dma.setup)
782 dmatype = info->dma.setup(info->host, &info->scsi.SCp,
783 direction, dmatype);
784 info->dma.transfer_type = dmatype;
785
786 if (dmatype == fasdma_real_all)
787 fas216_set_stc(info, info->SCpnt->request_bufflen);
788 else
789 fas216_set_stc(info, info->scsi.SCp.this_residual);
790
791 switch (dmatype) {
792 case fasdma_pio:
793 fas216_log(info, LOG_BUFFER, "PIO transfer");
794 fas216_writeb(info, REG_SOF, 0);
795 fas216_writeb(info, REG_STP, info->scsi.async_stp);
796 fas216_cmd(info, CMD_TRANSFERINFO);
797 fas216_pio(info, direction);
798 break;
799
800 case fasdma_pseudo:
801 fas216_log(info, LOG_BUFFER, "pseudo transfer");
802 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
803 info->dma.pseudo(info->host, &info->scsi.SCp,
804 direction, info->SCpnt->transfersize);
805 break;
806
807 case fasdma_real_block:
808 fas216_log(info, LOG_BUFFER, "block dma transfer");
809 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
810 break;
811
812 case fasdma_real_all:
813 fas216_log(info, LOG_BUFFER, "total dma transfer");
814 fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA);
815 break;
816
817 default:
818 fas216_log(info, LOG_BUFFER | LOG_ERROR,
819 "invalid FAS216 DMA type");
820 break;
821 }
822}
823
824/**
825 * fas216_stoptransfer - Stop a DMA transfer onto / off of the card
826 * @info: interface from which device disconnected from
827 *
828 * Called when we switch away from DATA IN or DATA OUT phases.
829 */
830static void fas216_stoptransfer(FAS216_Info *info)
831{
832 fas216_checkmagic(info);
833
834 if (info->dma.transfer_type == fasdma_real_all ||
835 info->dma.transfer_type == fasdma_real_block)
836 info->dma.stop(info->host, &info->scsi.SCp);
837
838 fas216_cleanuptransfer(info);
839
840 if (info->scsi.phase == PHASE_DATAIN) {
841 unsigned int fifo;
842
843 /*
844 * If we were performing Data-In, then the FIFO counter
845 * contains the number of bytes not transferred via DMA
846 * from the on-board FIFO. Read them manually.
847 */
848 fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
849 while (fifo && info->scsi.SCp.ptr) {
850 *info->scsi.SCp.ptr = fas216_readb(info, REG_FF);
851 fas216_updateptrs(info, 1);
852 fifo--;
853 }
854 } else {
855 /*
856 * After a Data-Out phase, there may be unsent
857 * bytes left in the FIFO. Flush them out.
858 */
859 fas216_cmd(info, CMD_FLUSHFIFO);
860 }
861}
862
863static void fas216_aborttransfer(FAS216_Info *info)
864{
865 fas216_checkmagic(info);
866
867 if (info->dma.transfer_type == fasdma_real_all ||
868 info->dma.transfer_type == fasdma_real_block)
869 info->dma.stop(info->host, &info->scsi.SCp);
870
871 info->dma.transfer_type = fasdma_none;
872 fas216_cmd(info, CMD_FLUSHFIFO);
873}
874
875static void fas216_kick(FAS216_Info *info);
876
877/**
878 * fas216_disconnected_intr - handle device disconnection
879 * @info: interface from which device disconnected from
880 *
881 * Handle device disconnection
882 */
883static void fas216_disconnect_intr(FAS216_Info *info)
884{
885 unsigned long flags;
886
887 fas216_checkmagic(info);
888
889 fas216_log(info, LOG_CONNECT, "disconnect phase=%02x",
890 info->scsi.phase);
891
892 msgqueue_flush(&info->scsi.msgs);
893
894 switch (info->scsi.phase) {
895 case PHASE_SELECTION: /* while selecting - no target */
896 case PHASE_SELSTEPS:
897 fas216_done(info, DID_NO_CONNECT);
898 break;
899
900 case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */
901 info->scsi.disconnectable = 1;
902 info->scsi.phase = PHASE_IDLE;
903 info->stats.disconnects += 1;
904 spin_lock_irqsave(&info->host_lock, flags);
905 if (info->scsi.phase == PHASE_IDLE)
906 fas216_kick(info);
907 spin_unlock_irqrestore(&info->host_lock, flags);
908 break;
909
910 case PHASE_DONE: /* at end of command - complete */
911 fas216_done(info, DID_OK);
912 break;
913
914 case PHASE_MSGOUT: /* message out - possible ABORT message */
915 if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) {
916 info->scsi.aborting = 0;
917 fas216_done(info, DID_ABORT);
918 break;
919 }
920
921 default: /* huh? */
922 printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
923 info->host->host_no, fas216_target(info), fas216_drv_phase(info));
924 print_debug_list();
925 fas216_stoptransfer(info);
926 fas216_done(info, DID_ERROR);
927 break;
928 }
929}
930
931/**
932 * fas216_reselected_intr - start reconnection of a device
933 * @info: interface which was reselected
934 *
935 * Start reconnection of a device
936 */
937static void
938fas216_reselected_intr(FAS216_Info *info)
939{
940 unsigned int cfis, i;
941 unsigned char msg[4];
942 unsigned char target, lun, tag;
943
944 fas216_checkmagic(info);
945
946 WARN_ON(info->scsi.phase == PHASE_SELECTION ||
947 info->scsi.phase == PHASE_SELSTEPS);
948
949 cfis = fas216_readb(info, REG_CFIS);
950
951 fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x",
952 info->scsi.phase, cfis);
953
954 cfis &= CFIS_CF;
955
956 if (cfis < 2 || cfis > 4) {
957 printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
958 info->host->host_no);
959 goto bad_message;
960 }
961
962 for (i = 0; i < cfis; i++)
963 msg[i] = fas216_readb(info, REG_FF);
964
965 if (!(msg[0] & (1 << info->host->this_id)) ||
966 !(msg[1] & 0x80))
967 goto initiator_error;
968
969 target = msg[0] & ~(1 << info->host->this_id);
970 target = ffs(target) - 1;
971 lun = msg[1] & 7;
972 tag = 0;
973
974 if (cfis >= 3) {
975 if (msg[2] != SIMPLE_QUEUE_TAG)
976 goto initiator_error;
977
978 tag = msg[3];
979 }
980
981 /* set up for synchronous transfers */
982 fas216_writeb(info, REG_SDID, target);
983 fas216_set_sync(info, target);
984 msgqueue_flush(&info->scsi.msgs);
985
986 fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x",
987 target, lun, tag);
988
989 if (info->scsi.disconnectable && info->SCpnt) {
990 info->scsi.disconnectable = 0;
991 if (info->SCpnt->device->id == target &&
992 info->SCpnt->device->lun == lun &&
993 info->SCpnt->tag == tag) {
994 fas216_log(info, LOG_CONNECT, "reconnected previously executing command");
995 } else {
996 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
997 fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue");
998 info->SCpnt = NULL;
999 }
1000 }
1001 if (!info->SCpnt) {
1002 info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,
1003 target, lun, tag);
1004 fas216_log(info, LOG_CONNECT, "had to get command");
1005 }
1006
1007 if (info->SCpnt) {
1008 /*
1009 * Restore data pointer from SAVED data pointer
1010 */
1011 info->scsi.SCp = info->SCpnt->SCp;
1012
1013 fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]",
1014 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1015 info->scsi.phase = PHASE_MSGIN;
1016 } else {
1017 /*
1018 * Our command structure not found - abort the
1019 * command on the target. Since we have no
1020 * record of this command, we can't send
1021 * an INITIATOR DETECTED ERROR message.
1022 */
1023 fas216_cmd(info, CMD_SETATN);
1024
1025#if 0
1026 if (tag)
1027 msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag);
1028 else
1029#endif
1030 msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
1031 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1032 info->scsi.aborting = 1;
1033 }
1034
1035 fas216_cmd(info, CMD_MSGACCEPTED);
1036 return;
1037
1038 initiator_error:
1039 printk(KERN_ERR "scsi%d.H: error during reselection: bytes",
1040 info->host->host_no);
1041 for (i = 0; i < cfis; i++)
1042 printk(" %02x", msg[i]);
1043 printk("\n");
1044 bad_message:
1045 fas216_cmd(info, CMD_SETATN);
1046 msgqueue_flush(&info->scsi.msgs);
1047 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
1048 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1049 fas216_cmd(info, CMD_MSGACCEPTED);
1050}
1051
1052static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen)
1053{
1054 int i;
1055
1056 switch (message[0]) {
1057 case COMMAND_COMPLETE:
1058 if (msglen != 1)
1059 goto unrecognised;
1060
1061 printk(KERN_ERR "scsi%d.%c: command complete with no "
1062 "status in MESSAGE_IN?\n",
1063 info->host->host_no, fas216_target(info));
1064 break;
1065
1066 case SAVE_POINTERS:
1067 if (msglen != 1)
1068 goto unrecognised;
1069
1070 /*
1071 * Save current data pointer to SAVED data pointer
1072 * SCSI II standard says that we must not acknowledge
1073 * this until we have really saved pointers.
1074 * NOTE: we DO NOT save the command nor status pointers
1075 * as required by the SCSI II standard. These always
1076 * point to the start of their respective areas.
1077 */
1078 info->SCpnt->SCp = info->scsi.SCp;
1079 info->SCpnt->SCp.sent_command = 0;
1080 fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
1081 "save data pointers: [%p, %X]",
1082 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1083 break;
1084
1085 case RESTORE_POINTERS:
1086 if (msglen != 1)
1087 goto unrecognised;
1088
1089 /*
1090 * Restore current data pointer from SAVED data pointer
1091 */
1092 info->scsi.SCp = info->SCpnt->SCp;
1093 fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER,
1094 "restore data pointers: [%p, 0x%x]",
1095 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1096 break;
1097
1098 case DISCONNECT:
1099 if (msglen != 1)
1100 goto unrecognised;
1101
1102 info->scsi.phase = PHASE_MSGIN_DISCONNECT;
1103 break;
1104
1105 case MESSAGE_REJECT:
1106 if (msglen != 1)
1107 goto unrecognised;
1108
1109 switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {
1110 case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:
1111 fas216_handlesync(info, message);
1112 break;
1113
1114 default:
1115 fas216_log(info, 0, "reject, last message 0x%04x",
1116 fas216_get_last_msg(info, info->scsi.msgin_fifo));
1117 }
1118 break;
1119
1120 case NOP:
1121 break;
1122
1123 case EXTENDED_MESSAGE:
1124 if (msglen < 3)
1125 goto unrecognised;
1126
1127 switch (message[2]) {
1128 case EXTENDED_SDTR: /* Sync transfer negotiation request/reply */
1129 fas216_handlesync(info, message);
1130 break;
1131
1132 default:
1133 goto unrecognised;
1134 }
1135 break;
1136
1137 default:
1138 goto unrecognised;
1139 }
1140 return;
1141
1142unrecognised:
1143 fas216_log(info, 0, "unrecognised message, rejecting");
1144 printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));
1145 for (i = 0; i < msglen; i++)
1146 printk("%s%02X", i & 31 ? " " : "\n ", message[i]);
1147 printk("\n");
1148
1149 /*
1150 * Something strange seems to be happening here -
1151 * I can't use SETATN since the chip gives me an
1152 * invalid command interrupt when I do. Weird.
1153 */
1154fas216_cmd(info, CMD_NOP);
1155fas216_dumpstate(info);
1156 fas216_cmd(info, CMD_SETATN);
1157 msgqueue_flush(&info->scsi.msgs);
1158 msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
1159 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1160fas216_dumpstate(info);
1161}
1162
1163static int fas216_wait_cmd(FAS216_Info *info, int cmd)
1164{
1165 int tout;
1166 int stat;
1167
1168 fas216_cmd(info, cmd);
1169
1170 for (tout = 1000; tout; tout -= 1) {
1171 stat = fas216_readb(info, REG_STAT);
1172 if (stat & (STAT_INT|STAT_PARITYERROR))
1173 break;
1174 udelay(1);
1175 }
1176
1177 return stat;
1178}
1179
1180static int fas216_get_msg_byte(FAS216_Info *info)
1181{
1182 unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);
1183
1184 if ((stat & STAT_INT) == 0)
1185 goto timedout;
1186
1187 if ((stat & STAT_BUSMASK) != STAT_MESGIN)
1188 goto unexpected_phase_change;
1189
1190 fas216_readb(info, REG_INST);
1191
1192 stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);
1193
1194 if ((stat & STAT_INT) == 0)
1195 goto timedout;
1196
1197 if (stat & STAT_PARITYERROR)
1198 goto parity_error;
1199
1200 if ((stat & STAT_BUSMASK) != STAT_MESGIN)
1201 goto unexpected_phase_change;
1202
1203 fas216_readb(info, REG_INST);
1204
1205 return fas216_readb(info, REG_FF);
1206
1207timedout:
1208 fas216_log(info, LOG_ERROR, "timed out waiting for message byte");
1209 return -1;
1210
1211unexpected_phase_change:
1212 fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat);
1213 return -2;
1214
1215parity_error:
1216 fas216_log(info, LOG_ERROR, "parity error during message in phase");
1217 return -3;
1218}
1219
1220/**
1221 * fas216_message - handle a function done interrupt from FAS216 chip
1222 * @info: interface which caused function done interrupt
1223 *
1224 * Handle a function done interrupt from FAS216 chip
1225 */
1226static void fas216_message(FAS216_Info *info)
1227{
1228 unsigned char *message = info->scsi.message;
1229 unsigned int msglen = 1;
1230 int msgbyte = 0;
1231
1232 fas216_checkmagic(info);
1233
1234 message[0] = fas216_readb(info, REG_FF);
1235
1236 if (message[0] == EXTENDED_MESSAGE) {
1237 msgbyte = fas216_get_msg_byte(info);
1238
1239 if (msgbyte >= 0) {
1240 message[1] = msgbyte;
1241
1242 for (msglen = 2; msglen < message[1] + 2; msglen++) {
1243 msgbyte = fas216_get_msg_byte(info);
1244
1245 if (msgbyte >= 0)
1246 message[msglen] = msgbyte;
1247 else
1248 break;
1249 }
1250 }
1251 }
1252
1253 if (msgbyte == -3)
1254 goto parity_error;
1255
1256#ifdef DEBUG_MESSAGES
1257 {
1258 int i;
1259
1260 printk("scsi%d.%c: message in: ",
1261 info->host->host_no, fas216_target(info));
1262 for (i = 0; i < msglen; i++)
1263 printk("%02X ", message[i]);
1264 printk("\n");
1265 }
1266#endif
1267
1268 fas216_parse_message(info, message, msglen);
1269 fas216_cmd(info, CMD_MSGACCEPTED);
1270 return;
1271
1272parity_error:
1273 fas216_cmd(info, CMD_SETATN);
1274 msgqueue_flush(&info->scsi.msgs);
1275 msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR);
1276 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1277 fas216_cmd(info, CMD_MSGACCEPTED);
1278 return;
1279}
1280
1281/**
1282 * fas216_send_command - send command after all message bytes have been sent
1283 * @info: interface which caused bus service
1284 *
1285 * Send a command to a target after all message bytes have been sent
1286 */
1287static void fas216_send_command(FAS216_Info *info)
1288{
1289 int i;
1290
1291 fas216_checkmagic(info);
1292
1293 fas216_cmd(info, CMD_NOP|CMD_WITHDMA);
1294 fas216_cmd(info, CMD_FLUSHFIFO);
1295
1296 /* load command */
1297 for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)
1298 fas216_writeb(info, REG_FF, info->SCpnt->cmnd[i]);
1299
1300 fas216_cmd(info, CMD_TRANSFERINFO);
1301
1302 info->scsi.phase = PHASE_COMMAND;
1303}
1304
1305/**
1306 * fas216_send_messageout - handle bus service to send a message
1307 * @info: interface which caused bus service
1308 *
1309 * Handle bus service to send a message.
1310 * Note: We do not allow the device to change the data direction!
1311 */
1312static void fas216_send_messageout(FAS216_Info *info, int start)
1313{
1314 unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);
1315
1316 fas216_checkmagic(info);
1317
1318 fas216_cmd(info, CMD_FLUSHFIFO);
1319
1320 if (tot_msglen) {
1321 struct message *msg;
1322 int msgnr = 0;
1323
1324 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
1325 int i;
1326
1327 for (i = start; i < msg->length; i++)
1328 fas216_writeb(info, REG_FF, msg->msg[i]);
1329
1330 msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);
1331 start = 0;
1332 }
1333 } else
1334 fas216_writeb(info, REG_FF, NOP);
1335
1336 fas216_cmd(info, CMD_TRANSFERINFO);
1337
1338 info->scsi.phase = PHASE_MSGOUT;
1339}
1340
1341/**
1342 * fas216_busservice_intr - handle bus service interrupt from FAS216 chip
1343 * @info: interface which caused bus service interrupt
1344 * @stat: Status register contents
1345 * @is: SCSI Status register contents
1346 *
1347 * Handle a bus service interrupt from FAS216 chip
1348 */
1349static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int is)
1350{
1351 fas216_checkmagic(info);
1352
1353 fas216_log(info, LOG_BUSSERVICE,
1354 "bus service: stat=%02x is=%02x phase=%02x",
1355 stat, is, info->scsi.phase);
1356
1357 switch (info->scsi.phase) {
1358 case PHASE_SELECTION:
1359 if ((is & IS_BITS) != IS_MSGBYTESENT)
1360 goto bad_is;
1361 break;
1362
1363 case PHASE_SELSTEPS:
1364 switch (is & IS_BITS) {
1365 case IS_SELARB:
1366 case IS_MSGBYTESENT:
1367 goto bad_is;
1368
1369 case IS_NOTCOMMAND:
1370 case IS_EARLYPHASE:
1371 if ((stat & STAT_BUSMASK) == STAT_MESGIN)
1372 break;
1373 goto bad_is;
1374
1375 case IS_COMPLETE:
1376 break;
1377 }
1378
1379 default:
1380 break;
1381 }
1382
1383 fas216_cmd(info, CMD_NOP);
1384
1385#define STATE(st,ph) ((ph) << 3 | (st))
1386 /* This table describes the legal SCSI state transitions,
1387 * as described by the SCSI II spec.
1388 */
1389 switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
1390 case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */
1391 case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */
1392 case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */
1393 case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */
1394 info->scsi.phase = PHASE_DATAIN;
1395 fas216_transfer(info);
1396 return;
1397
1398 case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */
1399 case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */
1400 fas216_cleanuptransfer(info);
1401 fas216_transfer(info);
1402 return;
1403
1404 case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */
1405 case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */
1406 case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */
1407 case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */
1408 fas216_cmd(info, CMD_FLUSHFIFO);
1409 info->scsi.phase = PHASE_DATAOUT;
1410 fas216_transfer(info);
1411 return;
1412
1413 case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */
1414 case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
1415 fas216_stoptransfer(info);
1416 case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */
1417 case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */
1418 case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */
1419 case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */
1420 fas216_cmd(info, CMD_INITCMDCOMPLETE);
1421 info->scsi.phase = PHASE_STATUS;
1422 return;
1423
1424 case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */
1425 case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */
1426 fas216_stoptransfer(info);
1427 case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */
1428 case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */
1429 case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */
1430 info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
1431 fas216_cmd(info, CMD_FLUSHFIFO);
1432 fas216_cmd(info, CMD_TRANSFERINFO);
1433 info->scsi.phase = PHASE_MSGIN;
1434 return;
1435
1436 case STATE(STAT_MESGIN, PHASE_MSGIN):
1437 info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
1438 fas216_cmd(info, CMD_TRANSFERINFO);
1439 return;
1440
1441 case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */
1442 case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */
1443 fas216_send_command(info);
1444 info->scsi.phase = PHASE_COMMAND;
1445 return;
1446
1447
1448 /*
1449 * Selection -> Message Out
1450 */
1451 case STATE(STAT_MESGOUT, PHASE_SELECTION):
1452 fas216_send_messageout(info, 1);
1453 return;
1454
1455 /*
1456 * Message Out -> Message Out
1457 */
1458 case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
1459 case STATE(STAT_MESGOUT, PHASE_MSGOUT):
1460 /*
1461 * If we get another message out phase, this usually
1462 * means some parity error occurred. Resend complete
1463 * set of messages. If we have more than one byte to
1464 * send, we need to assert ATN again.
1465 */
1466 if (info->device[info->SCpnt->device->id].parity_check) {
1467 /*
1468 * We were testing... good, the device
1469 * supports parity checking.
1470 */
1471 info->device[info->SCpnt->device->id].parity_check = 0;
1472 info->device[info->SCpnt->device->id].parity_enabled = 1;
1473 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
1474 }
1475
1476 if (msgqueue_msglength(&info->scsi.msgs) > 1)
1477 fas216_cmd(info, CMD_SETATN);
1478 /*FALLTHROUGH*/
1479
1480 /*
1481 * Any -> Message Out
1482 */
1483 case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
1484 fas216_send_messageout(info, 0);
1485 return;
1486
1487 /* Error recovery rules.
1488 * These either attempt to abort or retry the operation.
1489 * TODO: we need more of these
1490 */
1491 case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */
1492 /* error - we've sent out all the command bytes
1493 * we have.
1494 * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
1495 * to include the command bytes sent for this to work
1496 * correctly.
1497 */
1498 printk(KERN_ERR "scsi%d.%c: "
1499 "target trying to receive more command bytes\n",
1500 info->host->host_no, fas216_target(info));
1501 fas216_cmd(info, CMD_SETATN);
1502 fas216_set_stc(info, 15);
1503 fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA);
1504 msgqueue_flush(&info->scsi.msgs);
1505 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
1506 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1507 return;
1508 }
1509
1510 if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
1511 printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
1512 info->host->host_no, fas216_target(info),
1513 fas216_bus_phase(stat));
1514 msgqueue_flush(&info->scsi.msgs);
1515 fas216_cmd(info, CMD_SETATN);
1516 msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
1517 info->scsi.phase = PHASE_MSGOUT_EXPECT;
1518 info->scsi.aborting = 1;
1519 fas216_cmd(info, CMD_TRANSFERINFO);
1520 return;
1521 }
1522 printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
1523 info->host->host_no, fas216_target(info),
1524 fas216_bus_phase(stat),
1525 fas216_drv_phase(info));
1526 print_debug_list();
1527 return;
1528
1529bad_is:
1530 fas216_log(info, 0, "bus service at step %d?", is & IS_BITS);
1531 fas216_dumpstate(info);
1532 print_debug_list();
1533
1534 fas216_done(info, DID_ERROR);
1535}
1536
1537/**
1538 * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip
1539 * @info: interface which caused function done interrupt
1540 * @stat: Status register contents
1541 * @is: SCSI Status register contents
1542 *
1543 * Handle a function done interrupt from FAS216 chip
1544 */
1545static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int is)
1546{
1547 unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF;
1548
1549 fas216_checkmagic(info);
1550
1551 fas216_log(info, LOG_FUNCTIONDONE,
1552 "function done: stat=%02x is=%02x phase=%02x",
1553 stat, is, info->scsi.phase);
1554
1555 switch (info->scsi.phase) {
1556 case PHASE_STATUS: /* status phase - read status and msg */
1557 if (fifo_len != 2) {
1558 fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len);
1559 }
1560 /*
1561 * Read status then message byte.
1562 */
1563 info->scsi.SCp.Status = fas216_readb(info, REG_FF);
1564 info->scsi.SCp.Message = fas216_readb(info, REG_FF);
1565 info->scsi.phase = PHASE_DONE;
1566 fas216_cmd(info, CMD_MSGACCEPTED);
1567 break;
1568
1569 case PHASE_IDLE:
1570 case PHASE_SELECTION:
1571 case PHASE_SELSTEPS:
1572 break;
1573
1574 case PHASE_MSGIN: /* message in phase */
1575 if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
1576 info->scsi.msgin_fifo = fifo_len;
1577 fas216_message(info);
1578 break;
1579 }
1580
1581 default:
1582 fas216_log(info, 0, "internal phase %s for function done?"
1583 " What do I do with this?",
1584 fas216_target(info), fas216_drv_phase(info));
1585 }
1586}
1587
1588static void fas216_bus_reset(FAS216_Info *info)
1589{
1590 neg_t sync_state;
1591 int i;
1592
1593 msgqueue_flush(&info->scsi.msgs);
1594
1595 sync_state = neg_invalid;
1596
1597#ifdef SCSI2_SYNC
1598 if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA))
1599 sync_state = neg_wait;
1600#endif
1601
1602 info->scsi.phase = PHASE_IDLE;
1603 info->SCpnt = NULL; /* bug! */
1604 memset(&info->scsi.SCp, 0, sizeof(info->scsi.SCp));
1605
1606 for (i = 0; i < 8; i++) {
1607 info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
1608 info->device[i].sync_state = sync_state;
1609 info->device[i].period = info->ifcfg.asyncperiod / 4;
1610 info->device[i].stp = info->scsi.async_stp;
1611 info->device[i].sof = 0;
1612 info->device[i].wide_xfer = 0;
1613 }
1614
1615 info->rst_bus_status = 1;
1616 wake_up(&info->eh_wait);
1617}
1618
1619/**
1620 * fas216_intr - handle interrupts to progress a command
1621 * @info: interface to service
1622 *
1623 * Handle interrupts from the interface to progress a command
1624 */
1625irqreturn_t fas216_intr(FAS216_Info *info)
1626{
1627 unsigned char inst, is, stat;
1628 int handled = IRQ_NONE;
1629
1630 fas216_checkmagic(info);
1631
1632 stat = fas216_readb(info, REG_STAT);
1633 is = fas216_readb(info, REG_IS);
1634 inst = fas216_readb(info, REG_INST);
1635
1636 add_debug_list(stat, is, inst, info->scsi.phase);
1637
1638 if (stat & STAT_INT) {
1639 if (inst & INST_BUSRESET) {
1640 fas216_log(info, 0, "bus reset detected");
1641 fas216_bus_reset(info);
1642 scsi_report_bus_reset(info->host, 0);
1643 } else if (inst & INST_ILLEGALCMD) {
1644 fas216_log(info, LOG_ERROR, "illegal command given\n");
1645 fas216_dumpstate(info);
1646 print_debug_list();
1647 } else if (inst & INST_DISCONNECT)
1648 fas216_disconnect_intr(info);
1649 else if (inst & INST_RESELECTED) /* reselected */
1650 fas216_reselected_intr(info);
1651 else if (inst & INST_BUSSERVICE) /* bus service request */
1652 fas216_busservice_intr(info, stat, is);
1653 else if (inst & INST_FUNCDONE) /* function done */
1654 fas216_funcdone_intr(info, stat, is);
1655 else
1656 fas216_log(info, 0, "unknown interrupt received:"
1657 " phase %s inst %02X is %02X stat %02X",
1658 fas216_drv_phase(info), inst, is, stat);
1659 handled = IRQ_HANDLED;
1660 }
1661 return handled;
1662}
1663
1664static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
1665{
1666 int tot_msglen;
1667
1668 /* following what the ESP driver says */
1669 fas216_set_stc(info, 0);
1670 fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
1671
1672 /* flush FIFO */
1673 fas216_cmd(info, CMD_FLUSHFIFO);
1674
1675 /* load bus-id and timeout */
1676 fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
1677 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
1678
1679 /* synchronous transfers */
1680 fas216_set_sync(info, SCpnt->device->id);
1681
1682 tot_msglen = msgqueue_msglength(&info->scsi.msgs);
1683
1684#ifdef DEBUG_MESSAGES
1685 {
1686 struct message *msg;
1687 int msgnr = 0, i;
1688
1689 printk("scsi%d.%c: message out: ",
1690 info->host->host_no, '0' + SCpnt->device->id);
1691 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
1692 printk("{ ");
1693 for (i = 0; i < msg->length; i++)
1694 printk("%02x ", msg->msg[i]);
1695 printk("} ");
1696 }
1697 printk("\n");
1698 }
1699#endif
1700
1701 if (tot_msglen == 1 || tot_msglen == 3) {
1702 /*
1703 * We have an easy message length to send...
1704 */
1705 struct message *msg;
1706 int msgnr = 0, i;
1707
1708 info->scsi.phase = PHASE_SELSTEPS;
1709
1710 /* load message bytes */
1711 while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
1712 for (i = 0; i < msg->length; i++)
1713 fas216_writeb(info, REG_FF, msg->msg[i]);
1714 msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF);
1715 }
1716
1717 /* load command */
1718 for (i = 0; i < SCpnt->cmd_len; i++)
1719 fas216_writeb(info, REG_FF, SCpnt->cmnd[i]);
1720
1721 if (tot_msglen == 1)
1722 fas216_cmd(info, CMD_SELECTATN);
1723 else
1724 fas216_cmd(info, CMD_SELECTATN3);
1725 } else {
1726 /*
1727 * We have an unusual number of message bytes to send.
1728 * Load first byte into fifo, and issue SELECT with ATN and
1729 * stop steps.
1730 */
1731 struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
1732
1733 fas216_writeb(info, REG_FF, msg->msg[0]);
1734 msg->fifo = 1;
1735
1736 fas216_cmd(info, CMD_SELECTATNSTOP);
1737 }
1738}
1739
1740/*
1741 * Decide whether we need to perform a parity test on this device.
1742 * Can also be used to force parity error conditions during initial
1743 * information transfer phase (message out) for test purposes.
1744 */
1745static int parity_test(FAS216_Info *info, int target)
1746{
1747#if 0
1748 if (target == 3) {
1749 info->device[target].parity_check = 0;
1750 return 1;
1751 }
1752#endif
1753 return info->device[target].parity_check;
1754}
1755
1756static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
1757{
1758 int disconnect_ok;
1759
1760 /*
1761 * claim host busy
1762 */
1763 info->scsi.phase = PHASE_SELECTION;
1764 info->scsi.SCp = SCpnt->SCp;
1765 info->SCpnt = SCpnt;
1766 info->dma.transfer_type = fasdma_none;
1767
1768 if (parity_test(info, SCpnt->device->id))
1769 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE);
1770 else
1771 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
1772
1773 /*
1774 * Don't allow request sense commands to disconnect.
1775 */
1776 disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE &&
1777 info->device[SCpnt->device->id].disconnect_ok;
1778
1779 /*
1780 * build outgoing message bytes
1781 */
1782 msgqueue_flush(&info->scsi.msgs);
1783 msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun));
1784
1785 /*
1786 * add tag message if required
1787 */
1788 if (SCpnt->tag)
1789 msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
1790
1791 do {
1792#ifdef SCSI2_SYNC
1793 if ((info->device[SCpnt->device->id].sync_state == neg_wait ||
1794 info->device[SCpnt->device->id].sync_state == neg_complete) &&
1795 (SCpnt->cmnd[0] == REQUEST_SENSE ||
1796 SCpnt->cmnd[0] == INQUIRY)) {
1797 info->device[SCpnt->device->id].sync_state = neg_inprogress;
1798 msgqueue_addmsg(&info->scsi.msgs, 5,
1799 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1800 1000 / info->ifcfg.clockrate,
1801 info->ifcfg.sync_max_depth);
1802 break;
1803 }
1804#endif
1805 } while (0);
1806
1807 __fas216_start_command(info, SCpnt);
1808}
1809
1810static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt)
1811{
1812#ifdef SCSI2_TAG
1813 /*
1814 * tagged queuing - allocate a new tag to this command
1815 */
1816 if (SCpnt->device->simple_tags && SCpnt->cmnd[0] != REQUEST_SENSE &&
1817 SCpnt->cmnd[0] != INQUIRY) {
1818 SCpnt->device->current_tag += 1;
1819 if (SCpnt->device->current_tag == 0)
1820 SCpnt->device->current_tag = 1;
1821 SCpnt->tag = SCpnt->device->current_tag;
1822 } else
1823#endif
1824 set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
1825
1826 info->stats.removes += 1;
1827 switch (SCpnt->cmnd[0]) {
1828 case WRITE_6:
1829 case WRITE_10:
1830 case WRITE_12:
1831 info->stats.writes += 1;
1832 break;
1833 case READ_6:
1834 case READ_10:
1835 case READ_12:
1836 info->stats.reads += 1;
1837 break;
1838 default:
1839 info->stats.miscs += 1;
1840 break;
1841 }
1842}
1843
1844static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt)
1845{
1846 struct message *msg;
1847
1848 /*
1849 * claim host busy
1850 */
1851 info->scsi.phase = PHASE_SELECTION;
1852 info->scsi.SCp = SCpnt->SCp;
1853 info->SCpnt = SCpnt;
1854 info->dma.transfer_type = fasdma_none;
1855
1856 fas216_log(info, LOG_ERROR, "sending bus device reset");
1857
1858 msgqueue_flush(&info->scsi.msgs);
1859 msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET);
1860
1861 /* following what the ESP driver says */
1862 fas216_set_stc(info, 0);
1863 fas216_cmd(info, CMD_NOP | CMD_WITHDMA);
1864
1865 /* flush FIFO */
1866 fas216_cmd(info, CMD_FLUSHFIFO);
1867
1868 /* load bus-id and timeout */
1869 fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
1870 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
1871
1872 /* synchronous transfers */
1873 fas216_set_sync(info, SCpnt->device->id);
1874
1875 msg = msgqueue_getmsg(&info->scsi.msgs, 0);
1876
1877 fas216_writeb(info, REG_FF, BUS_DEVICE_RESET);
1878 msg->fifo = 1;
1879
1880 fas216_cmd(info, CMD_SELECTATNSTOP);
1881}
1882
1883/**
1884 * fas216_kick - kick a command to the interface
1885 * @info: our host interface to kick
1886 *
1887 * Kick a command to the interface, interface should be idle.
1888 * Notes: Interrupts are always disabled!
1889 */
1890static void fas216_kick(FAS216_Info *info)
1891{
1892 Scsi_Cmnd *SCpnt = NULL;
1893#define TYPE_OTHER 0
1894#define TYPE_RESET 1
1895#define TYPE_QUEUE 2
1896 int where_from = TYPE_OTHER;
1897
1898 fas216_checkmagic(info);
1899
1900 /*
1901 * Obtain the next command to process.
1902 */
1903 do {
1904 if (info->rstSCpnt) {
1905 SCpnt = info->rstSCpnt;
1906 /* don't remove it */
1907 where_from = TYPE_RESET;
1908 break;
1909 }
1910
1911 if (info->reqSCpnt) {
1912 SCpnt = info->reqSCpnt;
1913 info->reqSCpnt = NULL;
1914 break;
1915 }
1916
1917 if (info->origSCpnt) {
1918 SCpnt = info->origSCpnt;
1919 info->origSCpnt = NULL;
1920 break;
1921 }
1922
1923 /* retrieve next command */
1924 if (!SCpnt) {
1925 SCpnt = queue_remove_exclude(&info->queues.issue,
1926 info->busyluns);
1927 where_from = TYPE_QUEUE;
1928 break;
1929 }
1930 } while (0);
1931
1932 if (!SCpnt) {
1933 /*
1934 * no command pending, so enable reselection.
1935 */
1936 fas216_cmd(info, CMD_ENABLESEL);
1937 return;
1938 }
1939
1940 /*
1941 * We're going to start a command, so disable reselection
1942 */
1943 fas216_cmd(info, CMD_DISABLESEL);
1944
1945 if (info->scsi.disconnectable && info->SCpnt) {
1946 fas216_log(info, LOG_CONNECT,
1947 "moved command for %d to disconnected queue",
1948 info->SCpnt->device->id);
1949 queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
1950 info->scsi.disconnectable = 0;
1951 info->SCpnt = NULL;
1952 }
1953
1954 fas216_log_command(info, LOG_CONNECT | LOG_MESSAGES, SCpnt,
1955 "starting");
1956
1957 switch (where_from) {
1958 case TYPE_QUEUE:
1959 fas216_allocate_tag(info, SCpnt);
1960 case TYPE_OTHER:
1961 fas216_start_command(info, SCpnt);
1962 break;
1963 case TYPE_RESET:
1964 fas216_do_bus_device_reset(info, SCpnt);
1965 break;
1966 }
1967
1968 fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]",
1969 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
1970
1971 /*
1972 * should now get either DISCONNECT or
1973 * (FUNCTION DONE with BUS SERVICE) interrupt
1974 */
1975}
1976
1977/*
1978 * Clean up from issuing a BUS DEVICE RESET message to a device.
1979 */
1980static void
1981fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
1982{
1983 fas216_log(info, LOG_ERROR, "fas216 device reset complete");
1984
1985 info->rstSCpnt = NULL;
1986 info->rst_dev_status = 1;
1987 wake_up(&info->eh_wait);
1988}
1989
1990/**
1991 * fas216_rq_sns_done - Finish processing automatic request sense command
1992 * @info: interface that completed
1993 * @SCpnt: command that completed
1994 * @result: driver byte of result
1995 *
1996 * Finish processing automatic request sense command
1997 */
1998static void
1999fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
2000{
2001 fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
2002 "request sense complete, result=0x%04x%02x%02x",
2003 result, SCpnt->SCp.Message, SCpnt->SCp.Status);
2004
2005 if (result != DID_OK || SCpnt->SCp.Status != GOOD)
2006 /*
2007 * Something went wrong. Make sure that we don't
2008 * have valid data in the sense buffer that could
2009 * confuse the higher levels.
2010 */
2011 memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
2012//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);
2013//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
2014 /*
2015 * Note that we don't set SCpnt->result, since that should
2016 * reflect the status of the command that we were asked by
2017 * the upper layers to process. This would have been set
2018 * correctly by fas216_std_done.
2019 */
2020 SCpnt->scsi_done(SCpnt);
2021}
2022
2023/**
2024 * fas216_std_done - finish processing of standard command
2025 * @info: interface that completed
2026 * @SCpnt: command that completed
2027 * @result: driver byte of result
2028 *
2029 * Finish processing of standard command
2030 */
2031static void
2032fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
2033{
2034 info->stats.fins += 1;
2035
2036 SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |
2037 info->scsi.SCp.Status;
2038
2039 fas216_log_command(info, LOG_CONNECT, SCpnt,
2040 "command complete, result=0x%08x", SCpnt->result);
2041
2042 /*
2043 * If the driver detected an error, we're all done.
2044 */
2045 if (host_byte(SCpnt->result) != DID_OK ||
2046 msg_byte(SCpnt->result) != COMMAND_COMPLETE)
2047 goto done;
2048
2049 /*
2050 * If the command returned CHECK_CONDITION or COMMAND_TERMINATED
2051 * status, request the sense information.
2052 */
2053 if (status_byte(SCpnt->result) == CHECK_CONDITION ||
2054 status_byte(SCpnt->result) == COMMAND_TERMINATED)
2055 goto request_sense;
2056
2057 /*
2058 * If the command did not complete with GOOD status,
2059 * we are all done here.
2060 */
2061 if (status_byte(SCpnt->result) != GOOD)
2062 goto done;
2063
2064 /*
2065 * We have successfully completed a command. Make sure that
2066 * we do not have any buffers left to transfer. The world
2067 * is not perfect, and we seem to occasionally hit this.
2068 * It can be indicative of a buggy driver, target or the upper
2069 * levels of the SCSI code.
2070 */
2071 if (info->scsi.SCp.ptr) {
2072 switch (SCpnt->cmnd[0]) {
2073 case INQUIRY:
2074 case START_STOP:
2075 case MODE_SENSE:
2076 break;
2077
2078 default:
2079 printk(KERN_ERR "scsi%d.%c: incomplete data transfer "
2080 "detected: res=%08X ptr=%p len=%X CDB: ",
2081 info->host->host_no, '0' + SCpnt->device->id,
2082 SCpnt->result, info->scsi.SCp.ptr,
2083 info->scsi.SCp.this_residual);
2084 print_command(SCpnt->cmnd);
2085 SCpnt->result &= ~(255 << 16);
2086 SCpnt->result |= DID_BAD_TARGET << 16;
2087 goto request_sense;
2088 }
2089 }
2090
2091done:
2092 if (SCpnt->scsi_done) {
2093 SCpnt->scsi_done(SCpnt);
2094 return;
2095 }
2096
2097 panic("scsi%d.H: null scsi_done function in fas216_done",
2098 info->host->host_no);
2099
2100
2101request_sense:
2102 if (SCpnt->cmnd[0] == REQUEST_SENSE)
2103 goto done;
2104
2105 fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
2106 "requesting sense");
2107 memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd));
2108 SCpnt->cmnd[0] = REQUEST_SENSE;
2109 SCpnt->cmnd[1] = SCpnt->device->lun << 5;
2110 SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);
2111 SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
2112 SCpnt->SCp.buffer = NULL;
2113 SCpnt->SCp.buffers_residual = 0;
2114 SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer;
2115 SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer);
2116 SCpnt->SCp.Message = 0;
2117 SCpnt->SCp.Status = 0;
2118 SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
2119 SCpnt->sc_data_direction = SCSI_DATA_READ;
2120 SCpnt->use_sg = 0;
2121 SCpnt->tag = 0;
2122 SCpnt->host_scribble = (void *)fas216_rq_sns_done;
2123
2124 /*
2125 * Place this command into the high priority "request
2126 * sense" slot. This will be the very next command
2127 * executed, unless a target connects to us.
2128 */
2129 if (info->reqSCpnt)
2130 printk(KERN_WARNING "scsi%d.%c: loosing request command\n",
2131 info->host->host_no, '0' + SCpnt->device->id);
2132 info->reqSCpnt = SCpnt;
2133}
2134
2135/**
2136 * fas216_done - complete processing for current command
2137 * @info: interface that completed
2138 * @result: driver byte of result
2139 *
2140 * Complete processing for current command
2141 */
2142static void fas216_done(FAS216_Info *info, unsigned int result)
2143{
2144 void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int);
2145 Scsi_Cmnd *SCpnt;
2146 unsigned long flags;
2147
2148 fas216_checkmagic(info);
2149
2150 if (!info->SCpnt)
2151 goto no_command;
2152
2153 SCpnt = info->SCpnt;
2154 info->SCpnt = NULL;
2155 info->scsi.phase = PHASE_IDLE;
2156
2157 if (info->scsi.aborting) {
2158 fas216_log(info, 0, "uncaught abort - returning DID_ABORT");
2159 result = DID_ABORT;
2160 info->scsi.aborting = 0;
2161 }
2162
2163 /*
2164 * Sanity check the completion - if we have zero bytes left
2165 * to transfer, we should not have a valid pointer.
2166 */
2167 if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {
2168 printk("scsi%d.%c: zero bytes left to transfer, but "
2169 "buffer pointer still valid: ptr=%p len=%08x CDB: ",
2170 info->host->host_no, '0' + SCpnt->device->id,
2171 info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
2172 info->scsi.SCp.ptr = NULL;
2173 print_command(SCpnt->cmnd);
2174 }
2175
2176 /*
2177 * Clear down this command as completed. If we need to request
2178 * the sense information, fas216_kick will re-assert the busy
2179 * status.
2180 */
2181 info->device[SCpnt->device->id].parity_check = 0;
2182 clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
2183
2184 fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;
2185 fn(info, SCpnt, result);
2186
2187 if (info->scsi.irq != NO_IRQ) {
2188 spin_lock_irqsave(&info->host_lock, flags);
2189 if (info->scsi.phase == PHASE_IDLE)
2190 fas216_kick(info);
2191 spin_unlock_irqrestore(&info->host_lock, flags);
2192 }
2193 return;
2194
2195no_command:
2196 panic("scsi%d.H: null command in fas216_done",
2197 info->host->host_no);
2198}
2199
2200/**
2201 * fas216_queue_command - queue a command for adapter to process.
2202 * @SCpnt: Command to queue
2203 * @done: done function to call once command is complete
2204 *
2205 * Queue a command for adapter to process.
2206 * Returns: 0 on success, else error.
2207 * Notes: io_request_lock is held, interrupts are disabled.
2208 */
2209int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2210{
2211 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2212 int result;
2213
2214 fas216_checkmagic(info);
2215
2216 fas216_log_command(info, LOG_CONNECT, SCpnt,
2217 "received command (%p)", SCpnt);
2218
2219 SCpnt->scsi_done = done;
2220 SCpnt->host_scribble = (void *)fas216_std_done;
2221 SCpnt->result = 0;
2222
2223 init_SCp(SCpnt);
2224
2225 info->stats.queues += 1;
2226 SCpnt->tag = 0;
2227
2228 spin_lock(&info->host_lock);
2229
2230 /*
2231 * Add command into execute queue and let it complete under
2232 * whatever scheme we're using.
2233 */
2234 result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt);
2235
2236 /*
2237 * If we successfully added the command,
2238 * kick the interface to get it moving.
2239 */
2240 if (result == 0 && info->scsi.phase == PHASE_IDLE)
2241 fas216_kick(info);
2242 spin_unlock(&info->host_lock);
2243
2244 fas216_log_target(info, LOG_CONNECT, -1, "queue %s",
2245 result ? "failure" : "success");
2246
2247 return result;
2248}
2249
2250/**
2251 * fas216_internal_done - trigger restart of a waiting thread in fas216_noqueue_command
2252 * @SCpnt: Command to wake
2253 *
2254 * Trigger restart of a waiting thread in fas216_command
2255 */
2256static void fas216_internal_done(Scsi_Cmnd *SCpnt)
2257{
2258 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2259
2260 fas216_checkmagic(info);
2261
2262 info->internal_done = 1;
2263}
2264
2265/**
2266 * fas216_noqueue_command - process a command for the adapter.
2267 * @SCpnt: Command to queue
2268 *
2269 * Queue a command for adapter to process.
2270 * Returns: scsi result code.
2271 * Notes: io_request_lock is held, interrupts are disabled.
2272 */
2273int fas216_noqueue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2274{
2275 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2276
2277 fas216_checkmagic(info);
2278
2279 /*
2280 * We should only be using this if we don't have an interrupt.
2281 * Provide some "incentive" to use the queueing code.
2282 */
2283 BUG_ON(info->scsi.irq != NO_IRQ);
2284
2285 info->internal_done = 0;
2286 fas216_queue_command(SCpnt, fas216_internal_done);
2287
2288 /*
2289 * This wastes time, since we can't return until the command is
2290 * complete. We can't sleep either since we may get re-entered!
2291 * However, we must re-enable interrupts, or else we'll be
2292 * waiting forever.
2293 */
2294 spin_unlock_irq(info->host->host_lock);
2295
2296 while (!info->internal_done) {
2297 /*
2298 * If we don't have an IRQ, then we must poll the card for
2299 * it's interrupt, and use that to call this driver's
2300 * interrupt routine. That way, we keep the command
2301 * progressing. Maybe we can add some inteligence here
2302 * and go to sleep if we know that the device is going
2303 * to be some time (eg, disconnected).
2304 */
2305 if (fas216_readb(info, REG_STAT) & STAT_INT) {
2306 spin_lock_irq(info->host->host_lock);
2307 fas216_intr(info);
2308 spin_unlock_irq(info->host->host_lock);
2309 }
2310 }
2311
2312 spin_lock_irq(info->host->host_lock);
2313
2314 done(SCpnt);
2315
2316 return 0;
2317}
2318
2319/*
2320 * Error handler timeout function. Indicate that we timed out,
2321 * and wake up any error handler process so it can continue.
2322 */
2323static void fas216_eh_timer(unsigned long data)
2324{
2325 FAS216_Info *info = (FAS216_Info *)data;
2326
2327 fas216_log(info, LOG_ERROR, "error handling timed out\n");
2328
2329 del_timer(&info->eh_timer);
2330
2331 if (info->rst_bus_status == 0)
2332 info->rst_bus_status = -1;
2333 if (info->rst_dev_status == 0)
2334 info->rst_dev_status = -1;
2335
2336 wake_up(&info->eh_wait);
2337}
2338
2339enum res_find {
2340 res_failed, /* not found */
2341 res_success, /* command on issue queue */
2342 res_hw_abort /* command on disconnected dev */
2343};
2344
2345/**
2346 * fas216_do_abort - decide how to abort a command
2347 * @SCpnt: command to abort
2348 *
2349 * Decide how to abort a command.
2350 * Returns: abort status
2351 */
2352static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
2353{
2354 enum res_find res = res_failed;
2355
2356 if (queue_remove_cmd(&info->queues.issue, SCpnt)) {
2357 /*
2358 * The command was on the issue queue, and has not been
2359 * issued yet. We can remove the command from the queue,
2360 * and acknowledge the abort. Neither the device nor the
2361 * interface know about the command.
2362 */
2363 printk("on issue queue ");
2364
2365 res = res_success;
2366 } else if (queue_remove_cmd(&info->queues.disconnected, SCpnt)) {
2367 /*
2368 * The command was on the disconnected queue. We must
2369 * reconnect with the device if possible, and send it
2370 * an abort message.
2371 */
2372 printk("on disconnected queue ");
2373
2374 res = res_hw_abort;
2375 } else if (info->SCpnt == SCpnt) {
2376 printk("executing ");
2377
2378 switch (info->scsi.phase) {
2379 /*
2380 * If the interface is idle, and the command is 'disconnectable',
2381 * then it is the same as on the disconnected queue.
2382 */
2383 case PHASE_IDLE:
2384 if (info->scsi.disconnectable) {
2385 info->scsi.disconnectable = 0;
2386 info->SCpnt = NULL;
2387 res = res_hw_abort;
2388 }
2389 break;
2390
2391 default:
2392 break;
2393 }
2394 } else if (info->origSCpnt == SCpnt) {
2395 /*
2396 * The command will be executed next, but a command
2397 * is currently using the interface. This is similar to
2398 * being on the issue queue, except the busylun bit has
2399 * been set.
2400 */
2401 info->origSCpnt = NULL;
2402 clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
2403 printk("waiting for execution ");
2404 res = res_success;
2405 } else
2406 printk("unknown ");
2407
2408 return res;
2409}
2410
2411/**
2412 * fas216_eh_abort - abort this command
2413 * @SCpnt: command to abort
2414 *
2415 * Abort this command.
2416 * Returns: FAILED if unable to abort
2417 * Notes: io_request_lock is taken, and irqs are disabled
2418 */
2419int fas216_eh_abort(Scsi_Cmnd *SCpnt)
2420{
2421 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2422 int result = FAILED;
2423
2424 fas216_checkmagic(info);
2425
2426 info->stats.aborts += 1;
2427
2428 printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no);
2429 print_command(SCpnt->data_cmnd);
2430
2431 print_debug_list();
2432 fas216_dumpstate(info);
2433
2434 printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt);
2435
2436 switch (fas216_find_command(info, SCpnt)) {
2437 /*
2438 * We found the command, and cleared it out. Either
2439 * the command is still known to be executing on the
2440 * target, or the busylun bit is not set.
2441 */
2442 case res_success:
2443 printk("success\n");
2444 result = SUCCESS;
2445 break;
2446
2447 /*
2448 * We need to reconnect to the target and send it an
2449 * ABORT or ABORT_TAG message. We can only do this
2450 * if the bus is free.
2451 */
2452 case res_hw_abort:
2453
2454
2455 /*
2456 * We are unable to abort the command for some reason.
2457 */
2458 default:
2459 case res_failed:
2460 printk("failed\n");
2461 break;
2462 }
2463
2464 return result;
2465}
2466
2467/**
2468 * fas216_eh_device_reset - Reset the device associated with this command
2469 * @SCpnt: command specifing device to reset
2470 *
2471 * Reset the device associated with this command.
2472 * Returns: FAILED if unable to reset.
2473 * Notes: We won't be re-entered, so we'll only have one device
2474 * reset on the go at one time.
2475 */
2476int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
2477{
2478 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2479 unsigned long flags;
2480 int i, res = FAILED, target = SCpnt->device->id;
2481
2482 fas216_log(info, LOG_ERROR, "device reset for target %d", target);
2483
2484 spin_lock_irqsave(&info->host_lock, flags);
2485
2486 do {
2487 /*
2488 * If we are currently connected to a device, and
2489 * it is the device we want to reset, there is
2490 * nothing we can do here. Chances are it is stuck,
2491 * and we need a bus reset.
2492 */
2493 if (info->SCpnt && !info->scsi.disconnectable &&
2494 info->SCpnt->device->id == SCpnt->device->id)
2495 break;
2496
2497 /*
2498 * We're going to be resetting this device. Remove
2499 * all pending commands from the driver. By doing
2500 * so, we guarantee that we won't touch the command
2501 * structures except to process the reset request.
2502 */
2503 queue_remove_all_target(&info->queues.issue, target);
2504 queue_remove_all_target(&info->queues.disconnected, target);
2505 if (info->origSCpnt && info->origSCpnt->device->id == target)
2506 info->origSCpnt = NULL;
2507 if (info->reqSCpnt && info->reqSCpnt->device->id == target)
2508 info->reqSCpnt = NULL;
2509 for (i = 0; i < 8; i++)
2510 clear_bit(target * 8 + i, info->busyluns);
2511
2512 /*
2513 * Hijack this SCSI command structure to send
2514 * a bus device reset message to this device.
2515 */
2516 SCpnt->host_scribble = (void *)fas216_devicereset_done;
2517
2518 info->rst_dev_status = 0;
2519 info->rstSCpnt = SCpnt;
2520
2521 if (info->scsi.phase == PHASE_IDLE)
2522 fas216_kick(info);
2523
2524 mod_timer(&info->eh_timer, 30 * HZ);
2525 spin_unlock_irqrestore(&info->host_lock, flags);
2526
2527 /*
2528 * Wait up to 30 seconds for the reset to complete.
2529 */
2530 wait_event(info->eh_wait, info->rst_dev_status);
2531
2532 del_timer_sync(&info->eh_timer);
2533 spin_lock_irqsave(&info->host_lock, flags);
2534 info->rstSCpnt = NULL;
2535
2536 if (info->rst_dev_status == 1)
2537 res = SUCCESS;
2538 } while (0);
2539
2540 SCpnt->host_scribble = NULL;
2541 spin_unlock_irqrestore(&info->host_lock, flags);
2542
2543 fas216_log(info, LOG_ERROR, "device reset complete: %s\n",
2544 res == SUCCESS ? "success" : "failed");
2545
2546 return res;
2547}
2548
2549/**
2550 * fas216_eh_bus_reset - Reset the bus associated with the command
2551 * @SCpnt: command specifing bus to reset
2552 *
2553 * Reset the bus associated with the command.
2554 * Returns: FAILED if unable to reset.
2555 * Notes: Further commands are blocked.
2556 */
2557int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
2558{
2559 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2560 unsigned long flags;
2561 Scsi_Device *SDpnt;
2562
2563 fas216_checkmagic(info);
2564 fas216_log(info, LOG_ERROR, "resetting bus");
2565
2566 info->stats.bus_resets += 1;
2567
2568 spin_lock_irqsave(&info->host_lock, flags);
2569
2570 /*
2571 * Stop all activity on this interface.
2572 */
2573 fas216_aborttransfer(info);
2574 fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);
2575
2576 /*
2577 * Clear any pending interrupts.
2578 */
2579 while (fas216_readb(info, REG_STAT) & STAT_INT)
2580 fas216_readb(info, REG_INST);
2581
2582 info->rst_bus_status = 0;
2583
2584 /*
2585 * For each attached hard-reset device, clear out
2586 * all command structures. Leave the running
2587 * command in place.
2588 */
2589 shost_for_each_device(SDpnt, info->host) {
2590 int i;
2591
2592 if (SDpnt->soft_reset)
2593 continue;
2594
2595 queue_remove_all_target(&info->queues.issue, SDpnt->id);
2596 queue_remove_all_target(&info->queues.disconnected, SDpnt->id);
2597 if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id)
2598 info->origSCpnt = NULL;
2599 if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id)
2600 info->reqSCpnt = NULL;
2601 info->SCpnt = NULL;
2602
2603 for (i = 0; i < 8; i++)
2604 clear_bit(SDpnt->id * 8 + i, info->busyluns);
2605 }
2606
2607 info->scsi.phase = PHASE_IDLE;
2608
2609 /*
2610 * Reset the SCSI bus. Device cleanup happens in
2611 * the interrupt handler.
2612 */
2613 fas216_cmd(info, CMD_RESETSCSI);
2614
2615 mod_timer(&info->eh_timer, jiffies + HZ);
2616 spin_unlock_irqrestore(&info->host_lock, flags);
2617
2618 /*
2619 * Wait one second for the interrupt.
2620 */
2621 wait_event(info->eh_wait, info->rst_bus_status);
2622 del_timer_sync(&info->eh_timer);
2623
2624 fas216_log(info, LOG_ERROR, "bus reset complete: %s\n",
2625 info->rst_bus_status == 1 ? "success" : "failed");
2626
2627 return info->rst_bus_status == 1 ? SUCCESS : FAILED;
2628}
2629
2630/**
2631 * fas216_init_chip - Initialise FAS216 state after reset
2632 * @info: state structure for interface
2633 *
2634 * Initialise FAS216 state after reset
2635 */
2636static void fas216_init_chip(FAS216_Info *info)
2637{
2638 unsigned int clock = ((info->ifcfg.clockrate - 1) / 5 + 1) & 7;
2639 fas216_writeb(info, REG_CLKF, clock);
2640 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
2641 fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]);
2642 fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);
2643 fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
2644 fas216_writeb(info, REG_SOF, 0);
2645 fas216_writeb(info, REG_STP, info->scsi.async_stp);
2646 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
2647}
2648
2649/**
2650 * fas216_eh_host_reset - Reset the host associated with this command
2651 * @SCpnt: command specifing host to reset
2652 *
2653 * Reset the host associated with this command.
2654 * Returns: FAILED if unable to reset.
2655 * Notes: io_request_lock is taken, and irqs are disabled
2656 */
2657int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
2658{
2659 FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
2660
2661 fas216_checkmagic(info);
2662
2663 printk("scsi%d.%c: %s: resetting host\n",
2664 info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__);
2665
2666 /*
2667 * Reset the SCSI chip.
2668 */
2669 fas216_cmd(info, CMD_RESETCHIP);
2670
2671 /*
2672 * Ugly ugly ugly!
2673 * We need to release the host_lock and enable
2674 * IRQs if we sleep, but we must relock and disable
2675 * IRQs after the sleep.
2676 */
2677 spin_unlock_irq(info->host->host_lock);
2678 msleep(50 * 1000/100);
2679 spin_lock_irq(info->host->host_lock);
2680
2681 /*
2682 * Release the SCSI reset.
2683 */
2684 fas216_cmd(info, CMD_NOP);
2685
2686 fas216_init_chip(info);
2687
2688 return SUCCESS;
2689}
2690
2691#define TYPE_UNKNOWN 0
2692#define TYPE_NCR53C90 1
2693#define TYPE_NCR53C90A 2
2694#define TYPE_NCR53C9x 3
2695#define TYPE_Am53CF94 4
2696#define TYPE_EmFAS216 5
2697#define TYPE_QLFAS216 6
2698
2699static char *chip_types[] = {
2700 "unknown",
2701 "NS NCR53C90",
2702 "NS NCR53C90A",
2703 "NS NCR53C9x",
2704 "AMD Am53CF94",
2705 "Emulex FAS216",
2706 "QLogic FAS216"
2707};
2708
2709static int fas216_detect_type(FAS216_Info *info)
2710{
2711 int family, rev;
2712
2713 /*
2714 * Reset the chip.
2715 */
2716 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
2717 udelay(50);
2718 fas216_writeb(info, REG_CMD, CMD_NOP);
2719
2720 /*
2721 * Check to see if control reg 2 is present.
2722 */
2723 fas216_writeb(info, REG_CNTL3, 0);
2724 fas216_writeb(info, REG_CNTL2, CNTL2_S2FE);
2725
2726 /*
2727 * If we are unable to read back control reg 2
2728 * correctly, it is not present, and we have a
2729 * NCR53C90.
2730 */
2731 if ((fas216_readb(info, REG_CNTL2) & (~0xe0)) != CNTL2_S2FE)
2732 return TYPE_NCR53C90;
2733
2734 /*
2735 * Now, check control register 3
2736 */
2737 fas216_writeb(info, REG_CNTL2, 0);
2738 fas216_writeb(info, REG_CNTL3, 0);
2739 fas216_writeb(info, REG_CNTL3, 5);
2740
2741 /*
2742 * If we are unable to read the register back
2743 * correctly, we have a NCR53C90A
2744 */
2745 if (fas216_readb(info, REG_CNTL3) != 5)
2746 return TYPE_NCR53C90A;
2747
2748 /*
2749 * Now read the ID from the chip.
2750 */
2751 fas216_writeb(info, REG_CNTL3, 0);
2752
2753 fas216_writeb(info, REG_CNTL3, CNTL3_ADIDCHK);
2754 fas216_writeb(info, REG_CNTL3, 0);
2755
2756 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
2757 udelay(50);
2758 fas216_writeb(info, REG_CMD, CMD_WITHDMA | CMD_NOP);
2759
2760 fas216_writeb(info, REG_CNTL2, CNTL2_ENF);
2761 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
2762 udelay(50);
2763 fas216_writeb(info, REG_CMD, CMD_NOP);
2764
2765 rev = fas216_readb(info, REG_ID);
2766 family = rev >> 3;
2767 rev &= 7;
2768
2769 switch (family) {
2770 case 0x01:
2771 if (rev == 4)
2772 return TYPE_Am53CF94;
2773 break;
2774
2775 case 0x02:
2776 switch (rev) {
2777 case 2:
2778 return TYPE_EmFAS216;
2779 case 3:
2780 return TYPE_QLFAS216;
2781 }
2782 break;
2783
2784 default:
2785 break;
2786 }
2787 printk("family %x rev %x\n", family, rev);
2788 return TYPE_NCR53C9x;
2789}
2790
2791/**
2792 * fas216_reset_state - Initialise driver internal state
2793 * @info: state to initialise
2794 *
2795 * Initialise driver internal state
2796 */
2797static void fas216_reset_state(FAS216_Info *info)
2798{
2799 int i;
2800
2801 fas216_checkmagic(info);
2802
2803 fas216_bus_reset(info);
2804
2805 /*
2806 * Clear out all stale info in our state structure
2807 */
2808 memset(info->busyluns, 0, sizeof(info->busyluns));
2809 info->scsi.disconnectable = 0;
2810 info->scsi.aborting = 0;
2811
2812 for (i = 0; i < 8; i++) {
2813 info->device[i].parity_enabled = 0;
2814 info->device[i].parity_check = 1;
2815 }
2816
2817 /*
2818 * Drain all commands on disconnected queue
2819 */
2820 while (queue_remove(&info->queues.disconnected) != NULL);
2821
2822 /*
2823 * Remove executing commands.
2824 */
2825 info->SCpnt = NULL;
2826 info->reqSCpnt = NULL;
2827 info->rstSCpnt = NULL;
2828 info->origSCpnt = NULL;
2829}
2830
2831/**
2832 * fas216_init - initialise FAS/NCR/AMD SCSI structures.
2833 * @host: a driver-specific filled-out structure
2834 *
2835 * Initialise FAS/NCR/AMD SCSI structures.
2836 * Returns: 0 on success
2837 */
2838int fas216_init(struct Scsi_Host *host)
2839{
2840 FAS216_Info *info = (FAS216_Info *)host->hostdata;
2841
2842 info->magic_start = MAGIC;
2843 info->magic_end = MAGIC;
2844 info->host = host;
2845 info->scsi.cfg[0] = host->this_id | CNTL1_PERE;
2846 info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
2847 info->scsi.cfg[2] = info->ifcfg.cntl3 |
2848 CNTL3_ADIDCHK | CNTL3_QTAG | CNTL3_G2CB | CNTL3_LBTM;
2849 info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
2850
2851 info->rst_dev_status = -1;
2852 info->rst_bus_status = -1;
2853 init_waitqueue_head(&info->eh_wait);
2854 init_timer(&info->eh_timer);
2855 info->eh_timer.data = (unsigned long)info;
2856 info->eh_timer.function = fas216_eh_timer;
2857
2858 spin_lock_init(&info->host_lock);
2859
2860 memset(&info->stats, 0, sizeof(info->stats));
2861
2862 msgqueue_initialise(&info->scsi.msgs);
2863
2864 if (!queue_initialise(&info->queues.issue))
2865 return -ENOMEM;
2866
2867 if (!queue_initialise(&info->queues.disconnected)) {
2868 queue_free(&info->queues.issue);
2869 return -ENOMEM;
2870 }
2871
2872 return 0;
2873}
2874
2875/**
2876 * fas216_add - initialise FAS/NCR/AMD SCSI ic.
2877 * @host: a driver-specific filled-out structure
2878 * @dev: parent device
2879 *
2880 * Initialise FAS/NCR/AMD SCSI ic.
2881 * Returns: 0 on success
2882 */
2883int fas216_add(struct Scsi_Host *host, struct device *dev)
2884{
2885 FAS216_Info *info = (FAS216_Info *)host->hostdata;
2886 int type, ret;
2887
2888 if (info->ifcfg.clockrate <= 10 || info->ifcfg.clockrate > 40) {
2889 printk(KERN_CRIT "fas216: invalid clock rate %u MHz\n",
2890 info->ifcfg.clockrate);
2891 return -EINVAL;
2892 }
2893
2894 fas216_reset_state(info);
2895 type = fas216_detect_type(info);
2896 info->scsi.type = chip_types[type];
2897
2898 udelay(300);
2899
2900 /*
2901 * Initialise the chip correctly.
2902 */
2903 fas216_init_chip(info);
2904
2905 /*
2906 * Reset the SCSI bus. We don't want to see
2907 * the resulting reset interrupt, so mask it
2908 * out.
2909 */
2910 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_DISR);
2911 fas216_writeb(info, REG_CMD, CMD_RESETSCSI);
2912
2913 /*
2914 * scsi standard says wait 250ms
2915 */
2916 spin_unlock_irq(info->host->host_lock);
2917 msleep(100*1000/100);
2918 spin_lock_irq(info->host->host_lock);
2919
2920 fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
2921 fas216_readb(info, REG_INST);
2922
2923 fas216_checkmagic(info);
2924
2925 ret = scsi_add_host(host, dev);
2926 if (ret)
2927 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
2928 else
2929 scsi_scan_host(host);
2930
2931 return ret;
2932}
2933
2934void fas216_remove(struct Scsi_Host *host)
2935{
2936 FAS216_Info *info = (FAS216_Info *)host->hostdata;
2937
2938 fas216_checkmagic(info);
2939 scsi_remove_host(host);
2940
2941 fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
2942 scsi_host_put(host);
2943}
2944
2945/**
2946 * fas216_release - release all resources for FAS/NCR/AMD SCSI ic.
2947 * @host: a driver-specific filled-out structure
2948 *
2949 * release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.
2950 */
2951void fas216_release(struct Scsi_Host *host)
2952{
2953 FAS216_Info *info = (FAS216_Info *)host->hostdata;
2954
2955 queue_free(&info->queues.disconnected);
2956 queue_free(&info->queues.issue);
2957}
2958
2959int fas216_print_host(FAS216_Info *info, char *buffer)
2960{
2961 return sprintf(buffer,
2962 "\n"
2963 "Chip : %s\n"
2964 " Address: 0x%p\n"
2965 " IRQ : %d\n"
2966 " DMA : %d\n",
2967 info->scsi.type, info->scsi.io_base,
2968 info->scsi.irq, info->scsi.dma);
2969}
2970
2971int fas216_print_stats(FAS216_Info *info, char *buffer)
2972{
2973 char *p = buffer;
2974
2975 p += sprintf(p, "\n"
2976 "Command Statistics:\n"
2977 " Queued : %u\n"
2978 " Issued : %u\n"
2979 " Completed : %u\n"
2980 " Reads : %u\n"
2981 " Writes : %u\n"
2982 " Others : %u\n"
2983 " Disconnects: %u\n"
2984 " Aborts : %u\n"
2985 " Bus resets : %u\n"
2986 " Host resets: %u\n",
2987 info->stats.queues, info->stats.removes,
2988 info->stats.fins, info->stats.reads,
2989 info->stats.writes, info->stats.miscs,
2990 info->stats.disconnects, info->stats.aborts,
2991 info->stats.bus_resets, info->stats.host_resets);
2992
2993 return p - buffer;
2994}
2995
2996int fas216_print_devices(FAS216_Info *info, char *buffer)
2997{
2998 struct fas216_device *dev;
2999 Scsi_Device *scd;
3000 char *p = buffer;
3001
3002 p += sprintf(p, "Device/Lun TaggedQ Parity Sync\n");
3003
3004 shost_for_each_device(scd, info->host) {
3005 dev = &info->device[scd->id];
3006 p += sprintf(p, " %d/%d ", scd->id, scd->lun);
3007 if (scd->tagged_supported)
3008 p += sprintf(p, "%3sabled(%3d) ",
3009 scd->simple_tags ? "en" : "dis",
3010 scd->current_tag);
3011 else
3012 p += sprintf(p, "unsupported ");
3013
3014 p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis");
3015
3016 if (dev->sof)
3017 p += sprintf(p, "offset %d, %d ns\n",
3018 dev->sof, dev->period * 4);
3019 else
3020 p += sprintf(p, "async\n");
3021 }
3022
3023 return p - buffer;
3024}
3025
3026EXPORT_SYMBOL(fas216_init);
3027EXPORT_SYMBOL(fas216_add);
3028EXPORT_SYMBOL(fas216_queue_command);
3029EXPORT_SYMBOL(fas216_noqueue_command);
3030EXPORT_SYMBOL(fas216_intr);
3031EXPORT_SYMBOL(fas216_remove);
3032EXPORT_SYMBOL(fas216_release);
3033EXPORT_SYMBOL(fas216_eh_abort);
3034EXPORT_SYMBOL(fas216_eh_device_reset);
3035EXPORT_SYMBOL(fas216_eh_bus_reset);
3036EXPORT_SYMBOL(fas216_eh_host_reset);
3037EXPORT_SYMBOL(fas216_print_host);
3038EXPORT_SYMBOL(fas216_print_stats);
3039EXPORT_SYMBOL(fas216_print_devices);
3040
3041MODULE_AUTHOR("Russell King");
3042MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core");
3043MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
new file mode 100644
index 000000000000..60a2a120205b
--- /dev/null
+++ b/drivers/scsi/arm/fas216.h
@@ -0,0 +1,394 @@
1/*
2 * linux/drivers/acorn/scsi/fas216.h
3 *
4 * Copyright (C) 1997-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * FAS216 generic driver
11 */
12#ifndef FAS216_H
13#define FAS216_H
14
15#ifndef NO_IRQ
16#define NO_IRQ 255
17#endif
18
19#include "queue.h"
20#include "msgqueue.h"
21
22/* FAS register definitions */
23
24/* transfer count low */
25#define REG_CTCL (0)
26#define REG_STCL (0)
27
28/* transfer count medium */
29#define REG_CTCM (1)
30#define REG_STCM (1)
31
32/* fifo data */
33#define REG_FF (2)
34
35/* command */
36#define REG_CMD (3)
37#define CMD_NOP 0x00
38#define CMD_FLUSHFIFO 0x01
39#define CMD_RESETCHIP 0x02
40#define CMD_RESETSCSI 0x03
41
42#define CMD_TRANSFERINFO 0x10
43#define CMD_INITCMDCOMPLETE 0x11
44#define CMD_MSGACCEPTED 0x12
45#define CMD_PADBYTES 0x18
46#define CMD_SETATN 0x1a
47#define CMD_RSETATN 0x1b
48
49#define CMD_SELECTWOATN 0x41
50#define CMD_SELECTATN 0x42
51#define CMD_SELECTATNSTOP 0x43
52#define CMD_ENABLESEL 0x44
53#define CMD_DISABLESEL 0x45
54#define CMD_SELECTATN3 0x46
55#define CMD_RESEL3 0x47
56
57#define CMD_WITHDMA 0x80
58
59/* status register (read) */
60#define REG_STAT (4)
61#define STAT_IO (1 << 0) /* IO phase */
62#define STAT_CD (1 << 1) /* CD phase */
63#define STAT_MSG (1 << 2) /* MSG phase */
64#define STAT_TRANSFERDONE (1 << 3) /* Transfer completed */
65#define STAT_TRANSFERCNTZ (1 << 4) /* Transfer counter is zero */
66#define STAT_PARITYERROR (1 << 5) /* Parity error */
67#define STAT_REALBAD (1 << 6) /* Something bad */
68#define STAT_INT (1 << 7) /* Interrupt */
69
70#define STAT_BUSMASK (STAT_MSG|STAT_CD|STAT_IO)
71#define STAT_DATAOUT (0) /* Data out */
72#define STAT_DATAIN (STAT_IO) /* Data in */
73#define STAT_COMMAND (STAT_CD) /* Command out */
74#define STAT_STATUS (STAT_CD|STAT_IO) /* Status In */
75#define STAT_MESGOUT (STAT_MSG|STAT_CD) /* Message out */
76#define STAT_MESGIN (STAT_MSG|STAT_CD|STAT_IO) /* Message In */
77
78/* bus ID for select / reselect */
79#define REG_SDID (4)
80#define BUSID(target) ((target) & 7)
81
82/* Interrupt status register (read) */
83#define REG_INST (5)
84#define INST_SELWOATN (1 << 0) /* Select w/o ATN */
85#define INST_SELATN (1 << 1) /* Select w/ATN */
86#define INST_RESELECTED (1 << 2) /* Reselected */
87#define INST_FUNCDONE (1 << 3) /* Function done */
88#define INST_BUSSERVICE (1 << 4) /* Bus service */
89#define INST_DISCONNECT (1 << 5) /* Disconnect */
90#define INST_ILLEGALCMD (1 << 6) /* Illegal command */
91#define INST_BUSRESET (1 << 7) /* SCSI Bus reset */
92
93/* Timeout register (write) */
94#define REG_STIM (5)
95
96/* Sequence step register (read) */
97#define REG_IS (6)
98#define IS_BITS 0x07
99#define IS_SELARB 0x00 /* Select & Arb ok */
100#define IS_MSGBYTESENT 0x01 /* One byte message sent*/
101#define IS_NOTCOMMAND 0x02 /* Not in command state */
102#define IS_EARLYPHASE 0x03 /* Early phase change */
103#define IS_COMPLETE 0x04 /* Command ok */
104#define IS_SOF 0x08 /* Sync off flag */
105
106/* Transfer period step (write) */
107#define REG_STP (6)
108
109/* Synchronous Offset (write) */
110#define REG_SOF (7)
111
112/* Fifo state register (read) */
113#define REG_CFIS (7)
114#define CFIS_CF 0x1f /* Num bytes in FIFO */
115#define CFIS_IS 0xe0 /* Step */
116
117/* config register 1 */
118#define REG_CNTL1 (8)
119#define CNTL1_CID (7 << 0) /* Chip ID */
120#define CNTL1_STE (1 << 3) /* Self test enable */
121#define CNTL1_PERE (1 << 4) /* Parity enable reporting en. */
122#define CNTL1_PTE (1 << 5) /* Parity test enable */
123#define CNTL1_DISR (1 << 6) /* Disable Irq on SCSI reset */
124#define CNTL1_ETM (1 << 7) /* Extended Timing Mode */
125
126/* Clock conversion factor (read) */
127#define REG_CLKF (9)
128#define CLKF_F37MHZ 0x00 /* 35.01 - 40 MHz */
129#define CLKF_F10MHZ 0x02 /* 10 MHz */
130#define CLKF_F12MHZ 0x03 /* 10.01 - 15 MHz */
131#define CLKF_F17MHZ 0x04 /* 15.01 - 20 MHz */
132#define CLKF_F22MHZ 0x05 /* 20.01 - 25 MHz */
133#define CLKF_F27MHZ 0x06 /* 25.01 - 30 MHz */
134#define CLKF_F32MHZ 0x07 /* 30.01 - 35 MHz */
135
136/* Chip test register (write) */
137#define REG_FTM (10)
138#define TEST_FTM 0x01 /* Force target mode */
139#define TEST_FIM 0x02 /* Force initiator mode */
140#define TEST_FHI 0x04 /* Force high impedance mode */
141
142/* Configuration register 2 (read/write) */
143#define REG_CNTL2 (11)
144#define CNTL2_PGDP (1 << 0) /* Pass Th/Generate Data Parity */
145#define CNTL2_PGRP (1 << 1) /* Pass Th/Generate Reg Parity */
146#define CNTL2_ACDPE (1 << 2) /* Abort on Cmd/Data Parity Err */
147#define CNTL2_S2FE (1 << 3) /* SCSI2 Features Enable */
148#define CNTL2_TSDR (1 << 4) /* Tristate DREQ */
149#define CNTL2_SBO (1 << 5) /* Select Byte Order */
150#define CNTL2_ENF (1 << 6) /* Enable features */
151#define CNTL2_DAE (1 << 7) /* Data Alignment Enable */
152
153/* Configuration register 3 (read/write) */
154#define REG_CNTL3 (12)
155#define CNTL3_BS8 (1 << 0) /* Burst size 8 */
156#define CNTL3_MDM (1 << 1) /* Modify DMA mode */
157#define CNTL3_LBTM (1 << 2) /* Last Byte Transfer mode */
158#define CNTL3_FASTCLK (1 << 3) /* Fast SCSI clocking */
159#define CNTL3_FASTSCSI (1 << 4) /* Fast SCSI */
160#define CNTL3_G2CB (1 << 5) /* Group2 SCSI support */
161#define CNTL3_QTAG (1 << 6) /* Enable 3 byte msgs */
162#define CNTL3_ADIDCHK (1 << 7) /* Additional ID check */
163
164/* High transfer count (read/write) */
165#define REG_CTCH (14)
166#define REG_STCH (14)
167
168/* ID register (read only) */
169#define REG_ID (14)
170
171/* Data alignment */
172#define REG_DAL (15)
173
174typedef enum {
175 PHASE_IDLE, /* we're not planning on doing anything */
176 PHASE_SELECTION, /* selecting a device */
177 PHASE_SELSTEPS, /* selection with command steps */
178 PHASE_COMMAND, /* command sent */
179 PHASE_MESSAGESENT, /* selected, and we're sending cmd */
180 PHASE_DATAOUT, /* data out to device */
181 PHASE_DATAIN, /* data in from device */
182 PHASE_MSGIN, /* message in from device */
183 PHASE_MSGIN_DISCONNECT, /* disconnecting from bus */
184 PHASE_MSGOUT, /* after message out phase */
185 PHASE_MSGOUT_EXPECT, /* expecting message out */
186 PHASE_STATUS, /* status from device */
187 PHASE_DONE /* Command complete */
188} phase_t;
189
190typedef enum {
191 DMA_OUT, /* DMA from memory to chip */
192 DMA_IN /* DMA from chip to memory */
193} fasdmadir_t;
194
195typedef enum {
196 fasdma_none, /* No dma */
197 fasdma_pio, /* PIO mode */
198 fasdma_pseudo, /* Pseudo DMA */
199 fasdma_real_block, /* Real DMA, on block by block basis */
200 fasdma_real_all /* Real DMA, on request by request */
201} fasdmatype_t;
202
203typedef enum {
204 neg_wait, /* Negociate with device */
205 neg_inprogress, /* Negociation sent */
206 neg_complete, /* Negociation complete */
207 neg_targcomplete, /* Target completed negociation */
208 neg_invalid /* Negociation not supported */
209} neg_t;
210
211#define MAGIC 0x441296bdUL
212#define NR_MSGS 8
213
214#define FASCAP_DMA (1 << 0)
215#define FASCAP_PSEUDODMA (1 << 1)
216
217typedef struct {
218 unsigned long magic_start;
219 spinlock_t host_lock;
220 struct Scsi_Host *host; /* host */
221 Scsi_Cmnd *SCpnt; /* currently processing command */
222 Scsi_Cmnd *origSCpnt; /* original connecting command */
223 Scsi_Cmnd *reqSCpnt; /* request sense command */
224 Scsi_Cmnd *rstSCpnt; /* reset command */
225 Scsi_Cmnd *pending_SCpnt[8]; /* per-device pending commands */
226 int next_pending; /* next pending device */
227
228 /*
229 * Error recovery
230 */
231 wait_queue_head_t eh_wait;
232 struct timer_list eh_timer;
233 unsigned int rst_dev_status;
234 unsigned int rst_bus_status;
235
236 /* driver information */
237 struct {
238 phase_t phase; /* current phase */
239 void __iomem *io_base; /* iomem base of FAS216 */
240 unsigned int io_shift; /* shift to adjust reg offsets by */
241 unsigned char cfg[4]; /* configuration registers */
242 const char *type; /* chip type */
243 unsigned int irq; /* interrupt */
244 int dma; /* dma channel */
245
246 Scsi_Pointer SCp; /* current commands data pointer */
247
248 MsgQueue_t msgs; /* message queue for connected device */
249
250 unsigned int async_stp; /* Async transfer STP value */
251 unsigned char msgin_fifo; /* bytes in fifo at time of message in */
252 unsigned char message[256]; /* last message received from device */
253
254 unsigned char disconnectable:1; /* this command can be disconnected */
255 unsigned char aborting:1; /* aborting command */
256 } scsi;
257
258 /* statistics information */
259 struct {
260 unsigned int queues;
261 unsigned int removes;
262 unsigned int fins;
263 unsigned int reads;
264 unsigned int writes;
265 unsigned int miscs;
266 unsigned int disconnects;
267 unsigned int aborts;
268 unsigned int bus_resets;
269 unsigned int host_resets;
270 } stats;
271
272 /* configuration information */
273 struct {
274 unsigned char clockrate; /* clock rate of FAS device (MHz) */
275 unsigned char select_timeout; /* timeout (R5) */
276 unsigned char sync_max_depth; /* Synchronous xfer max fifo depth */
277 unsigned char wide_max_size; /* Maximum wide transfer size */
278 unsigned char cntl3; /* Control Reg 3 */
279 unsigned int asyncperiod; /* Async transfer period (ns) */
280 unsigned int capabilities; /* driver capabilities */
281 unsigned int disconnect_ok:1; /* Disconnects allowed? */
282 } ifcfg;
283
284 /* queue handling */
285 struct {
286 Queue_t issue; /* issue queue */
287 Queue_t disconnected; /* disconnected command queue */
288 } queues;
289
290 /* per-device info */
291 struct fas216_device {
292 unsigned char disconnect_ok:1; /* device can disconnect */
293 unsigned char parity_enabled:1; /* parity checking enabled */
294 unsigned char parity_check:1; /* need to check parity checking */
295 unsigned char period; /* sync xfer period in (*4ns) */
296 unsigned char stp; /* synchronous transfer period */
297 unsigned char sof; /* synchronous offset register */
298 unsigned char wide_xfer; /* currently negociated wide transfer */
299 neg_t sync_state; /* synchronous transfer mode */
300 neg_t wide_state; /* wide transfer mode */
301 } device[8];
302 unsigned long busyluns[64/sizeof(unsigned long)];/* array of bits indicating LUNs busy */
303
304 /* dma */
305 struct {
306 fasdmatype_t transfer_type; /* current type of DMA transfer */
307 fasdmatype_t (*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_dma);
308 void (*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer);
309 void (*stop) (struct Scsi_Host *host, Scsi_Pointer *SCp);
310 } dma;
311
312 /* miscellaneous */
313 int internal_done; /* flag to indicate request done */
314 unsigned long magic_end;
315} FAS216_Info;
316
317/* Function: int fas216_init (struct Scsi_Host *instance)
318 * Purpose : initialise FAS/NCR/AMD SCSI structures.
319 * Params : instance - a driver-specific filled-out structure
320 * Returns : 0 on success
321 */
322extern int fas216_init (struct Scsi_Host *instance);
323
324/* Function: int fas216_add (struct Scsi_Host *instance, struct device *dev)
325 * Purpose : initialise FAS/NCR/AMD SCSI ic.
326 * Params : instance - a driver-specific filled-out structure
327 * Returns : 0 on success
328 */
329extern int fas216_add (struct Scsi_Host *instance, struct device *dev);
330
331/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
332 * Purpose : queue a command for adapter to process.
333 * Params : SCpnt - Command to queue
334 * done - done function to call once command is complete
335 * Returns : 0 - success, else error
336 */
337extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
338
339/* Function: int fas216_noqueue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
340 * Purpose : queue a command for adapter to process, and process it to completion.
341 * Params : SCpnt - Command to queue
342 * done - done function to call once command is complete
343 * Returns : 0 - success, else error
344 */
345extern int fas216_noqueue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
346
347/* Function: irqreturn_t fas216_intr (FAS216_Info *info)
348 * Purpose : handle interrupts from the interface to progress a command
349 * Params : info - interface to service
350 */
351extern irqreturn_t fas216_intr (FAS216_Info *info);
352
353extern void fas216_remove (struct Scsi_Host *instance);
354
355/* Function: void fas216_release (struct Scsi_Host *instance)
356 * Purpose : release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.
357 * Params : instance - a driver-specific filled-out structure
358 * Returns : 0 on success
359 */
360extern void fas216_release (struct Scsi_Host *instance);
361
362extern int fas216_print_host(FAS216_Info *info, char *buffer);
363extern int fas216_print_stats(FAS216_Info *info, char *buffer);
364extern int fas216_print_devices(FAS216_Info *info, char *buffer);
365
366/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
367 * Purpose : abort this command
368 * Params : SCpnt - command to abort
369 * Returns : FAILED if unable to abort
370 */
371extern int fas216_eh_abort(Scsi_Cmnd *SCpnt);
372
373/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
374 * Purpose : Reset the device associated with this command
375 * Params : SCpnt - command specifing device to reset
376 * Returns : FAILED if unable to reset
377 */
378extern int fas216_eh_device_reset(Scsi_Cmnd *SCpnt);
379
380/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
381 * Purpose : Reset the complete bus associated with this command
382 * Params : SCpnt - command specifing bus to reset
383 * Returns : FAILED if unable to reset
384 */
385extern int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt);
386
387/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
388 * Purpose : Reset the host associated with this command
389 * Params : SCpnt - command specifing host to reset
390 * Returns : FAILED if unable to reset
391 */
392extern int fas216_eh_host_reset(Scsi_Cmnd *SCpnt);
393
394#endif /* FAS216_H */
diff --git a/drivers/scsi/arm/msgqueue.c b/drivers/scsi/arm/msgqueue.c
new file mode 100644
index 000000000000..7c95c7582b29
--- /dev/null
+++ b/drivers/scsi/arm/msgqueue.c
@@ -0,0 +1,171 @@
1/*
2 * linux/drivers/acorn/scsi/msgqueue.c
3 *
4 * Copyright (C) 1997-1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * message queue handling
11 */
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/stddef.h>
15#include <linux/init.h>
16
17#include "msgqueue.h"
18
19/*
20 * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
21 * Purpose : Allocate a message queue entry
22 * Params : msgq - message queue to claim entry for
23 * Returns : message queue entry or NULL.
24 */
25static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
26{
27 struct msgqueue_entry *mq;
28
29 if ((mq = msgq->free) != NULL)
30 msgq->free = mq->next;
31
32 return mq;
33}
34
35/*
36 * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
37 * Purpose : free a message queue entry
38 * Params : msgq - message queue to free entry from
39 * mq - message queue entry to free
40 */
41static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
42{
43 if (mq) {
44 mq->next = msgq->free;
45 msgq->free = mq;
46 }
47}
48
49/*
50 * Function: void msgqueue_initialise(MsgQueue_t *msgq)
51 * Purpose : initialise a message queue
52 * Params : msgq - queue to initialise
53 */
54void msgqueue_initialise(MsgQueue_t *msgq)
55{
56 int i;
57
58 msgq->qe = NULL;
59 msgq->free = &msgq->entries[0];
60
61 for (i = 0; i < NR_MESSAGES; i++)
62 msgq->entries[i].next = &msgq->entries[i + 1];
63
64 msgq->entries[NR_MESSAGES - 1].next = NULL;
65}
66
67
68/*
69 * Function: void msgqueue_free(MsgQueue_t *msgq)
70 * Purpose : free a queue
71 * Params : msgq - queue to free
72 */
73void msgqueue_free(MsgQueue_t *msgq)
74{
75}
76
77/*
78 * Function: int msgqueue_msglength(MsgQueue_t *msgq)
79 * Purpose : calculate the total length of all messages on the message queue
80 * Params : msgq - queue to examine
81 * Returns : number of bytes of messages in queue
82 */
83int msgqueue_msglength(MsgQueue_t *msgq)
84{
85 struct msgqueue_entry *mq = msgq->qe;
86 int length = 0;
87
88 for (mq = msgq->qe; mq; mq = mq->next)
89 length += mq->msg.length;
90
91 return length;
92}
93
94/*
95 * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
96 * Purpose : return a message
97 * Params : msgq - queue to obtain message from
98 * : msgno - message number
99 * Returns : pointer to message string, or NULL
100 */
101struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
102{
103 struct msgqueue_entry *mq;
104
105 for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--);
106
107 return mq ? &mq->msg : NULL;
108}
109
110/*
111 * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
112 * Purpose : add a message onto a message queue
113 * Params : msgq - queue to add message on
114 * length - length of message
115 * ... - message bytes
116 * Returns : != 0 if successful
117 */
118int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
119{
120 struct msgqueue_entry *mq = mqe_alloc(msgq);
121 va_list ap;
122
123 if (mq) {
124 struct msgqueue_entry **mqp;
125 int i;
126
127 va_start(ap, length);
128 for (i = 0; i < length; i++)
129 mq->msg.msg[i] = va_arg(ap, unsigned int);
130 va_end(ap);
131
132 mq->msg.length = length;
133 mq->msg.fifo = 0;
134 mq->next = NULL;
135
136 mqp = &msgq->qe;
137 while (*mqp)
138 mqp = &(*mqp)->next;
139
140 *mqp = mq;
141 }
142
143 return mq != NULL;
144}
145
146/*
147 * Function: void msgqueue_flush(MsgQueue_t *msgq)
148 * Purpose : flush all messages from message queue
149 * Params : msgq - queue to flush
150 */
151void msgqueue_flush(MsgQueue_t *msgq)
152{
153 struct msgqueue_entry *mq, *mqnext;
154
155 for (mq = msgq->qe; mq; mq = mqnext) {
156 mqnext = mq->next;
157 mqe_free(msgq, mq);
158 }
159 msgq->qe = NULL;
160}
161
162EXPORT_SYMBOL(msgqueue_initialise);
163EXPORT_SYMBOL(msgqueue_free);
164EXPORT_SYMBOL(msgqueue_msglength);
165EXPORT_SYMBOL(msgqueue_getmsg);
166EXPORT_SYMBOL(msgqueue_addmsg);
167EXPORT_SYMBOL(msgqueue_flush);
168
169MODULE_AUTHOR("Russell King");
170MODULE_DESCRIPTION("SCSI message queue handling");
171MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/msgqueue.h b/drivers/scsi/arm/msgqueue.h
new file mode 100644
index 000000000000..41c7333df3e3
--- /dev/null
+++ b/drivers/scsi/arm/msgqueue.h
@@ -0,0 +1,82 @@
1/*
2 * linux/drivers/acorn/scsi/msgqueue.h
3 *
4 * Copyright (C) 1997 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * message queue handling
11 */
12#ifndef MSGQUEUE_H
13#define MSGQUEUE_H
14
15struct message {
16 char msg[8];
17 int length;
18 int fifo;
19};
20
21struct msgqueue_entry {
22 struct message msg;
23 struct msgqueue_entry *next;
24};
25
26#define NR_MESSAGES 4
27
28typedef struct {
29 struct msgqueue_entry *qe;
30 struct msgqueue_entry *free;
31 struct msgqueue_entry entries[NR_MESSAGES];
32} MsgQueue_t;
33
34/*
35 * Function: void msgqueue_initialise(MsgQueue_t *msgq)
36 * Purpose : initialise a message queue
37 * Params : msgq - queue to initialise
38 */
39extern void msgqueue_initialise(MsgQueue_t *msgq);
40
41/*
42 * Function: void msgqueue_free(MsgQueue_t *msgq)
43 * Purpose : free a queue
44 * Params : msgq - queue to free
45 */
46extern void msgqueue_free(MsgQueue_t *msgq);
47
48/*
49 * Function: int msgqueue_msglength(MsgQueue_t *msgq)
50 * Purpose : calculate the total length of all messages on the message queue
51 * Params : msgq - queue to examine
52 * Returns : number of bytes of messages in queue
53 */
54extern int msgqueue_msglength(MsgQueue_t *msgq);
55
56/*
57 * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
58 * Purpose : return a message & its length
59 * Params : msgq - queue to obtain message from
60 * : msgno - message number
61 * Returns : pointer to message string, or NULL
62 */
63extern struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno);
64
65/*
66 * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
67 * Purpose : add a message onto a message queue
68 * Params : msgq - queue to add message on
69 * length - length of message
70 * ... - message bytes
71 * Returns : != 0 if successful
72 */
73extern int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...);
74
75/*
76 * Function: void msgqueue_flush(MsgQueue_t *msgq)
77 * Purpose : flush all messages from message queue
78 * Params : msgq - queue to flush
79 */
80extern void msgqueue_flush(MsgQueue_t *msgq);
81
82#endif
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
new file mode 100644
index 000000000000..ff2554f4cb80
--- /dev/null
+++ b/drivers/scsi/arm/oak.c
@@ -0,0 +1,217 @@
1/*
2 * Oak Generic NCR5380 driver
3 *
4 * Copyright 1995-2002, Russell King
5 */
6
7#include <linux/module.h>
8#include <linux/signal.h>
9#include <linux/sched.h>
10#include <linux/ioport.h>
11#include <linux/delay.h>
12#include <linux/blkdev.h>
13#include <linux/init.h>
14
15#include <asm/ecard.h>
16#include <asm/io.h>
17#include <asm/system.h>
18
19#include "../scsi.h"
20#include <scsi/scsi_host.h>
21
22#define AUTOSENSE
23/*#define PSEUDO_DMA*/
24
25#define OAKSCSI_PUBLIC_RELEASE 1
26
27#define NCR5380_read(reg) oakscsi_read(_instance, reg)
28#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
29#define NCR5380_intr oakscsi_intr
30#define NCR5380_queue_command oakscsi_queue_command
31#define NCR5380_proc_info oakscsi_proc_info
32
33#define NCR5380_implementation_fields int port, ctrl
34#define NCR5380_local_declare() struct Scsi_Host *_instance
35#define NCR5380_setup(instance) _instance = instance
36
37#define BOARD_NORMAL 0
38#define BOARD_NCR53C400 1
39
40#include "../NCR5380.h"
41
42#undef START_DMA_INITIATOR_RECEIVE_REG
43#define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
44
45const char * oakscsi_info (struct Scsi_Host *spnt)
46{
47 return "";
48}
49
50#define STAT(p) inw(p + 144)
51extern void inswb(int from, void *to, int len);
52
53static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
54 int len)
55{
56 int iobase = instance->io_port;
57printk("writing %p len %d\n",addr, len);
58 if(!len) return -1;
59
60 while(1)
61 {
62 int status;
63 while(((status = STAT(iobase)) & 0x100)==0);
64 }
65}
66
67static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
68 int len)
69{
70 int iobase = instance->io_port;
71printk("reading %p len %d\n", addr, len);
72 while(len > 0)
73 {
74 int status, timeout;
75 unsigned long b;
76
77 timeout = 0x01FFFFFF;
78
79 while(((status = STAT(iobase)) & 0x100)==0)
80 {
81 timeout--;
82 if(status & 0x200 || !timeout)
83 {
84 printk("status = %08X\n",status);
85 return 1;
86 }
87 }
88 if(len >= 128)
89 {
90 inswb(iobase + 136, addr, 128);
91 addr += 128;
92 len -= 128;
93 }
94 else
95 {
96 b = (unsigned long) inw(iobase + 136);
97 *addr ++ = b;
98 len -= 1;
99 if(len)
100 *addr ++ = b>>8;
101 len -= 1;
102 }
103 }
104 return 0;
105}
106
107#define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg)))
108#define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg)))
109
110#undef STAT
111
112#include "../NCR5380.c"
113
114static Scsi_Host_Template oakscsi_template = {
115 .module = THIS_MODULE,
116 .proc_info = oakscsi_proc_info,
117 .name = "Oak 16-bit SCSI",
118 .info = oakscsi_info,
119 .queuecommand = oakscsi_queue_command,
120 .eh_abort_handler = NCR5380_abort,
121 .eh_device_reset_handler= NCR5380_device_reset,
122 .eh_bus_reset_handler = NCR5380_bus_reset,
123 .eh_host_reset_handler = NCR5380_host_reset,
124 .can_queue = 16,
125 .this_id = 7,
126 .sg_tablesize = SG_ALL,
127 .cmd_per_lun = 2,
128 .use_clustering = DISABLE_CLUSTERING,
129 .proc_name = "oakscsi",
130};
131
132static int __devinit
133oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
134{
135 struct Scsi_Host *host;
136 int ret = -ENOMEM;
137
138 host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata));
139 if (!host)
140 goto out;
141
142 host->io_port = ecard_address(ec, ECARD_MEMC, 0);
143 host->irq = IRQ_NONE;
144 host->n_io_port = 255;
145
146 ret = -EBUSY;
147 if (!request_region (host->io_port, host->n_io_port, "Oak SCSI"))
148 goto unreg;
149
150 NCR5380_init(host, 0);
151
152 printk("scsi%d: at port 0x%08lx irqs disabled",
153 host->host_no, host->io_port);
154 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
155 host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
156 printk("\nscsi%d:", host->host_no);
157 NCR5380_print_options(host);
158 printk("\n");
159
160 ret = scsi_add_host(host, &ec->dev);
161 if (ret)
162 goto out_release;
163
164 scsi_scan_host(host);
165 goto out;
166
167 out_release:
168 release_region(host->io_port, host->n_io_port);
169 unreg:
170 scsi_host_put(host);
171 out:
172 return ret;
173}
174
175static void __devexit oakscsi_remove(struct expansion_card *ec)
176{
177 struct Scsi_Host *host = ecard_get_drvdata(ec);
178
179 ecard_set_drvdata(ec, NULL);
180 scsi_remove_host(host);
181
182 NCR5380_exit(host);
183 release_region(host->io_port, host->n_io_port);
184 scsi_host_put(host);
185}
186
187static const struct ecard_id oakscsi_cids[] = {
188 { MANU_OAK, PROD_OAK_SCSI },
189 { 0xffff, 0xffff }
190};
191
192static struct ecard_driver oakscsi_driver = {
193 .probe = oakscsi_probe,
194 .remove = __devexit_p(oakscsi_remove),
195 .id_table = oakscsi_cids,
196 .drv = {
197 .name = "oakscsi",
198 },
199};
200
201static int __init oakscsi_init(void)
202{
203 return ecard_register_driver(&oakscsi_driver);
204}
205
206static void __exit oakscsi_exit(void)
207{
208 ecard_remove_driver(&oakscsi_driver);
209}
210
211module_init(oakscsi_init);
212module_exit(oakscsi_exit);
213
214MODULE_AUTHOR("Russell King");
215MODULE_DESCRIPTION("Oak SCSI driver");
216MODULE_LICENSE("GPL");
217
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
new file mode 100644
index 000000000000..54f23be6460f
--- /dev/null
+++ b/drivers/scsi/arm/powertec.c
@@ -0,0 +1,472 @@
1/*
2 * linux/drivers/acorn/scsi/powertec.c
3 *
4 * Copyright (C) 1997-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/module.h>
11#include <linux/blkdev.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/ioport.h>
15#include <linux/sched.h>
16#include <linux/proc_fs.h>
17#include <linux/delay.h>
18#include <linux/interrupt.h>
19#include <linux/init.h>
20#include <linux/dma-mapping.h>
21
22#include <asm/dma.h>
23#include <asm/ecard.h>
24#include <asm/io.h>
25#include <asm/irq.h>
26#include <asm/pgtable.h>
27
28#include "../scsi.h"
29#include <scsi/scsi_host.h>
30#include "fas216.h"
31#include "scsi.h"
32
33#include <scsi/scsicam.h>
34
35#define POWERTEC_FAS216_OFFSET 0x3000
36#define POWERTEC_FAS216_SHIFT 6
37
38#define POWERTEC_INTR_STATUS 0x2000
39#define POWERTEC_INTR_BIT 0x80
40
41#define POWERTEC_RESET_CONTROL 0x1018
42#define POWERTEC_RESET_BIT 1
43
44#define POWERTEC_TERM_CONTROL 0x2018
45#define POWERTEC_TERM_ENABLE 1
46
47#define POWERTEC_INTR_CONTROL 0x101c
48#define POWERTEC_INTR_ENABLE 1
49#define POWERTEC_INTR_DISABLE 0
50
51#define VERSION "1.10 (19/01/2003 2.5.59)"
52
53/*
54 * Use term=0,1,0,0,0 to turn terminators on/off.
55 * One entry per slot.
56 */
57static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
58
59#define NR_SG 256
60
61struct powertec_info {
62 FAS216_Info info;
63 struct expansion_card *ec;
64 void __iomem *base;
65 unsigned int term_ctl;
66 struct scatterlist sg[NR_SG];
67};
68
69/* Prototype: void powertecscsi_irqenable(ec, irqnr)
70 * Purpose : Enable interrupts on Powertec SCSI card
71 * Params : ec - expansion card structure
72 * : irqnr - interrupt number
73 */
74static void
75powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
76{
77 struct powertec_info *info = ec->irq_data;
78 writeb(POWERTEC_INTR_ENABLE, info->base + POWERTEC_INTR_CONTROL);
79}
80
81/* Prototype: void powertecscsi_irqdisable(ec, irqnr)
82 * Purpose : Disable interrupts on Powertec SCSI card
83 * Params : ec - expansion card structure
84 * : irqnr - interrupt number
85 */
86static void
87powertecscsi_irqdisable(struct expansion_card *ec, int irqnr)
88{
89 struct powertec_info *info = ec->irq_data;
90 writeb(POWERTEC_INTR_DISABLE, info->base + POWERTEC_INTR_CONTROL);
91}
92
93static const expansioncard_ops_t powertecscsi_ops = {
94 .irqenable = powertecscsi_irqenable,
95 .irqdisable = powertecscsi_irqdisable,
96};
97
98/* Prototype: void powertecscsi_terminator_ctl(host, on_off)
99 * Purpose : Turn the Powertec SCSI terminators on or off
100 * Params : host - card to turn on/off
101 * : on_off - !0 to turn on, 0 to turn off
102 */
103static void
104powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
105{
106 struct powertec_info *info = (struct powertec_info *)host->hostdata;
107
108 info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0;
109 writeb(info->term_ctl, info->base + POWERTEC_TERM_CONTROL);
110}
111
112/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
113 * Purpose : handle interrupts from Powertec SCSI card
114 * Params : irq - interrupt number
115 * dev_id - user-defined (Scsi_Host structure)
116 * regs - processor registers at interrupt
117 */
118static irqreturn_t
119powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
120{
121 struct powertec_info *info = dev_id;
122
123 return fas216_intr(&info->info);
124}
125
126/* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type)
127 * Purpose : initialises DMA/PIO
128 * Params : host - host
129 * SCpnt - command
130 * direction - DMA on to/off of card
131 * min_type - minimum DMA support that we must have for this transfer
132 * Returns : type of transfer to be performed
133 */
134static fasdmatype_t
135powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
136 fasdmadir_t direction, fasdmatype_t min_type)
137{
138 struct powertec_info *info = (struct powertec_info *)host->hostdata;
139 struct device *dev = scsi_get_device(host);
140 int dmach = info->info.scsi.dma;
141
142 if (info->info.ifcfg.capabilities & FASCAP_DMA &&
143 min_type == fasdma_real_all) {
144 int bufs, map_dir, dma_dir;
145
146 bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
147
148 if (direction == DMA_OUT)
149 map_dir = DMA_TO_DEVICE,
150 dma_dir = DMA_MODE_WRITE;
151 else
152 map_dir = DMA_FROM_DEVICE,
153 dma_dir = DMA_MODE_READ;
154
155 dma_map_sg(dev, info->sg, bufs + 1, map_dir);
156
157 disable_dma(dmach);
158 set_dma_sg(dmach, info->sg, bufs + 1);
159 set_dma_mode(dmach, dma_dir);
160 enable_dma(dmach);
161 return fasdma_real_all;
162 }
163
164 /*
165 * If we're not doing DMA,
166 * we'll do slow PIO
167 */
168 return fasdma_pio;
169}
170
171/* Prototype: int powertecscsi_dma_stop(host, SCpnt)
172 * Purpose : stops DMA/PIO
173 * Params : host - host
174 * SCpnt - command
175 */
176static void
177powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
178{
179 struct powertec_info *info = (struct powertec_info *)host->hostdata;
180 if (info->info.scsi.dma != NO_DMA)
181 disable_dma(info->info.scsi.dma);
182}
183
184/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
185 * Purpose : returns a descriptive string about this interface,
186 * Params : host - driver host structure to return info for.
187 * Returns : pointer to a static buffer containing null terminated string.
188 */
189const char *powertecscsi_info(struct Scsi_Host *host)
190{
191 struct powertec_info *info = (struct powertec_info *)host->hostdata;
192 static char string[150];
193
194 sprintf(string, "%s (%s) in slot %d v%s terminators o%s",
195 host->hostt->name, info->info.scsi.type, info->ec->slot_no,
196 VERSION, info->term_ctl ? "n" : "ff");
197
198 return string;
199}
200
201/* Prototype: int powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
202 * Purpose : Set a driver specific function
203 * Params : host - host to setup
204 * : buffer - buffer containing string describing operation
205 * : length - length of string
206 * Returns : -EINVAL, or 0
207 */
208static int
209powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
210{
211 int ret = length;
212
213 if (length >= 12 && strncmp(buffer, "POWERTECSCSI", 12) == 0) {
214 buffer += 12;
215 length -= 12;
216
217 if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
218 if (buffer[5] == '1')
219 powertecscsi_terminator_ctl(host, 1);
220 else if (buffer[5] == '0')
221 powertecscsi_terminator_ctl(host, 0);
222 else
223 ret = -EINVAL;
224 } else
225 ret = -EINVAL;
226 } else
227 ret = -EINVAL;
228
229 return ret;
230}
231
232/* Prototype: int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
233 * int length, int host_no, int inout)
234 * Purpose : Return information about the driver to a user process accessing
235 * the /proc filesystem.
236 * Params : buffer - a buffer to write information to
237 * start - a pointer into this buffer set by this routine to the start
238 * of the required information.
239 * offset - offset into information that we have read upto.
240 * length - length of buffer
241 * inout - 0 for reading, 1 for writing.
242 * Returns : length of data written to buffer.
243 */
244int powertecscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
245 int length, int inout)
246{
247 struct powertec_info *info;
248 char *p = buffer;
249 int pos;
250
251 if (inout == 1)
252 return powertecscsi_set_proc_info(host, buffer, length);
253
254 info = (struct powertec_info *)host->hostdata;
255
256 p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION);
257 p += fas216_print_host(&info->info, p);
258 p += sprintf(p, "Term : o%s\n",
259 info->term_ctl ? "n" : "ff");
260
261 p += fas216_print_stats(&info->info, p);
262 p += fas216_print_devices(&info->info, p);
263
264 *start = buffer + offset;
265 pos = p - buffer - offset;
266 if (pos > length)
267 pos = length;
268
269 return pos;
270}
271
272static ssize_t powertecscsi_show_term(struct device *dev, char *buf)
273{
274 struct expansion_card *ec = ECARD_DEV(dev);
275 struct Scsi_Host *host = ecard_get_drvdata(ec);
276 struct powertec_info *info = (struct powertec_info *)host->hostdata;
277
278 return sprintf(buf, "%d\n", info->term_ctl ? 1 : 0);
279}
280
281static ssize_t
282powertecscsi_store_term(struct device *dev, const char *buf, size_t len)
283{
284 struct expansion_card *ec = ECARD_DEV(dev);
285 struct Scsi_Host *host = ecard_get_drvdata(ec);
286
287 if (len > 1)
288 powertecscsi_terminator_ctl(host, buf[0] != '0');
289
290 return len;
291}
292
293static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
294 powertecscsi_show_term, powertecscsi_store_term);
295
296static Scsi_Host_Template powertecscsi_template = {
297 .module = THIS_MODULE,
298 .proc_info = powertecscsi_proc_info,
299 .name = "PowerTec SCSI",
300 .info = powertecscsi_info,
301 .queuecommand = fas216_queue_command,
302 .eh_host_reset_handler = fas216_eh_host_reset,
303 .eh_bus_reset_handler = fas216_eh_bus_reset,
304 .eh_device_reset_handler = fas216_eh_device_reset,
305 .eh_abort_handler = fas216_eh_abort,
306
307 .can_queue = 8,
308 .this_id = 7,
309 .sg_tablesize = SG_ALL,
310 .cmd_per_lun = 2,
311 .use_clustering = ENABLE_CLUSTERING,
312 .proc_name = "powertec",
313};
314
315static int __devinit
316powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
317{
318 struct Scsi_Host *host;
319 struct powertec_info *info;
320 unsigned long resbase, reslen;
321 void __iomem *base;
322 int ret;
323
324 ret = ecard_request_resources(ec);
325 if (ret)
326 goto out;
327
328 resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
329 reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
330 base = ioremap(resbase, reslen);
331 if (!base) {
332 ret = -ENOMEM;
333 goto out_region;
334 }
335
336 host = scsi_host_alloc(&powertecscsi_template,
337 sizeof (struct powertec_info));
338 if (!host) {
339 ret = -ENOMEM;
340 goto out_unmap;
341 }
342
343 ecard_set_drvdata(ec, host);
344
345 info = (struct powertec_info *)host->hostdata;
346 info->base = base;
347 powertecscsi_terminator_ctl(host, term[ec->slot_no]);
348
349 info->info.scsi.io_base = base + POWERTEC_FAS216_OFFSET;
350 info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT;
351 info->info.scsi.irq = ec->irq;
352 info->info.scsi.dma = ec->dma;
353 info->info.ifcfg.clockrate = 40; /* MHz */
354 info->info.ifcfg.select_timeout = 255;
355 info->info.ifcfg.asyncperiod = 200; /* ns */
356 info->info.ifcfg.sync_max_depth = 7;
357 info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
358 info->info.ifcfg.disconnect_ok = 1;
359 info->info.ifcfg.wide_max_size = 0;
360 info->info.ifcfg.capabilities = 0;
361 info->info.dma.setup = powertecscsi_dma_setup;
362 info->info.dma.pseudo = NULL;
363 info->info.dma.stop = powertecscsi_dma_stop;
364
365 ec->irqaddr = base + POWERTEC_INTR_STATUS;
366 ec->irqmask = POWERTEC_INTR_BIT;
367 ec->irq_data = info;
368 ec->ops = &powertecscsi_ops;
369
370 device_create_file(&ec->dev, &dev_attr_bus_term);
371
372 ret = fas216_init(host);
373 if (ret)
374 goto out_free;
375
376 ret = request_irq(ec->irq, powertecscsi_intr,
377 SA_INTERRUPT, "powertec", info);
378 if (ret) {
379 printk("scsi%d: IRQ%d not free: %d\n",
380 host->host_no, ec->irq, ret);
381 goto out_release;
382 }
383
384 if (info->info.scsi.dma != NO_DMA) {
385 if (request_dma(info->info.scsi.dma, "powertec")) {
386 printk("scsi%d: DMA%d not free, using PIO\n",
387 host->host_no, info->info.scsi.dma);
388 info->info.scsi.dma = NO_DMA;
389 } else {
390 set_dma_speed(info->info.scsi.dma, 180);
391 info->info.ifcfg.capabilities |= FASCAP_DMA;
392 }
393 }
394
395 ret = fas216_add(host, &ec->dev);
396 if (ret == 0)
397 goto out;
398
399 if (info->info.scsi.dma != NO_DMA)
400 free_dma(info->info.scsi.dma);
401 free_irq(ec->irq, host);
402
403 out_release:
404 fas216_release(host);
405
406 out_free:
407 device_remove_file(&ec->dev, &dev_attr_bus_term);
408 scsi_host_put(host);
409
410 out_unmap:
411 iounmap(base);
412
413 out_region:
414 ecard_release_resources(ec);
415
416 out:
417 return ret;
418}
419
420static void __devexit powertecscsi_remove(struct expansion_card *ec)
421{
422 struct Scsi_Host *host = ecard_get_drvdata(ec);
423 struct powertec_info *info = (struct powertec_info *)host->hostdata;
424
425 ecard_set_drvdata(ec, NULL);
426 fas216_remove(host);
427
428 device_remove_file(&ec->dev, &dev_attr_bus_term);
429
430 if (info->info.scsi.dma != NO_DMA)
431 free_dma(info->info.scsi.dma);
432 free_irq(ec->irq, info);
433
434 iounmap(info->base);
435
436 fas216_release(host);
437 scsi_host_put(host);
438 ecard_release_resources(ec);
439}
440
441static const struct ecard_id powertecscsi_cids[] = {
442 { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI },
443 { 0xffff, 0xffff },
444};
445
446static struct ecard_driver powertecscsi_driver = {
447 .probe = powertecscsi_probe,
448 .remove = __devexit_p(powertecscsi_remove),
449 .id_table = powertecscsi_cids,
450 .drv = {
451 .name = "powertecscsi",
452 },
453};
454
455static int __init powertecscsi_init(void)
456{
457 return ecard_register_driver(&powertecscsi_driver);
458}
459
460static void __exit powertecscsi_exit(void)
461{
462 ecard_remove_driver(&powertecscsi_driver);
463}
464
465module_init(powertecscsi_init);
466module_exit(powertecscsi_exit);
467
468MODULE_AUTHOR("Russell King");
469MODULE_DESCRIPTION("Powertec SCSI driver");
470MODULE_PARM(term, "1-8i");
471MODULE_PARM_DESC(term, "SCSI bus termination");
472MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
new file mode 100644
index 000000000000..e6d159270d29
--- /dev/null
+++ b/drivers/scsi/arm/queue.c
@@ -0,0 +1,319 @@
1/*
2 * linux/drivers/acorn/scsi/queue.c: queue handling primitives
3 *
4 * Copyright (C) 1997-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Changelog:
11 * 15-Sep-1997 RMK Created.
12 * 11-Oct-1997 RMK Corrected problem with queue_remove_exclude
13 * not updating internal linked list properly
14 * (was causing commands to go missing).
15 * 30-Aug-2000 RMK Use Linux list handling and spinlocks
16 */
17#include <linux/module.h>
18#include <linux/blkdev.h>
19#include <linux/kernel.h>
20#include <linux/string.h>
21#include <linux/slab.h>
22#include <linux/spinlock.h>
23#include <linux/list.h>
24#include <linux/init.h>
25
26#include "../scsi.h"
27
28#define DEBUG
29
30typedef struct queue_entry {
31 struct list_head list;
32 Scsi_Cmnd *SCpnt;
33#ifdef DEBUG
34 unsigned long magic;
35#endif
36} QE_t;
37
38#ifdef DEBUG
39#define QUEUE_MAGIC_FREE 0xf7e1c9a3
40#define QUEUE_MAGIC_USED 0xf7e1cc33
41
42#define SET_MAGIC(q,m) ((q)->magic = (m))
43#define BAD_MAGIC(q,m) ((q)->magic != (m))
44#else
45#define SET_MAGIC(q,m) do { } while (0)
46#define BAD_MAGIC(q,m) (0)
47#endif
48
49#include "queue.h"
50
51#define NR_QE 32
52
53/*
54 * Function: void queue_initialise (Queue_t *queue)
55 * Purpose : initialise a queue
56 * Params : queue - queue to initialise
57 */
58int queue_initialise (Queue_t *queue)
59{
60 unsigned int nqueues = NR_QE;
61 QE_t *q;
62
63 spin_lock_init(&queue->queue_lock);
64 INIT_LIST_HEAD(&queue->head);
65 INIT_LIST_HEAD(&queue->free);
66
67 /*
68 * If life was easier, then SCpnt would have a
69 * host-available list head, and we wouldn't
70 * need to keep free lists or allocate this
71 * memory.
72 */
73 queue->alloc = q = kmalloc(sizeof(QE_t) * nqueues, GFP_KERNEL);
74 if (q) {
75 for (; nqueues; q++, nqueues--) {
76 SET_MAGIC(q, QUEUE_MAGIC_FREE);
77 q->SCpnt = NULL;
78 list_add(&q->list, &queue->free);
79 }
80 }
81
82 return queue->alloc != NULL;
83}
84
85/*
86 * Function: void queue_free (Queue_t *queue)
87 * Purpose : free a queue
88 * Params : queue - queue to free
89 */
90void queue_free (Queue_t *queue)
91{
92 if (!list_empty(&queue->head))
93 printk(KERN_WARNING "freeing non-empty queue %p\n", queue);
94 if (queue->alloc)
95 kfree(queue->alloc);
96}
97
98
99/*
100 * Function: int queue_add_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
101 * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head.
102 * Params : queue - destination queue
103 * SCpnt - command to add
104 * head - add command to head of queue
105 * Returns : 0 on error, !0 on success
106 */
107int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
108{
109 unsigned long flags;
110 struct list_head *l;
111 QE_t *q;
112 int ret = 0;
113
114 spin_lock_irqsave(&queue->queue_lock, flags);
115 if (list_empty(&queue->free))
116 goto empty;
117
118 l = queue->free.next;
119 list_del(l);
120
121 q = list_entry(l, QE_t, list);
122 if (BAD_MAGIC(q, QUEUE_MAGIC_FREE))
123 BUG();
124
125 SET_MAGIC(q, QUEUE_MAGIC_USED);
126 q->SCpnt = SCpnt;
127
128 if (head)
129 list_add(l, &queue->head);
130 else
131 list_add_tail(l, &queue->head);
132
133 ret = 1;
134empty:
135 spin_unlock_irqrestore(&queue->queue_lock, flags);
136 return ret;
137}
138
139static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent)
140{
141 QE_t *q;
142
143 /*
144 * Move the entry from the "used" list onto the "free" list
145 */
146 list_del(ent);
147 q = list_entry(ent, QE_t, list);
148 if (BAD_MAGIC(q, QUEUE_MAGIC_USED))
149 BUG();
150
151 SET_MAGIC(q, QUEUE_MAGIC_FREE);
152 list_add(ent, &queue->free);
153
154 return q->SCpnt;
155}
156
157/*
158 * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude)
159 * Purpose : remove a SCSI command from a queue
160 * Params : queue - queue to remove command from
161 * exclude - bit array of target&lun which is busy
162 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
163 */
164Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
165{
166 unsigned long flags;
167 struct list_head *l;
168 Scsi_Cmnd *SCpnt = NULL;
169
170 spin_lock_irqsave(&queue->queue_lock, flags);
171 list_for_each(l, &queue->head) {
172 QE_t *q = list_entry(l, QE_t, list);
173 if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) {
174 SCpnt = __queue_remove(queue, l);
175 break;
176 }
177 }
178 spin_unlock_irqrestore(&queue->queue_lock, flags);
179
180 return SCpnt;
181}
182
183/*
184 * Function: Scsi_Cmnd *queue_remove (queue)
185 * Purpose : removes first SCSI command from a queue
186 * Params : queue - queue to remove command from
187 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
188 */
189Scsi_Cmnd *queue_remove(Queue_t *queue)
190{
191 unsigned long flags;
192 Scsi_Cmnd *SCpnt = NULL;
193
194 spin_lock_irqsave(&queue->queue_lock, flags);
195 if (!list_empty(&queue->head))
196 SCpnt = __queue_remove(queue, queue->head.next);
197 spin_unlock_irqrestore(&queue->queue_lock, flags);
198
199 return SCpnt;
200}
201
202/*
203 * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
204 * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
205 * Params : queue - queue to remove command from
206 * target - target that we want
207 * lun - lun on device
208 * tag - tag on device
209 * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
210 */
211Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag)
212{
213 unsigned long flags;
214 struct list_head *l;
215 Scsi_Cmnd *SCpnt = NULL;
216
217 spin_lock_irqsave(&queue->queue_lock, flags);
218 list_for_each(l, &queue->head) {
219 QE_t *q = list_entry(l, QE_t, list);
220 if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun &&
221 q->SCpnt->tag == tag) {
222 SCpnt = __queue_remove(queue, l);
223 break;
224 }
225 }
226 spin_unlock_irqrestore(&queue->queue_lock, flags);
227
228 return SCpnt;
229}
230
231/*
232 * Function: queue_remove_all_target(queue, target)
233 * Purpose : remove all SCSI commands from the queue for a specified target
234 * Params : queue - queue to remove command from
235 * target - target device id
236 * Returns : nothing
237 */
238void queue_remove_all_target(Queue_t *queue, int target)
239{
240 unsigned long flags;
241 struct list_head *l;
242
243 spin_lock_irqsave(&queue->queue_lock, flags);
244 list_for_each(l, &queue->head) {
245 QE_t *q = list_entry(l, QE_t, list);
246 if (q->SCpnt->device->id == target)
247 __queue_remove(queue, l);
248 }
249 spin_unlock_irqrestore(&queue->queue_lock, flags);
250}
251
252/*
253 * Function: int queue_probetgtlun (queue, target, lun)
254 * Purpose : check to see if we have a command in the queue for the specified
255 * target/lun.
256 * Params : queue - queue to look in
257 * target - target we want to probe
258 * lun - lun on target
259 * Returns : 0 if not found, != 0 if found
260 */
261int queue_probetgtlun (Queue_t *queue, int target, int lun)
262{
263 unsigned long flags;
264 struct list_head *l;
265 int found = 0;
266
267 spin_lock_irqsave(&queue->queue_lock, flags);
268 list_for_each(l, &queue->head) {
269 QE_t *q = list_entry(l, QE_t, list);
270 if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun) {
271 found = 1;
272 break;
273 }
274 }
275 spin_unlock_irqrestore(&queue->queue_lock, flags);
276
277 return found;
278}
279
280/*
281 * Function: int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt)
282 * Purpose : remove a specific command from the queues
283 * Params : queue - queue to look in
284 * SCpnt - command to find
285 * Returns : 0 if not found
286 */
287int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt)
288{
289 unsigned long flags;
290 struct list_head *l;
291 int found = 0;
292
293 spin_lock_irqsave(&queue->queue_lock, flags);
294 list_for_each(l, &queue->head) {
295 QE_t *q = list_entry(l, QE_t, list);
296 if (q->SCpnt == SCpnt) {
297 __queue_remove(queue, l);
298 found = 1;
299 break;
300 }
301 }
302 spin_unlock_irqrestore(&queue->queue_lock, flags);
303
304 return found;
305}
306
307EXPORT_SYMBOL(queue_initialise);
308EXPORT_SYMBOL(queue_free);
309EXPORT_SYMBOL(__queue_add);
310EXPORT_SYMBOL(queue_remove);
311EXPORT_SYMBOL(queue_remove_exclude);
312EXPORT_SYMBOL(queue_remove_tgtluntag);
313EXPORT_SYMBOL(queue_remove_cmd);
314EXPORT_SYMBOL(queue_remove_all_target);
315EXPORT_SYMBOL(queue_probetgtlun);
316
317MODULE_AUTHOR("Russell King");
318MODULE_DESCRIPTION("SCSI command queueing");
319MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/queue.h b/drivers/scsi/arm/queue.h
new file mode 100644
index 000000000000..0c9dec4c1716
--- /dev/null
+++ b/drivers/scsi/arm/queue.h
@@ -0,0 +1,105 @@
1/*
2 * linux/drivers/acorn/scsi/queue.h: queue handling
3 *
4 * Copyright (C) 1997 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef QUEUE_H
11#define QUEUE_H
12
13typedef struct {
14 struct list_head head;
15 struct list_head free;
16 spinlock_t queue_lock;
17 void *alloc; /* start of allocated mem */
18} Queue_t;
19
20/*
21 * Function: void queue_initialise (Queue_t *queue)
22 * Purpose : initialise a queue
23 * Params : queue - queue to initialise
24 */
25extern int queue_initialise (Queue_t *queue);
26
27/*
28 * Function: void queue_free (Queue_t *queue)
29 * Purpose : free a queue
30 * Params : queue - queue to free
31 */
32extern void queue_free (Queue_t *queue);
33
34/*
35 * Function: Scsi_Cmnd *queue_remove (queue)
36 * Purpose : removes first SCSI command from a queue
37 * Params : queue - queue to remove command from
38 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
39 */
40extern Scsi_Cmnd *queue_remove (Queue_t *queue);
41
42/*
43 * Function: Scsi_Cmnd *queue_remove_exclude_ref (queue, exclude)
44 * Purpose : remove a SCSI command from a queue
45 * Params : queue - queue to remove command from
46 * exclude - array of busy LUNs
47 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
48 */
49extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned long *exclude);
50
51#define queue_add_cmd_ordered(queue,SCpnt) \
52 __queue_add(queue,SCpnt,(SCpnt)->cmnd[0] == REQUEST_SENSE)
53#define queue_add_cmd_tail(queue,SCpnt) \
54 __queue_add(queue,SCpnt,0)
55/*
56 * Function: int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head)
57 * Purpose : Add a new command onto a queue
58 * Params : queue - destination queue
59 * SCpnt - command to add
60 * head - add command to head of queue
61 * Returns : 0 on error, !0 on success
62 */
63extern int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head);
64
65/*
66 * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
67 * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
68 * Params : queue - queue to remove command from
69 * target - target that we want
70 * lun - lun on device
71 * tag - tag on device
72 * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
73 */
74extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag);
75
76/*
77 * Function: queue_remove_all_target(queue, target)
78 * Purpose : remove all SCSI commands from the queue for a specified target
79 * Params : queue - queue to remove command from
80 * target - target device id
81 * Returns : nothing
82 */
83extern void queue_remove_all_target(Queue_t *queue, int target);
84
85/*
86 * Function: int queue_probetgtlun (queue, target, lun)
87 * Purpose : check to see if we have a command in the queue for the specified
88 * target/lun.
89 * Params : queue - queue to look in
90 * target - target we want to probe
91 * lun - lun on target
92 * Returns : 0 if not found, != 0 if found
93 */
94extern int queue_probetgtlun (Queue_t *queue, int target, int lun);
95
96/*
97 * Function: int queue_remove_cmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
98 * Purpose : remove a specific command from the queues
99 * Params : queue - queue to look in
100 * SCpnt - command to find
101 * Returns : 0 if not found
102 */
103int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt);
104
105#endif /* QUEUE_H */
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
new file mode 100644
index 000000000000..2f1b3f4bf954
--- /dev/null
+++ b/drivers/scsi/arm/scsi.h
@@ -0,0 +1,115 @@
1/*
2 * linux/drivers/acorn/scsi/scsi.h
3 *
4 * Copyright (C) 2002 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Commonly used scsi driver functions.
11 */
12
13#define BELT_AND_BRACES
14
15/*
16 * The scatter-gather list handling. This contains all
17 * the yucky stuff that needs to be fixed properly.
18 */
19static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int max)
20{
21 int bufs = SCp->buffers_residual;
22
23 BUG_ON(bufs + 1 > max);
24
25 sg->page = virt_to_page(SCp->ptr);
26 sg->offset = offset_in_page(SCp->ptr);
27 sg->length = SCp->this_residual;
28
29 if (bufs)
30 memcpy(sg + 1, SCp->buffer + 1,
31 sizeof(struct scatterlist) * bufs);
32 return bufs + 1;
33}
34
35static inline int next_SCp(Scsi_Pointer *SCp)
36{
37 int ret = SCp->buffers_residual;
38 if (ret) {
39 SCp->buffer++;
40 SCp->buffers_residual--;
41 SCp->ptr = (char *)
42 (page_address(SCp->buffer->page) +
43 SCp->buffer->offset);
44 SCp->this_residual = SCp->buffer->length;
45 } else {
46 SCp->ptr = NULL;
47 SCp->this_residual = 0;
48 }
49 return ret;
50}
51
52static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
53{
54 char c = *SCp->ptr;
55
56 SCp->ptr += 1;
57 SCp->this_residual -= 1;
58
59 return c;
60}
61
62static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c)
63{
64 *SCp->ptr = c;
65 SCp->ptr += 1;
66 SCp->this_residual -= 1;
67}
68
69static inline void init_SCp(Scsi_Cmnd *SCpnt)
70{
71 memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer));
72
73 if (SCpnt->use_sg) {
74 unsigned long len = 0;
75 int buf;
76
77 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
78 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
79 SCpnt->SCp.ptr = (char *)
80 (page_address(SCpnt->SCp.buffer->page) +
81 SCpnt->SCp.buffer->offset);
82 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
83
84#ifdef BELT_AND_BRACES
85 /*
86 * Calculate correct buffer length. Some commands
87 * come in with the wrong request_bufflen.
88 */
89 for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
90 len += SCpnt->SCp.buffer[buf].length;
91
92 if (SCpnt->request_bufflen != len)
93 printk(KERN_WARNING "scsi%d.%c: bad request buffer "
94 "length %d, should be %ld\n", SCpnt->device->host->host_no,
95 '0' + SCpnt->device->id, SCpnt->request_bufflen, len);
96 SCpnt->request_bufflen = len;
97#endif
98 } else {
99 SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
100 SCpnt->SCp.this_residual = SCpnt->request_bufflen;
101 }
102
103 /*
104 * If the upper SCSI layers pass a buffer, but zero length,
105 * we aren't interested in the buffer pointer.
106 */
107 if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {
108#if 0 //def BELT_AND_BRACES
109 printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "
110 "command ", SCpnt->host->host_no, '0' + SCpnt->target);
111 print_command(SCpnt->cmnd);
112#endif
113 SCpnt->SCp.ptr = NULL;
114 }
115}