blob: 88c649b3ef6141d0ea07dbc13c1174a3338cac77 [file] [log] [blame]
Thomas Gleixner3e0a4e82019-05-23 11:14:55 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* aha152x.c -- Adaptec AHA-152x driver
Jan Engelhardt96de0e22007-10-19 23:21:04 +02003 * Author: Jürgen E. Fischer, fischer@norbit.de
4 * Copyright 1993-2004 Jürgen E. Fischer
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * $Id: aha152x.c,v 2.7 2004/01/24 11:42:59 fischer Exp $
7 *
8 * $Log: aha152x.c,v $
9 * Revision 2.7 2004/01/24 11:42:59 fischer
10 * - gather code that is not used by PCMCIA at the end
11 * - move request_region for !PCMCIA case to detection
12 * - migration to new scsi host api (remove legacy code)
13 * - free host scribble before scsi_done
14 * - fix error handling
15 * - one isapnp device added to id_table
16 *
17 * Revision 2.6 2003/10/30 20:52:47 fischer
18 * - interfaces changes for kernel 2.6
19 * - aha152x_probe_one introduced for pcmcia stub
20 * - fixed pnpdev handling
21 * - instead of allocation a new one, reuse command for request sense after check condition and reset
22 * - fixes race in is_complete
23 *
24 * Revision 2.5 2002/04/14 11:24:53 fischer
25 * - isapnp support
26 * - abort fixed
27 * - 2.5 support
28 *
29 * Revision 2.4 2000/12/16 12:53:56 fischer
30 * - allow REQUEST SENSE to be queued
31 * - handle shared PCI interrupts
32 *
33 * Revision 2.3 2000/11/04 16:40:26 fischer
34 * - handle data overruns
35 * - extend timeout for data phases
36 *
37 * Revision 2.2 2000/08/08 19:54:53 fischer
38 * - minor changes
39 *
40 * Revision 2.1 2000/05/17 16:23:17 fischer
41 * - signature update
42 * - fix for data out w/o scatter gather
43 *
44 * Revision 2.0 1999/12/25 15:07:32 fischer
45 * - interrupt routine completly reworked
46 * - basic support for new eh code
47 *
48 * Revision 1.21 1999/11/10 23:46:36 fischer
49 * - default to synchronous operation
50 * - synchronous negotiation fixed
51 * - added timeout to loops
52 * - debugging output can be controlled through procfs
53 *
54 * Revision 1.20 1999/11/07 18:37:31 fischer
55 * - synchronous operation works
56 * - resid support for sg driver
57 *
58 * Revision 1.19 1999/11/02 22:39:59 fischer
59 * - moved leading comments to README.aha152x
60 * - new additional module parameters
61 * - updates for 2.3
62 * - support for the Tripace TC1550 controller
63 * - interrupt handling changed
64 *
65 * Revision 1.18 1996/09/07 20:10:40 fischer
66 * - fixed can_queue handling (multiple outstanding commands working again)
67 *
68 * Revision 1.17 1996/08/17 16:05:14 fischer
69 * - biosparam improved
70 * - interrupt verification
71 * - updated documentation
72 * - cleanups
73 *
74 * Revision 1.16 1996/06/09 00:04:56 root
75 * - added configuration symbols for insmod (aha152x/aha152x1)
76 *
77 * Revision 1.15 1996/04/30 14:52:06 fischer
78 * - proc info fixed
79 * - support for extended translation for >1GB disks
80 *
81 * Revision 1.14 1996/01/17 15:11:20 fischer
82 * - fixed lockup in MESSAGE IN phase after reconnection
83 *
84 * Revision 1.13 1996/01/09 02:15:53 fischer
85 * - some cleanups
86 * - moved request_irq behind controller initialization
87 * (to avoid spurious interrupts)
88 *
89 * Revision 1.12 1995/12/16 12:26:07 fischer
90 * - barrier()s added
91 * - configurable RESET delay added
92 *
93 * Revision 1.11 1995/12/06 21:18:35 fischer
94 * - some minor updates
95 *
96 * Revision 1.10 1995/07/22 19:18:45 fischer
97 * - support for 2 controllers
98 * - started synchronous data transfers (not working yet)
99 *
100 * Revision 1.9 1995/03/18 09:20:24 root
101 * - patches for PCMCIA and modules
102 *
103 * Revision 1.8 1995/01/21 22:07:19 root
104 * - snarf_region => request_region
105 * - aha152x_intr interface change
106 *
107 * Revision 1.7 1995/01/02 23:19:36 root
108 * - updated COMMAND_SIZE to cmd_len
109 * - changed sti() to restore_flags()
110 * - fixed some #ifdef which generated warnings
111 *
112 * Revision 1.6 1994/11/24 20:35:27 root
113 * - problem with odd number of bytes in fifo fixed
114 *
115 * Revision 1.5 1994/10/30 14:39:56 root
116 * - abort code fixed
117 * - debugging improved
118 *
119 * Revision 1.4 1994/09/12 11:33:01 root
120 * - irqaction to request_irq
121 * - abortion updated
122 *
123 * Revision 1.3 1994/08/04 13:53:05 root
124 * - updates for mid-level-driver changes
125 * - accept unexpected BUSFREE phase as error condition
126 * - parity check now configurable
127 *
128 * Revision 1.2 1994/07/03 12:56:36 root
129 * - cleaned up debugging code
130 * - more tweaking on reset delays
131 * - updated abort/reset code (pretty untested...)
132 *
133 * Revision 1.1 1994/05/28 21:18:49 root
134 * - update for mid-level interface change (abort-reset)
135 * - delays after resets adjusted for some slow devices
136 *
137 * Revision 1.0 1994/03/25 12:52:00 root
138 * - Fixed "more data than expected" problem
139 * - added new BIOS signatures
140 *
141 * Revision 0.102 1994/01/31 20:44:12 root
142 * - minor changes in insw/outsw handling
143 *
144 * Revision 0.101 1993/12/13 01:16:27 root
145 * - fixed STATUS phase (non-GOOD stati were dropped sometimes;
146 * fixes problems with CD-ROM sector size detection & media change)
147 *
148 * Revision 0.100 1993/12/10 16:58:47 root
149 * - fix for unsuccessful selections in case of non-continuous id assignments
150 * on the scsi bus.
151 *
152 * Revision 0.99 1993/10/24 16:19:59 root
153 * - fixed DATA IN (rare read errors gone)
154 *
155 * Revision 0.98 1993/10/17 12:54:44 root
156 * - fixed some recent fixes (shame on me)
157 * - moved initialization of scratch area to aha152x_queue
158 *
159 * Revision 0.97 1993/10/09 18:53:53 root
160 * - DATA IN fixed. Rarely left data in the fifo.
161 *
162 * Revision 0.96 1993/10/03 00:53:59 root
163 * - minor changes on DATA IN
164 *
165 * Revision 0.95 1993/09/24 10:36:01 root
166 * - change handling of MSGI after reselection
167 * - fixed sti/cli
168 * - minor changes
169 *
170 * Revision 0.94 1993/09/18 14:08:22 root
171 * - fixed bug in multiple outstanding command code
172 * - changed detection
173 * - support for kernel command line configuration
174 * - reset corrected
175 * - changed message handling
176 *
177 * Revision 0.93 1993/09/15 20:41:19 root
178 * - fixed bugs with multiple outstanding commands
179 *
180 * Revision 0.92 1993/09/13 02:46:33 root
181 * - multiple outstanding commands work (no problems with IBM drive)
182 *
183 * Revision 0.91 1993/09/12 20:51:46 root
184 * added multiple outstanding commands
185 * (some problem with this $%&? IBM device remain)
186 *
187 * Revision 0.9 1993/09/12 11:11:22 root
188 * - corrected auto-configuration
189 * - changed the auto-configuration (added some '#define's)
190 * - added support for dis-/reconnection
191 *
192 * Revision 0.8 1993/09/06 23:09:39 root
193 * - added support for the drive activity light
194 * - minor changes
195 *
196 * Revision 0.7 1993/09/05 14:30:15 root
197 * - improved phase detection
198 * - now using the new snarf_region code of 0.99pl13
199 *
200 * Revision 0.6 1993/09/02 11:01:38 root
201 * first public release; added some signatures and biosparam()
202 *
203 * Revision 0.5 1993/08/30 10:23:30 root
204 * fixed timing problems with my IBM drive
205 *
206 * Revision 0.4 1993/08/29 14:06:52 root
207 * fixed some problems with timeouts due incomplete commands
208 *
209 * Revision 0.3 1993/08/28 15:55:03 root
210 * writing data works too. mounted and worked on a dos partition
211 *
212 * Revision 0.2 1993/08/27 22:42:07 root
213 * reading data works. Mounted a msdos partition.
214 *
215 * Revision 0.1 1993/08/25 13:38:30 root
216 * first "damn thing doesn't work" version
217 *
218 * Revision 0.0 1993/08/14 19:54:25 root
219 * empty function bodies; detect() works.
220 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 **************************************************************************
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200222
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 see Documentation/scsi/aha152x.txt for configuration details
224
225 **************************************************************************/
226
227#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228#include <asm/irq.h>
Matthew Wilcox53d5ed62006-10-11 01:22:01 -0700229#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230#include <linux/blkdev.h>
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200231#include <linux/completion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232#include <linux/errno.h>
233#include <linux/string.h>
234#include <linux/wait.h>
235#include <linux/ioport.h>
236#include <linux/delay.h>
237#include <linux/proc_fs.h>
238#include <linux/interrupt.h>
239#include <linux/init.h>
240#include <linux/kernel.h>
241#include <linux/isapnp.h>
242#include <linux/spinlock.h>
243#include <linux/workqueue.h>
James Bottomley5fcda422006-09-14 17:04:58 -0500244#include <linux/list.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +0900245#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246#include <scsi/scsicam.h>
247
248#include "scsi.h"
db9dff32005-04-03 14:53:59 -0500249#include <scsi/scsi_dbg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250#include <scsi/scsi_host.h>
Matthew Wilcox1abfd372005-12-15 16:22:01 -0500251#include <scsi/scsi_transport_spi.h>
Boaz Harrosh73d2cb12007-11-01 18:54:44 +0200252#include <scsi/scsi_eh.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253#include "aha152x.h"
254
James Bottomley5fcda422006-09-14 17:04:58 -0500255static LIST_HEAD(aha152x_host_list);
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258/* DEFINES */
259
260/* For PCMCIA cards, always use AUTOCONF */
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +0200261#if defined(AHA152X_PCMCIA) || defined(MODULE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262#if !defined(AUTOCONF)
263#define AUTOCONF
264#endif
265#endif
266
267#if !defined(AUTOCONF) && !defined(SETUP0)
268#error define AUTOCONF or SETUP0
269#endif
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271#define DO_LOCK(flags) spin_lock_irqsave(&QLOCK,flags)
272#define DO_UNLOCK(flags) spin_unlock_irqrestore(&QLOCK,flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274#define LEAD "(scsi%d:%d:%d) "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275#define INFO_LEAD KERN_INFO LEAD
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276#define CMDINFO(cmd) \
277 (cmd) ? ((cmd)->device->host->host_no) : -1, \
278 (cmd) ? ((cmd)->device->id & 0x0f) : -1, \
Hannes Reinecke9cb78c12014-06-25 15:27:36 +0200279 (cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Boaz Harrosh23385452007-07-29 22:29:02 +0300281static inline void
282CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
283{
284 scsi_set_resid(cmd, scsi_get_resid(cmd) + inc);
285}
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287#define DELAY_DEFAULT 1000
288
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +0200289#if defined(AHA152X_PCMCIA)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290#define IRQ_MIN 0
291#define IRQ_MAX 16
292#else
293#define IRQ_MIN 9
294#if defined(__PPC)
Yinghai Lu171ac6a2008-08-19 20:49:54 -0700295#define IRQ_MAX (nr_irqs-1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296#else
297#define IRQ_MAX 12
298#endif
299#endif
300
301enum {
302 not_issued = 0x0001, /* command not yet issued */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200303 selecting = 0x0002, /* target is being selected */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 identified = 0x0004, /* IDENTIFY was sent */
305 disconnected = 0x0008, /* target disconnected */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200306 completed = 0x0010, /* target sent COMMAND COMPLETE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 aborted = 0x0020, /* ABORT was sent */
308 resetted = 0x0040, /* BUS DEVICE RESET was sent */
309 spiordy = 0x0080, /* waiting for SPIORDY to raise */
310 syncneg = 0x0100, /* synchronous negotiation in progress */
311 aborting = 0x0200, /* ABORT is pending */
312 resetting = 0x0400, /* BUS DEVICE RESET is pending */
313 check_condition = 0x0800, /* requesting sense after CHECK CONDITION */
314};
315
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200316MODULE_AUTHOR("Jürgen Fischer");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317MODULE_DESCRIPTION(AHA152X_REVID);
318MODULE_LICENSE("GPL");
319
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +0200320#if !defined(AHA152X_PCMCIA)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321#if defined(MODULE)
322static int io[] = {0, 0};
David Howells88f06b72017-04-04 16:54:27 +0100323module_param_hw_array(io, int, ioport, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324MODULE_PARM_DESC(io,"base io address of controller");
325
326static int irq[] = {0, 0};
David Howells88f06b72017-04-04 16:54:27 +0100327module_param_hw_array(irq, int, irq, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328MODULE_PARM_DESC(irq,"interrupt for controller");
329
330static int scsiid[] = {7, 7};
331module_param_array(scsiid, int, NULL, 0);
332MODULE_PARM_DESC(scsiid,"scsi id of controller");
333
334static int reconnect[] = {1, 1};
335module_param_array(reconnect, int, NULL, 0);
336MODULE_PARM_DESC(reconnect,"allow targets to disconnect");
337
338static int parity[] = {1, 1};
339module_param_array(parity, int, NULL, 0);
340MODULE_PARM_DESC(parity,"use scsi parity");
341
342static int sync[] = {1, 1};
343module_param_array(sync, int, NULL, 0);
344MODULE_PARM_DESC(sync,"use synchronous transfers");
345
346static int delay[] = {DELAY_DEFAULT, DELAY_DEFAULT};
347module_param_array(delay, int, NULL, 0);
348MODULE_PARM_DESC(delay,"scsi reset delay");
349
350static int exttrans[] = {0, 0};
351module_param_array(exttrans, int, NULL, 0);
352MODULE_PARM_DESC(exttrans,"use extended translation");
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
355module_param_array(aha152x, int, NULL, 0);
356MODULE_PARM_DESC(aha152x, "parameters for first controller");
357
358static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
359module_param_array(aha152x1, int, NULL, 0);
360MODULE_PARM_DESC(aha152x1, "parameters for second controller");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361#endif /* MODULE */
362
363#ifdef __ISAPNP__
Greg Kroah-Hartman6f039792012-12-21 13:08:55 -0800364static struct isapnp_device_id id_table[] = {
Ondrej Zary50f87f92011-06-09 21:21:23 +0200365 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
366 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
367 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
368 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
369 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
370 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
371 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
372 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
373 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
374 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
375 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
376 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
377 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 { ISAPNP_DEVICE_SINGLE_END, }
379};
380MODULE_DEVICE_TABLE(isapnp, id_table);
381#endif /* ISAPNP */
382
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +0200383#endif /* !AHA152X_PCMCIA */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100385static struct scsi_host_template aha152x_driver_template;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387/*
388 * internal states of the host
389 *
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200390 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391enum aha152x_state {
392 idle=0,
393 unknown,
394 seldo,
395 seldi,
396 selto,
397 busfree,
398 msgo,
399 cmd,
400 msgi,
401 status,
402 datai,
403 datao,
404 parerr,
405 rsti,
406 maxstate
407};
408
409/*
410 * current state information of the host
411 *
412 */
413struct aha152x_hostdata {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200414 struct scsi_cmnd *issue_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* pending commands to issue */
416
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200417 struct scsi_cmnd *current_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 /* current command on the bus */
419
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200420 struct scsi_cmnd *disconnected_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 /* commands that disconnected */
422
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200423 struct scsi_cmnd *done_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 /* command that was completed */
425
426 spinlock_t lock;
427 /* host lock */
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429#if defined(AHA152X_STAT)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200430 int total_commands;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 int disconnections;
432 int busfree_without_any_action;
433 int busfree_without_old_command;
434 int busfree_without_new_command;
435 int busfree_without_done_command;
436 int busfree_with_check_condition;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200437 int count[maxstate];
438 int count_trans[maxstate];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 unsigned long time[maxstate];
440#endif
441
442 int commands; /* current number of commands */
443
444 int reconnect; /* disconnection allowed */
445 int parity; /* parity checking enabled */
446 int synchronous; /* synchronous transferes enabled */
447 int delay; /* reset out delay */
448 int ext_trans; /* extended translation enabled */
449
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200450 int swint; /* software-interrupt was fired during detect() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 int service; /* bh needs to be run */
452 int in_intr; /* bh is running */
453
454 /* current state,
455 previous state,
456 last state different from current state */
457 enum aha152x_state state, prevstate, laststate;
458
459 int target;
460 /* reconnecting target */
461
462 unsigned char syncrate[8];
463 /* current synchronous transfer agreements */
464
465 unsigned char syncneg[8];
466 /* 0: no negotiation;
467 * 1: negotiation in progress;
468 * 2: negotiation completed
469 */
470
471 int cmd_i;
472 /* number of sent bytes of current command */
473
474 int msgi_len;
475 /* number of received message bytes */
476 unsigned char msgi[256];
477 /* received message bytes */
478
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200479 int msgo_i, msgo_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 /* number of sent bytes and length of current messages */
481 unsigned char msgo[256];
482 /* pending messages */
483
484 int data_len;
485 /* number of sent/received bytes in dataphase */
486
487 unsigned long io_port0;
488 unsigned long io_port1;
489
490#ifdef __ISAPNP__
491 struct pnp_dev *pnpdev;
492#endif
James Bottomley5fcda422006-09-14 17:04:58 -0500493 struct list_head host_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494};
495
496
497/*
498 * host specific command extension
499 *
500 */
501struct aha152x_scdata {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200502 struct scsi_cmnd *next; /* next sc in queue */
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200503 struct completion *done;/* semaphore to block on */
Boaz Harrosh73d2cb12007-11-01 18:54:44 +0200504 struct scsi_eh_save ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505};
506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507/* access macros for hostdata */
508
509#define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata)
510
511#define HOSTNO ((shpnt)->host_no)
512
513#define CURRENT_SC (HOSTDATA(shpnt)->current_SC)
514#define DONE_SC (HOSTDATA(shpnt)->done_SC)
515#define ISSUE_SC (HOSTDATA(shpnt)->issue_SC)
516#define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC)
517#define QLOCK (HOSTDATA(shpnt)->lock)
518#define QLOCKER (HOSTDATA(shpnt)->locker)
519#define QLOCKERL (HOSTDATA(shpnt)->lockerl)
520
521#define STATE (HOSTDATA(shpnt)->state)
522#define PREVSTATE (HOSTDATA(shpnt)->prevstate)
523#define LASTSTATE (HOSTDATA(shpnt)->laststate)
524
525#define RECONN_TARGET (HOSTDATA(shpnt)->target)
526
527#define CMD_I (HOSTDATA(shpnt)->cmd_i)
528
529#define MSGO(i) (HOSTDATA(shpnt)->msgo[i])
530#define MSGO_I (HOSTDATA(shpnt)->msgo_i)
531#define MSGOLEN (HOSTDATA(shpnt)->msgo_len)
532#define ADDMSGO(x) (MSGOLEN<256 ? (void)(MSGO(MSGOLEN++)=x) : aha152x_error(shpnt,"MSGO overflow"))
533
534#define MSGI(i) (HOSTDATA(shpnt)->msgi[i])
535#define MSGILEN (HOSTDATA(shpnt)->msgi_len)
536#define ADDMSGI(x) (MSGILEN<256 ? (void)(MSGI(MSGILEN++)=x) : aha152x_error(shpnt,"MSGI overflow"))
537
538#define DATA_LEN (HOSTDATA(shpnt)->data_len)
539
540#define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->device->id])
541#define SYNCNEG (HOSTDATA(shpnt)->syncneg[CURRENT_SC->device->id])
542
543#define DELAY (HOSTDATA(shpnt)->delay)
544#define EXT_TRANS (HOSTDATA(shpnt)->ext_trans)
545#define TC1550 (HOSTDATA(shpnt)->tc1550)
546#define RECONNECT (HOSTDATA(shpnt)->reconnect)
547#define PARITY (HOSTDATA(shpnt)->parity)
548#define SYNCHRONOUS (HOSTDATA(shpnt)->synchronous)
549
550#define HOSTIOPORT0 (HOSTDATA(shpnt)->io_port0)
551#define HOSTIOPORT1 (HOSTDATA(shpnt)->io_port1)
552
553#define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble)
554#define SCNEXT(SCpnt) SCDATA(SCpnt)->next
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200555#define SCSEM(SCpnt) SCDATA(SCpnt)->done
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Jens Axboe45711f12007-10-22 21:19:53 +0200557#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559/* state handling */
560static void seldi_run(struct Scsi_Host *shpnt);
561static void seldo_run(struct Scsi_Host *shpnt);
562static void selto_run(struct Scsi_Host *shpnt);
563static void busfree_run(struct Scsi_Host *shpnt);
564
565static void msgo_init(struct Scsi_Host *shpnt);
566static void msgo_run(struct Scsi_Host *shpnt);
567static void msgo_end(struct Scsi_Host *shpnt);
568
569static void cmd_init(struct Scsi_Host *shpnt);
570static void cmd_run(struct Scsi_Host *shpnt);
571static void cmd_end(struct Scsi_Host *shpnt);
572
573static void datai_init(struct Scsi_Host *shpnt);
574static void datai_run(struct Scsi_Host *shpnt);
575static void datai_end(struct Scsi_Host *shpnt);
576
577static void datao_init(struct Scsi_Host *shpnt);
578static void datao_run(struct Scsi_Host *shpnt);
579static void datao_end(struct Scsi_Host *shpnt);
580
581static void status_run(struct Scsi_Host *shpnt);
582
583static void msgi_run(struct Scsi_Host *shpnt);
584static void msgi_end(struct Scsi_Host *shpnt);
585
586static void parerr_run(struct Scsi_Host *shpnt);
587static void rsti_run(struct Scsi_Host *shpnt);
588
589static void is_complete(struct Scsi_Host *shpnt);
590
591/*
592 * driver states
593 *
594 */
595static struct {
596 char *name;
597 void (*init)(struct Scsi_Host *);
598 void (*run)(struct Scsi_Host *);
599 void (*end)(struct Scsi_Host *);
600 int spio;
601} states[] = {
602 { "idle", NULL, NULL, NULL, 0},
603 { "unknown", NULL, NULL, NULL, 0},
604 { "seldo", NULL, seldo_run, NULL, 0},
605 { "seldi", NULL, seldi_run, NULL, 0},
606 { "selto", NULL, selto_run, NULL, 0},
607 { "busfree", NULL, busfree_run, NULL, 0},
608 { "msgo", msgo_init, msgo_run, msgo_end, 1},
609 { "cmd", cmd_init, cmd_run, cmd_end, 1},
610 { "msgi", NULL, msgi_run, msgi_end, 1},
611 { "status", NULL, status_run, NULL, 1},
612 { "datai", datai_init, datai_run, datai_end, 0},
613 { "datao", datao_init, datao_run, datao_end, 0},
614 { "parerr", NULL, parerr_run, NULL, 0},
615 { "rsti", NULL, rsti_run, NULL, 0},
616};
617
618/* setup & interrupt */
David Howells7d12e782006-10-05 14:55:46 +0100619static irqreturn_t intr(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620static void reset_ports(struct Scsi_Host *shpnt);
621static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
622static void done(struct Scsi_Host *shpnt, int error);
623
624/* diagnostics */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200625static void show_command(struct scsi_cmnd * ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626static void show_queues(struct Scsi_Host *shpnt);
627static void disp_enintr(struct Scsi_Host *shpnt);
628
629
630/*
631 * queue services:
632 *
633 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200634static inline void append_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200636 struct scsi_cmnd *end;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
638 SCNEXT(new_SC) = NULL;
639 if (!*SC)
640 *SC = new_SC;
641 else {
642 for (end = *SC; SCNEXT(end); end = SCNEXT(end))
643 ;
644 SCNEXT(end) = new_SC;
645 }
646}
647
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200648static inline struct scsi_cmnd *remove_first_SC(struct scsi_cmnd ** SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200650 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
652 ptr = *SC;
653 if (ptr) {
654 *SC = SCNEXT(*SC);
655 SCNEXT(ptr)=NULL;
656 }
657 return ptr;
658}
659
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200660static inline struct scsi_cmnd *remove_lun_SC(struct scsi_cmnd ** SC,
661 int target, int lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200663 struct scsi_cmnd *ptr, *prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665 for (ptr = *SC, prev = NULL;
666 ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
667 prev = ptr, ptr = SCNEXT(ptr))
668 ;
669
670 if (ptr) {
671 if (prev)
672 SCNEXT(prev) = SCNEXT(ptr);
673 else
674 *SC = SCNEXT(ptr);
675
676 SCNEXT(ptr)=NULL;
677 }
678
679 return ptr;
680}
681
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200682static inline struct scsi_cmnd *remove_SC(struct scsi_cmnd **SC,
683 struct scsi_cmnd *SCp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200685 struct scsi_cmnd *ptr, *prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687 for (ptr = *SC, prev = NULL;
688 ptr && SCp!=ptr;
689 prev = ptr, ptr = SCNEXT(ptr))
690 ;
691
692 if (ptr) {
693 if (prev)
694 SCNEXT(prev) = SCNEXT(ptr);
695 else
696 *SC = SCNEXT(ptr);
697
698 SCNEXT(ptr)=NULL;
699 }
700
701 return ptr;
702}
703
David Howells7d12e782006-10-05 14:55:46 +0100704static irqreturn_t swintr(int irqno, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705{
Jeff Garzikc7bec5a2006-10-06 15:00:58 -0400706 struct Scsi_Host *shpnt = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
708 HOSTDATA(shpnt)->swint++;
709
710 SETPORT(DMACNTRL0, INTEN);
711 return IRQ_HANDLED;
712}
713
714struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
715{
716 struct Scsi_Host *shpnt;
717
718 shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata));
719 if (!shpnt) {
720 printk(KERN_ERR "aha152x: scsi_host_alloc failed\n");
721 return NULL;
722 }
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
James Bottomley5fcda422006-09-14 17:04:58 -0500725 INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
726
727 /* need to have host registered before triggering any interrupt */
728 list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 shpnt->io_port = setup->io_port;
731 shpnt->n_io_port = IO_RANGE;
732 shpnt->irq = setup->irq;
733
734 if (!setup->tc1550) {
735 HOSTIOPORT0 = setup->io_port;
736 HOSTIOPORT1 = setup->io_port;
737 } else {
738 HOSTIOPORT0 = setup->io_port+0x10;
739 HOSTIOPORT1 = setup->io_port-0x10;
740 }
741
742 spin_lock_init(&QLOCK);
743 RECONNECT = setup->reconnect;
744 SYNCHRONOUS = setup->synchronous;
745 PARITY = setup->parity;
746 DELAY = setup->delay;
747 EXT_TRANS = setup->ext_trans;
748
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 SETPORT(SCSIID, setup->scsiid << 4);
750 shpnt->this_id = setup->scsiid;
751
752 if (setup->reconnect)
753 shpnt->can_queue = AHA152X_MAXQUEUE;
754
755 /* RESET OUT */
756 printk("aha152x: resetting bus...\n");
757 SETPORT(SCSISEQ, SCSIRSTO);
758 mdelay(256);
759 SETPORT(SCSISEQ, 0);
760 mdelay(DELAY);
761
762 reset_ports(shpnt);
763
764 printk(KERN_INFO
765 "aha152x%d%s: "
766 "vital data: rev=%x, "
767 "io=0x%03lx (0x%03lx/0x%03lx), "
768 "irq=%d, "
769 "scsiid=%d, "
770 "reconnect=%s, "
771 "parity=%s, "
772 "synchronous=%s, "
773 "delay=%d, "
774 "extended translation=%s\n",
775 shpnt->host_no, setup->tc1550 ? " (tc1550 mode)" : "",
776 GETPORT(REV) & 0x7,
777 shpnt->io_port, HOSTIOPORT0, HOSTIOPORT1,
778 shpnt->irq,
779 shpnt->this_id,
780 RECONNECT ? "enabled" : "disabled",
781 PARITY ? "enabled" : "disabled",
782 SYNCHRONOUS ? "enabled" : "disabled",
783 DELAY,
784 EXT_TRANS ? "enabled" : "disabled");
785
786 /* not expecting any interrupts */
787 SETPORT(SIMODE0, 0);
788 SETPORT(SIMODE1, 0);
789
Michael Opdenacker4909cc22014-03-05 06:09:41 +0100790 if (request_irq(shpnt->irq, swintr, IRQF_SHARED, "aha152x", shpnt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
792 goto out_host_put;
793 }
794
795 HOSTDATA(shpnt)->swint = 0;
796
797 printk(KERN_INFO "aha152x%d: trying software interrupt, ", shpnt->host_no);
798
799 mb();
800 SETPORT(DMACNTRL0, SWINT|INTEN);
801 mdelay(1000);
802 free_irq(shpnt->irq, shpnt);
803
804 if (!HOSTDATA(shpnt)->swint) {
805 if (TESTHI(DMASTAT, INTSTAT)) {
806 printk("lost.\n");
807 } else {
808 printk("failed.\n");
809 }
810
811 SETPORT(DMACNTRL0, INTEN);
812
813 printk(KERN_ERR "aha152x%d: irq %d possibly wrong. "
814 "Please verify.\n", shpnt->host_no, shpnt->irq);
815 goto out_host_put;
816 }
817 printk("ok.\n");
818
819
820 /* clear interrupts */
821 SETPORT(SSTAT0, 0x7f);
822 SETPORT(SSTAT1, 0xef);
823
Michael Opdenacker4909cc22014-03-05 06:09:41 +0100824 if (request_irq(shpnt->irq, intr, IRQF_SHARED, "aha152x", shpnt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
826 goto out_host_put;
827 }
828
829 if( scsi_add_host(shpnt, NULL) ) {
830 free_irq(shpnt->irq, shpnt);
831 printk(KERN_ERR "aha152x%d: failed to add host.\n", shpnt->host_no);
832 goto out_host_put;
833 }
834
835 scsi_scan_host(shpnt);
836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return shpnt;
838
839out_host_put:
James Bottomley5fcda422006-09-14 17:04:58 -0500840 list_del(&HOSTDATA(shpnt)->host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 scsi_host_put(shpnt);
842
843 return NULL;
844}
845
846void aha152x_release(struct Scsi_Host *shpnt)
847{
Matthew Wilcox1bd40572007-08-15 12:56:57 -0600848 if (!shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 return;
850
Matthew Wilcox1bd40572007-08-15 12:56:57 -0600851 scsi_remove_host(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 if (shpnt->irq)
853 free_irq(shpnt->irq, shpnt);
854
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +0200855#if !defined(AHA152X_PCMCIA)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (shpnt->io_port)
857 release_region(shpnt->io_port, IO_RANGE);
858#endif
859
860#ifdef __ISAPNP__
861 if (HOSTDATA(shpnt)->pnpdev)
862 pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
863#endif
864
James Bottomley5fcda422006-09-14 17:04:58 -0500865 list_del(&HOSTDATA(shpnt)->host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 scsi_host_put(shpnt);
867}
868
869
870/*
871 * setup controller to generate interrupts depending
872 * on current state (lock has to be acquired)
873 *
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200874 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875static int setup_expected_interrupts(struct Scsi_Host *shpnt)
876{
877 if(CURRENT_SC) {
878 CURRENT_SC->SCp.phase |= 1 << 16;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 if(CURRENT_SC->SCp.phase & selecting) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 SETPORT(SSTAT1, SELTO);
882 SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
883 SETPORT(SIMODE1, ENSELTIMO);
884 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200886 SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 }
888 } else if(STATE==seldi) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 SETPORT(SIMODE0, 0);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200890 SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
893 SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0));
894 }
895
896 if(!HOSTDATA(shpnt)->in_intr)
897 SETBITS(DMACNTRL0, INTEN);
898
899 return TESTHI(DMASTAT, INTSTAT);
900}
901
902
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200903/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 * Queue a command and setup interrupts for a free bus.
905 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200906static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
907 struct completion *complete,
908 int phase, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 struct Scsi_Host *shpnt = SCpnt->device->host;
911 unsigned long flags;
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 SCpnt->scsi_done = done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 SCpnt->SCp.phase = not_issued | phase;
Boaz Harrosh0ceb4792007-07-29 22:22:04 +0300915 SCpnt->SCp.Status = 0x1; /* Ilegal status by SCSI standard */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 SCpnt->SCp.Message = 0;
917 SCpnt->SCp.have_data_in = 0;
918 SCpnt->SCp.sent_command = 0;
919
920 if(SCpnt->SCp.phase & (resetting|check_condition)) {
Harvey Harrison172c1222008-04-28 16:50:03 -0700921 if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200922 scmd_printk(KERN_ERR, SCpnt, "cannot reuse command\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 return FAILED;
924 }
925 } else {
926 SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
Harvey Harrison172c1222008-04-28 16:50:03 -0700927 if(!SCpnt->host_scribble) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +0200928 scmd_printk(KERN_ERR, SCpnt, "allocation failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 return FAILED;
930 }
931 }
932
933 SCNEXT(SCpnt) = NULL;
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200934 SCSEM(SCpnt) = complete;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
936 /* setup scratch area
937 SCp.ptr : buffer pointer
938 SCp.this_residual : buffer length
939 SCp.buffer : next buffer
940 SCp.buffers_residual : left buffers in list
941 SCp.phase : current state of the command */
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300942
Boaz Harrosh73d2cb12007-11-01 18:54:44 +0200943 if ((phase & resetting) || !scsi_sglist(SCpnt)) {
944 SCpnt->SCp.ptr = NULL;
945 SCpnt->SCp.this_residual = 0;
946 scsi_set_resid(SCpnt, 0);
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300947 SCpnt->SCp.buffer = NULL;
948 SCpnt->SCp.buffers_residual = 0;
949 } else {
Boaz Harrosh23385452007-07-29 22:29:02 +0300950 scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
951 SCpnt->SCp.buffer = scsi_sglist(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer);
953 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
Boaz Harrosh23385452007-07-29 22:29:02 +0300954 SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
957 DO_LOCK(flags);
958
959#if defined(AHA152X_STAT)
960 HOSTDATA(shpnt)->total_commands++;
961#endif
962
963 /* Turn led on, when this is the first command. */
964 HOSTDATA(shpnt)->commands++;
965 if (HOSTDATA(shpnt)->commands==1)
966 SETPORT(PORTA, 1);
967
968 append_SC(&ISSUE_SC, SCpnt);
969
970 if(!HOSTDATA(shpnt)->in_intr)
971 setup_expected_interrupts(shpnt);
972
973 DO_UNLOCK(flags);
974
975 return 0;
976}
977
978/*
979 * queue a command
980 *
981 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200982static int aha152x_queue_lck(struct scsi_cmnd *SCpnt,
983 void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 return aha152x_internal_queue(SCpnt, NULL, 0, done);
986}
987
Jeff Garzikf2812332010-11-16 02:10:29 -0500988static DEF_SCSI_QCMD(aha152x_queue)
989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
991/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 *
993 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200994static void reset_done(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 if(SCSEM(SCpnt)) {
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200997 complete(SCSEM(SCpnt));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 } else {
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200999 printk(KERN_ERR "aha152x: reset_done w/o completion\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 }
1001}
1002
1003/*
1004 * Abort a command
1005 *
1006 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001007static int aha152x_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008{
1009 struct Scsi_Host *shpnt = SCpnt->device->host;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001010 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 unsigned long flags;
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 DO_LOCK(flags);
1014
1015 ptr=remove_SC(&ISSUE_SC, SCpnt);
1016
1017 if(ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 HOSTDATA(shpnt)->commands--;
1019 if (!HOSTDATA(shpnt)->commands)
1020 SETPORT(PORTA, 0);
1021 DO_UNLOCK(flags);
1022
1023 kfree(SCpnt->host_scribble);
1024 SCpnt->host_scribble=NULL;
1025
1026 return SUCCESS;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 DO_UNLOCK(flags);
1030
1031 /*
1032 * FIXME:
1033 * for current command: queue ABORT for message out and raise ATN
1034 * for disconnected command: pseudo SC with ABORT message or ABORT on reselection?
1035 *
1036 */
1037
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001038 scmd_printk(KERN_ERR, SCpnt,
1039 "cannot abort running or disconnected command\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040
1041 return FAILED;
1042}
1043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044/*
1045 * Reset a device
1046 *
1047 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001048static int aha152x_device_reset(struct scsi_cmnd * SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
1050 struct Scsi_Host *shpnt = SCpnt->device->host;
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001051 DECLARE_COMPLETION(done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 int ret, issued, disconnected;
Christoph Hellwig631c2282006-07-08 20:42:15 +02001053 unsigned char old_cmd_len = SCpnt->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 unsigned long flags;
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001055 unsigned long timeleft;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 if(CURRENT_SC==SCpnt) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001058 scmd_printk(KERN_ERR, SCpnt, "cannot reset current device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 return FAILED;
1060 }
1061
1062 DO_LOCK(flags);
Harvey Harrison172c1222008-04-28 16:50:03 -07001063 issued = remove_SC(&ISSUE_SC, SCpnt) == NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 disconnected = issued && remove_SC(&DISCONNECTED_SC, SCpnt);
1065 DO_UNLOCK(flags);
1066
1067 SCpnt->cmd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001069 aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001071 timeleft = wait_for_completion_timeout(&done, 100*HZ);
1072 if (!timeleft) {
1073 /* remove command from issue queue */
1074 DO_LOCK(flags);
1075 remove_SC(&ISSUE_SC, SCpnt);
1076 DO_UNLOCK(flags);
1077 }
Christoph Hellwig631c2282006-07-08 20:42:15 +02001078
1079 SCpnt->cmd_len = old_cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 DO_LOCK(flags);
1082
1083 if(SCpnt->SCp.phase & resetted) {
1084 HOSTDATA(shpnt)->commands--;
1085 if (!HOSTDATA(shpnt)->commands)
1086 SETPORT(PORTA, 0);
1087 kfree(SCpnt->host_scribble);
1088 SCpnt->host_scribble=NULL;
1089
1090 ret = SUCCESS;
1091 } else {
1092 /* requeue */
1093 if(!issued) {
1094 append_SC(&ISSUE_SC, SCpnt);
1095 } else if(disconnected) {
1096 append_SC(&DISCONNECTED_SC, SCpnt);
1097 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001098
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 ret = FAILED;
1100 }
1101
1102 DO_UNLOCK(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return ret;
1104}
1105
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001106static void free_hard_reset_SCs(struct Scsi_Host *shpnt,
1107 struct scsi_cmnd **SCs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001109 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111 ptr=*SCs;
1112 while(ptr) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001113 struct scsi_cmnd *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 if(SCDATA(ptr)) {
1116 next = SCNEXT(ptr);
1117 } else {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001118 scmd_printk(KERN_DEBUG, ptr,
1119 "queue corrupted at %p\n", ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 next = NULL;
1121 }
1122
1123 if (!ptr->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 remove_SC(SCs, ptr);
1125 HOSTDATA(shpnt)->commands--;
1126 kfree(ptr->host_scribble);
1127 ptr->host_scribble=NULL;
1128 }
1129
1130 ptr = next;
1131 }
1132}
1133
1134/*
1135 * Reset the bus
1136 *
Hannes Reinecke819f80c2017-08-25 13:57:16 +02001137 * AIC-6260 has a hard reset (MRST signal), but apparently
1138 * one cannot trigger it via software. So live with
1139 * a soft reset; no-one seemed to have cared.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 */
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001141static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 unsigned long flags;
1144
1145 DO_LOCK(flags);
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 free_hard_reset_SCs(shpnt, &ISSUE_SC);
1148 free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 SETPORT(SCSISEQ, SCSIRSTO);
1151 mdelay(256);
1152 SETPORT(SCSISEQ, 0);
1153 mdelay(DELAY);
1154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 setup_expected_interrupts(shpnt);
1156 if(HOSTDATA(shpnt)->commands==0)
1157 SETPORT(PORTA, 0);
1158
1159 DO_UNLOCK(flags);
1160
1161 return SUCCESS;
1162}
1163
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001164/*
1165 * Reset the bus
1166 *
1167 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001168static int aha152x_bus_reset(struct scsi_cmnd *SCpnt)
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001169{
1170 return aha152x_bus_reset_host(SCpnt->device->host);
1171}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
1173/*
1174 * Restore default values to the AIC-6260 registers and reset the fifos
1175 *
1176 */
1177static void reset_ports(struct Scsi_Host *shpnt)
1178{
1179 unsigned long flags;
1180
1181 /* disable interrupts */
1182 SETPORT(DMACNTRL0, RSTFIFO);
1183
1184 SETPORT(SCSISEQ, 0);
1185
1186 SETPORT(SXFRCTL1, 0);
1187 SETPORT(SCSISIG, 0);
1188 SETRATE(0);
1189
1190 /* clear all interrupt conditions */
1191 SETPORT(SSTAT0, 0x7f);
1192 SETPORT(SSTAT1, 0xef);
1193
1194 SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);
1195
1196 SETPORT(DMACNTRL0, 0);
1197 SETPORT(DMACNTRL1, 0);
1198
1199 SETPORT(BRSTCNTRL, 0xf1);
1200
1201 /* clear SCSI fifos and transfer count */
1202 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
1203 SETPORT(SXFRCTL0, CH1);
1204
1205 DO_LOCK(flags);
1206 setup_expected_interrupts(shpnt);
1207 DO_UNLOCK(flags);
1208}
1209
1210/*
1211 * Reset the host (bus and controller)
1212 *
1213 */
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001214int aha152x_host_reset_host(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001216 aha152x_bus_reset_host(shpnt);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001217 reset_ports(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 return SUCCESS;
1220}
1221
1222/*
1223 * Return the "logical geometry"
1224 *
1225 */
1226static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1227 sector_t capacity, int *info_array)
1228{
1229 struct Scsi_Host *shpnt = sdev->host;
1230
1231 /* try default translation */
1232 info_array[0] = 64;
1233 info_array[1] = 32;
1234 info_array[2] = (unsigned long)capacity / (64 * 32);
1235
1236 /* for disks >1GB do some guessing */
1237 if (info_array[2] >= 1024) {
1238 int info[3];
1239
1240 /* try to figure out the geometry from the partition table */
1241 if (scsicam_bios_param(bdev, capacity, info) < 0 ||
1242 !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) {
1243 if (EXT_TRANS) {
1244 printk(KERN_NOTICE
1245 "aha152x: unable to verify geometry for disk with >1GB.\n"
1246 " using extended translation.\n");
1247 info_array[0] = 255;
1248 info_array[1] = 63;
1249 info_array[2] = (unsigned long)capacity / (255 * 63);
1250 } else {
1251 printk(KERN_NOTICE
1252 "aha152x: unable to verify geometry for disk with >1GB.\n"
1253 " Using default translation. Please verify yourself.\n"
1254 " Perhaps you need to enable extended translation in the driver.\n"
1255 " See Documentation/scsi/aha152x.txt for details.\n");
1256 }
1257 } else {
1258 info_array[0] = info[0];
1259 info_array[1] = info[1];
1260 info_array[2] = info[2];
1261
1262 if (info[0] == 255 && !EXT_TRANS) {
1263 printk(KERN_NOTICE
1264 "aha152x: current partition table is using extended translation.\n"
1265 " using it also, although it's not explicitly enabled.\n");
1266 }
1267 }
1268 }
1269
1270 return 0;
1271}
1272
1273/*
1274 * Internal done function
1275 *
1276 */
1277static void done(struct Scsi_Host *shpnt, int error)
1278{
1279 if (CURRENT_SC) {
1280 if(DONE_SC)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001281 scmd_printk(KERN_ERR, CURRENT_SC,
1282 "there's already a completed command %p "
1283 "- will cause abort\n", DONE_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 DONE_SC = CURRENT_SC;
1286 CURRENT_SC = NULL;
1287 DONE_SC->result = error;
1288 } else
1289 printk(KERN_ERR "aha152x: done() called outside of command\n");
1290}
1291
1292static struct work_struct aha152x_tq;
1293
1294/*
1295 * Run service completions on the card with interrupts enabled.
1296 *
1297 */
David Howellsc4028952006-11-22 14:57:56 +00001298static void run(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299{
James Bottomley5fcda422006-09-14 17:04:58 -05001300 struct aha152x_hostdata *hd;
1301
1302 list_for_each_entry(hd, &aha152x_host_list, host_list) {
1303 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
1304
1305 is_complete(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 }
1307}
1308
1309/*
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001310 * Interrupt handler
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 *
1312 */
David Howells7d12e782006-10-05 14:55:46 +01001313static irqreturn_t intr(int irqno, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314{
Jeff Garzike19166d2008-04-18 19:22:52 -04001315 struct Scsi_Host *shpnt = dev_id;
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001316 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 unsigned char rev, dmacntrl0;
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 /*
1320 * Read a couple of registers that are known to not be all 1's. If
1321 * we read all 1's (-1), that means that either:
1322 *
1323 * a. The host adapter chip has gone bad, and we cannot control it,
1324 * OR
1325 * b. The host adapter is a PCMCIA card that has been ejected
1326 *
1327 * In either case, we cannot do anything with the host adapter at
1328 * this point in time. So just ignore the interrupt and return.
1329 * In the latter case, the interrupt might actually be meant for
1330 * someone else sharing this IRQ, and that driver will handle it.
1331 */
1332 rev = GETPORT(REV);
1333 dmacntrl0 = GETPORT(DMACNTRL0);
1334 if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
1335 return IRQ_NONE;
1336
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001337 if( TESTLO(DMASTAT, INTSTAT) )
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001338 return IRQ_NONE;
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 /* no more interrupts from the controller, while we're busy.
1341 INTEN is restored by the BH handler */
1342 CLRBITS(DMACNTRL0, INTEN);
1343
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001344 DO_LOCK(flags);
1345 if( HOSTDATA(shpnt)->service==0 ) {
1346 HOSTDATA(shpnt)->service=1;
1347
1348 /* Poke the BH handler */
David Howellsc4028952006-11-22 14:57:56 +00001349 INIT_WORK(&aha152x_tq, run);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001350 schedule_work(&aha152x_tq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 }
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001352 DO_UNLOCK(flags);
1353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 return IRQ_HANDLED;
1355}
1356
1357/*
1358 * busfree phase
1359 * - handle completition/disconnection/error of current command
1360 * - start selection for next command (if any)
1361 */
1362static void busfree_run(struct Scsi_Host *shpnt)
1363{
1364 unsigned long flags;
1365#if defined(AHA152X_STAT)
1366 int action=0;
1367#endif
1368
1369 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
1370 SETPORT(SXFRCTL0, CH1);
1371
1372 SETPORT(SSTAT1, CLRBUSFREE);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 if(CURRENT_SC) {
1375#if defined(AHA152X_STAT)
1376 action++;
1377#endif
1378 CURRENT_SC->SCp.phase &= ~syncneg;
1379
1380 if(CURRENT_SC->SCp.phase & completed) {
1381 /* target sent COMMAND COMPLETE */
1382 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1383
1384 } else if(CURRENT_SC->SCp.phase & aborted) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16));
1386
1387 } else if(CURRENT_SC->SCp.phase & resetted) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16));
1389
1390 } else if(CURRENT_SC->SCp.phase & disconnected) {
1391 /* target sent DISCONNECT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392#if defined(AHA152X_STAT)
1393 HOSTDATA(shpnt)->disconnections++;
1394#endif
1395 append_SC(&DISCONNECTED_SC, CURRENT_SC);
1396 CURRENT_SC->SCp.phase |= 1 << 16;
1397 CURRENT_SC = NULL;
1398
1399 } else {
1400 done(shpnt, DID_ERROR << 16);
1401 }
1402#if defined(AHA152X_STAT)
1403 } else {
1404 HOSTDATA(shpnt)->busfree_without_old_command++;
1405#endif
1406 }
1407
1408 DO_LOCK(flags);
1409
1410 if(DONE_SC) {
1411#if defined(AHA152X_STAT)
1412 action++;
1413#endif
1414
1415 if(DONE_SC->SCp.phase & check_condition) {
Christoph Hellwig5e13cdf2006-07-08 20:39:30 +02001416 struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
1417 struct aha152x_scdata *sc = SCDATA(cmd);
1418
Boaz Harrosh73d2cb12007-11-01 18:54:44 +02001419 scsi_eh_restore_cmnd(cmd, &sc->ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001421 cmd->SCp.Status = SAM_STAT_CHECK_CONDITION;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
1423 HOSTDATA(shpnt)->commands--;
1424 if (!HOSTDATA(shpnt)->commands)
1425 SETPORT(PORTA, 0); /* turn led off */
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001426 } else if(DONE_SC->SCp.Status==SAM_STAT_CHECK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427#if defined(AHA152X_STAT)
1428 HOSTDATA(shpnt)->busfree_with_check_condition++;
1429#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001431 if(!(DONE_SC->SCp.phase & not_issued)) {
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001432 struct aha152x_scdata *sc;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001433 struct scsi_cmnd *ptr = DONE_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 DONE_SC=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001436 sc = SCDATA(ptr);
1437 /* It was allocated in aha152x_internal_queue? */
1438 BUG_ON(!sc);
Boaz Harrosh73d2cb12007-11-01 18:54:44 +02001439 scsi_eh_prep_cmnd(ptr, &sc->ses, NULL, 0, ~0);
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 DO_UNLOCK(flags);
1442 aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done);
1443 DO_LOCK(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 }
1445 }
1446
1447 if(DONE_SC && DONE_SC->scsi_done) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001448 struct scsi_cmnd *ptr = DONE_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 DONE_SC=NULL;
1450
1451 /* turn led off, when no commands are in the driver */
1452 HOSTDATA(shpnt)->commands--;
1453 if (!HOSTDATA(shpnt)->commands)
1454 SETPORT(PORTA, 0); /* turn led off */
1455
1456 if(ptr->scsi_done != reset_done) {
1457 kfree(ptr->host_scribble);
1458 ptr->host_scribble=NULL;
1459 }
1460
1461 DO_UNLOCK(flags);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001462 ptr->scsi_done(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 DO_LOCK(flags);
1464 }
1465
1466 DONE_SC=NULL;
1467#if defined(AHA152X_STAT)
1468 } else {
1469 HOSTDATA(shpnt)->busfree_without_done_command++;
1470#endif
1471 }
1472
1473 if(ISSUE_SC)
1474 CURRENT_SC = remove_first_SC(&ISSUE_SC);
1475
1476 DO_UNLOCK(flags);
1477
1478 if(CURRENT_SC) {
1479#if defined(AHA152X_STAT)
1480 action++;
1481#endif
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001482 CURRENT_SC->SCp.phase |= selecting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
1484 /* clear selection timeout */
1485 SETPORT(SSTAT1, SELTO);
1486
1487 SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->device->id);
1488 SETPORT(SXFRCTL1, (PARITY ? ENSPCHK : 0 ) | ENSTIMER);
1489 SETPORT(SCSISEQ, ENSELO | ENAUTOATNO | (DISCONNECTED_SC ? ENRESELI : 0));
1490 } else {
1491#if defined(AHA152X_STAT)
1492 HOSTDATA(shpnt)->busfree_without_new_command++;
1493#endif
1494 SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
1495 }
1496
1497#if defined(AHA152X_STAT)
1498 if(!action)
1499 HOSTDATA(shpnt)->busfree_without_any_action++;
1500#endif
1501}
1502
1503/*
1504 * Selection done (OUT)
1505 * - queue IDENTIFY message and SDTR to selected target for message out
1506 * (ATN asserted automagically via ENAUTOATNO in busfree())
1507 */
1508static void seldo_run(struct Scsi_Host *shpnt)
1509{
1510 SETPORT(SCSISIG, 0);
1511 SETPORT(SSTAT1, CLRBUSFREE);
1512 SETPORT(SSTAT1, CLRPHASECHG);
1513
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001514 CURRENT_SC->SCp.phase &= ~(selecting|not_issued);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 SETPORT(SCSISEQ, 0);
1517
1518 if (TESTLO(SSTAT0, SELDO)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001519 scmd_printk(KERN_ERR, CURRENT_SC,
1520 "aha152x: passing bus free condition\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 done(shpnt, DID_NO_CONNECT << 16);
1522 return;
1523 }
1524
1525 SETPORT(SSTAT0, CLRSELDO);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001526
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
1528
1529 if (CURRENT_SC->SCp.phase & aborting) {
1530 ADDMSGO(ABORT);
1531 } else if (CURRENT_SC->SCp.phase & resetting) {
1532 ADDMSGO(BUS_DEVICE_RESET);
1533 } else if (SYNCNEG==0 && SYNCHRONOUS) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001534 CURRENT_SC->SCp.phase |= syncneg;
Matthew Wilcox6ea3c0b2006-02-07 07:54:46 -07001535 MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 SYNCNEG=1; /* negotiation in progress */
1537 }
1538
1539 SETRATE(SYNCRATE);
1540}
1541
1542/*
1543 * Selection timeout
1544 * - return command to mid-level with failure cause
1545 *
1546 */
1547static void selto_run(struct Scsi_Host *shpnt)
1548{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001549 SETPORT(SCSISEQ, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 SETPORT(SSTAT1, CLRSELTIMO);
1551
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001552 if (!CURRENT_SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001555 CURRENT_SC->SCp.phase &= ~selecting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001557 if (CURRENT_SC->SCp.phase & aborted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 done(shpnt, DID_ABORT << 16);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001559 else if (TESTLO(SSTAT0, SELINGO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 done(shpnt, DID_BUS_BUSY << 16);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001561 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 /* ARBITRATION won, but SELECTION failed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 done(shpnt, DID_NO_CONNECT << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564}
1565
1566/*
1567 * Selection in done
1568 * - put current command back to issue queue
1569 * (reconnection of a disconnected nexus instead
1570 * of successful selection out)
1571 *
1572 */
1573static void seldi_run(struct Scsi_Host *shpnt)
1574{
1575 int selid;
1576 int target;
1577 unsigned long flags;
1578
1579 SETPORT(SCSISIG, 0);
1580 SETPORT(SSTAT0, CLRSELDI);
1581 SETPORT(SSTAT1, CLRBUSFREE);
1582 SETPORT(SSTAT1, CLRPHASECHG);
1583
1584 if(CURRENT_SC) {
1585 if(!(CURRENT_SC->SCp.phase & not_issued))
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001586 scmd_printk(KERN_ERR, CURRENT_SC,
1587 "command should not have been issued yet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 DO_LOCK(flags);
1590 append_SC(&ISSUE_SC, CURRENT_SC);
1591 DO_UNLOCK(flags);
1592
1593 CURRENT_SC = NULL;
1594 }
1595
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001596 if (!DISCONNECTED_SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 RECONN_TARGET=-1;
1600
1601 selid = GETPORT(SELID) & ~(1 << shpnt->this_id);
1602
1603 if (selid==0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001604 shost_printk(KERN_INFO, shpnt,
1605 "target id unknown (%02x)\n", selid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 return;
1607 }
1608
1609 for(target=7; !(selid & (1 << target)); target--)
1610 ;
1611
1612 if(selid & ~(1 << target)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001613 shost_printk(KERN_INFO, shpnt,
1614 "multiple targets reconnected (%02x)\n", selid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 }
1616
1617
1618 SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
1619 SETPORT(SCSISEQ, 0);
1620
1621 SETRATE(HOSTDATA(shpnt)->syncrate[target]);
1622
1623 RECONN_TARGET=target;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624}
1625
1626/*
1627 * message in phase
1628 * - handle initial message after reconnection to identify
1629 * reconnecting nexus
1630 * - queue command on DISCONNECTED_SC on DISCONNECT message
1631 * - set completed flag on COMMAND COMPLETE
1632 * (other completition code moved to busfree_run)
1633 * - handle response to SDTR
1634 * - clear synchronous transfer agreements on BUS RESET
1635 *
1636 * FIXME: what about SAVE POINTERS, RESTORE POINTERS?
1637 *
1638 */
1639static void msgi_run(struct Scsi_Host *shpnt)
1640{
1641 for(;;) {
1642 int sstat1 = GETPORT(SSTAT1);
1643
1644 if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT))
1645 return;
1646
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001647 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
1650 ADDMSGI(GETPORT(SCSIDAT));
1651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 if(!CURRENT_SC) {
1653 if(LASTSTATE!=seldi) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001654 shost_printk(KERN_ERR, shpnt,
1655 "message in w/o current command"
1656 " not after reselection\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658
1659 /*
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001660 * Handle reselection
1661 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if(!(MSGI(0) & IDENTIFY_BASE)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001663 shost_printk(KERN_ERR, shpnt,
1664 "target didn't identify after reselection\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 continue;
1666 }
1667
1668 CURRENT_SC = remove_lun_SC(&DISCONNECTED_SC, RECONN_TARGET, MSGI(0) & 0x3f);
1669
1670 if (!CURRENT_SC) {
1671 show_queues(shpnt);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001672 shost_printk(KERN_ERR, shpnt,
1673 "no disconnected command"
1674 " for target %d/%d\n",
1675 RECONN_TARGET, MSGI(0) & 0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 continue;
1677 }
1678
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 CURRENT_SC->SCp.Message = MSGI(0);
1680 CURRENT_SC->SCp.phase &= ~disconnected;
1681
1682 MSGILEN=0;
1683
1684 /* next message if any */
1685 continue;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 CURRENT_SC->SCp.Message = MSGI(0);
1689
1690 switch (MSGI(0)) {
1691 case DISCONNECT:
1692 if (!RECONNECT)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001693 scmd_printk(KERN_WARNING, CURRENT_SC,
1694 "target was not allowed to disconnect\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 CURRENT_SC->SCp.phase |= disconnected;
1697 break;
1698
1699 case COMMAND_COMPLETE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 CURRENT_SC->SCp.phase |= completed;
1701 break;
1702
1703 case MESSAGE_REJECT:
1704 if (SYNCNEG==1) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001705 scmd_printk(KERN_INFO, CURRENT_SC,
1706 "Synchronous Data Transfer Request"
1707 " was rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 SYNCNEG=2; /* negotiation completed */
1709 } else
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001710 scmd_printk(KERN_INFO, CURRENT_SC,
1711 "inbound message (MESSAGE REJECT)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 break;
1713
1714 case SAVE_POINTERS:
1715 break;
1716
1717 case RESTORE_POINTERS:
1718 break;
1719
1720 case EXTENDED_MESSAGE:
1721 if(MSGILEN<2 || MSGILEN<MSGI(1)+2) {
1722 /* not yet completed */
1723 continue;
1724 }
1725
1726 switch (MSGI(2)) {
1727 case EXTENDED_SDTR:
1728 {
1729 long ticks;
1730
1731 if (MSGI(1) != 3) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001732 scmd_printk(KERN_ERR, CURRENT_SC,
1733 "SDTR message length!=3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 break;
1735 }
1736
1737 if (!HOSTDATA(shpnt)->synchronous)
1738 break;
1739
1740 printk(INFO_LEAD, CMDINFO(CURRENT_SC));
Matthew Wilcox1abfd372005-12-15 16:22:01 -05001741 spi_print_msg(&MSGI(0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 printk("\n");
1743
1744 ticks = (MSGI(3) * 4 + 49) / 50;
1745
1746 if (syncneg) {
1747 /* negotiation in progress */
1748 if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) {
1749 ADDMSGO(MESSAGE_REJECT);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001750 scmd_printk(KERN_INFO,
1751 CURRENT_SC,
1752 "received Synchronous Data Transfer Request invalid - rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 break;
1754 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
1757 } else if (ticks <= 9 && MSGI(4) >= 1) {
1758 ADDMSGO(EXTENDED_MESSAGE);
1759 ADDMSGO(3);
1760 ADDMSGO(EXTENDED_SDTR);
1761 if (ticks < 4) {
1762 ticks = 4;
1763 ADDMSGO(50);
1764 } else
1765 ADDMSGO(MSGI(3));
1766
1767 if (MSGI(4) > 8)
1768 MSGI(4) = 8;
1769
1770 ADDMSGO(MSGI(4));
1771
1772 SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
1773 } else {
1774 /* requested SDTR is too slow, do it asynchronously */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001775 scmd_printk(KERN_INFO,
1776 CURRENT_SC,
1777 "Synchronous Data Transfer Request too slow - Rejecting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 ADDMSGO(MESSAGE_REJECT);
1779 }
1780
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001781 /* negotiation completed */
1782 SYNCNEG=2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 SETRATE(SYNCRATE);
1784 }
1785 break;
1786
1787 case BUS_DEVICE_RESET:
1788 {
1789 int i;
1790
1791 for(i=0; i<8; i++) {
1792 HOSTDATA(shpnt)->syncrate[i]=0;
1793 HOSTDATA(shpnt)->syncneg[i]=0;
1794 }
1795
1796 }
1797 break;
1798
1799 case EXTENDED_MODIFY_DATA_POINTER:
1800 case EXTENDED_EXTENDED_IDENTIFY:
1801 case EXTENDED_WDTR:
1802 default:
1803 ADDMSGO(MESSAGE_REJECT);
1804 break;
1805 }
1806 break;
1807 }
1808
1809 MSGILEN=0;
1810 }
1811}
1812
1813static void msgi_end(struct Scsi_Host *shpnt)
1814{
1815 if(MSGILEN>0)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001816 scmd_printk(KERN_WARNING, CURRENT_SC,
1817 "target left before message completed (%d)\n",
1818 MSGILEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001820 if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 SETPORT(SCSISIG, P_MSGI | SIG_ATNO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822}
1823
1824/*
1825 * message out phase
1826 *
1827 */
1828static void msgo_init(struct Scsi_Host *shpnt)
1829{
1830 if(MSGOLEN==0) {
1831 if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) {
1832 ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
1833 } else {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001834 scmd_printk(KERN_INFO, CURRENT_SC,
1835 "unexpected MESSAGE OUT phase; rejecting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 ADDMSGO(MESSAGE_REJECT);
1837 }
1838 }
1839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840}
1841
1842/*
1843 * message out phase
1844 *
1845 */
1846static void msgo_run(struct Scsi_Host *shpnt)
1847{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 while(MSGO_I<MSGOLEN) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001849 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
1852 if (MSGO_I==MSGOLEN-1) {
1853 /* Leave MESSAGE OUT after transfer */
1854 SETPORT(SSTAT1, CLRATNO);
1855 }
1856
1857
1858 if (MSGO(MSGO_I) & IDENTIFY_BASE)
1859 CURRENT_SC->SCp.phase |= identified;
1860
1861 if (MSGO(MSGO_I)==ABORT)
1862 CURRENT_SC->SCp.phase |= aborted;
1863
1864 if (MSGO(MSGO_I)==BUS_DEVICE_RESET)
1865 CURRENT_SC->SCp.phase |= resetted;
1866
1867 SETPORT(SCSIDAT, MSGO(MSGO_I++));
1868 }
1869}
1870
1871static void msgo_end(struct Scsi_Host *shpnt)
1872{
1873 if(MSGO_I<MSGOLEN) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001874 scmd_printk(KERN_ERR, CURRENT_SC,
1875 "message sent incompletely (%d/%d)\n",
1876 MSGO_I, MSGOLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 if(SYNCNEG==1) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001878 scmd_printk(KERN_INFO, CURRENT_SC,
1879 "Synchronous Data Transfer Request was rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 SYNCNEG=2;
1881 }
1882 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001883
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 MSGO_I = 0;
1885 MSGOLEN = 0;
1886}
1887
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001888/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 * command phase
1890 *
1891 */
1892static void cmd_init(struct Scsi_Host *shpnt)
1893{
1894 if (CURRENT_SC->SCp.sent_command) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001895 scmd_printk(KERN_ERR, CURRENT_SC,
1896 "command already sent\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 done(shpnt, DID_ERROR << 16);
1898 return;
1899 }
1900
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 CMD_I=0;
1902}
1903
1904/*
1905 * command phase
1906 *
1907 */
1908static void cmd_run(struct Scsi_Host *shpnt)
1909{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 while(CMD_I<CURRENT_SC->cmd_len) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001911 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
1914 SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]);
1915 }
1916}
1917
1918static void cmd_end(struct Scsi_Host *shpnt)
1919{
1920 if(CMD_I<CURRENT_SC->cmd_len)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001921 scmd_printk(KERN_ERR, CURRENT_SC,
1922 "command sent incompletely (%d/%d)\n",
1923 CMD_I, CURRENT_SC->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 else
1925 CURRENT_SC->SCp.sent_command++;
1926}
1927
1928/*
1929 * status phase
1930 *
1931 */
1932static void status_run(struct Scsi_Host *shpnt)
1933{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001934 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
1937 CURRENT_SC->SCp.Status = GETPORT(SCSIDAT);
1938
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939}
1940
1941/*
1942 * data in phase
1943 *
1944 */
1945static void datai_init(struct Scsi_Host *shpnt)
1946{
1947 SETPORT(DMACNTRL0, RSTFIFO);
1948 SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
1949
1950 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
1951 SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
1952
1953 SETPORT(SIMODE0, 0);
1954 SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE);
1955
1956 DATA_LEN=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957}
1958
1959static void datai_run(struct Scsi_Host *shpnt)
1960{
1961 unsigned long the_time;
1962 int fifodata, data_count;
1963
1964 /*
1965 * loop while the phase persists or the fifos are not empty
1966 *
1967 */
1968 while(TESTLO(DMASTAT, INTSTAT) || TESTLO(DMASTAT, DFIFOEMP) || TESTLO(SSTAT2, SEMPTY)) {
1969 /* FIXME: maybe this should be done by setting up
1970 * STCNT to trigger ENSWRAP interrupt, instead of
1971 * polling for DFIFOFULL
1972 */
1973 the_time=jiffies + 100*HZ;
1974 while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time))
1975 barrier();
1976
1977 if(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001978 scmd_printk(KERN_ERR, CURRENT_SC, "datai timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 break;
1980 }
1981
1982 if(TESTHI(DMASTAT, DFIFOFULL)) {
1983 fifodata = 128;
1984 } else {
1985 the_time=jiffies + 100*HZ;
1986 while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
1987 barrier();
1988
1989 if(TESTLO(SSTAT2, SEMPTY)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001990 scmd_printk(KERN_ERR, CURRENT_SC,
1991 "datai sempty timeout");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 break;
1993 }
1994
1995 fifodata = GETPORT(FIFOSTAT);
1996 }
1997
1998 if(CURRENT_SC->SCp.this_residual>0) {
1999 while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002000 data_count = fifodata > CURRENT_SC->SCp.this_residual ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 CURRENT_SC->SCp.this_residual :
2002 fifodata;
2003 fifodata -= data_count;
2004
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002005 if (data_count & 1) {
2006 SETPORT(DMACNTRL0, ENDMA|_8BIT);
2007 *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
2008 CURRENT_SC->SCp.this_residual--;
2009 DATA_LEN++;
2010 SETPORT(DMACNTRL0, ENDMA);
2011 }
2012
2013 if (data_count > 1) {
2014 data_count >>= 1;
2015 insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
2016 CURRENT_SC->SCp.ptr += 2 * data_count;
2017 CURRENT_SC->SCp.this_residual -= 2 * data_count;
2018 DATA_LEN += 2 * data_count;
2019 }
2020
2021 if (CURRENT_SC->SCp.this_residual == 0 &&
2022 CURRENT_SC->SCp.buffers_residual > 0) {
2023 /* advance to next buffer */
2024 CURRENT_SC->SCp.buffers_residual--;
2025 CURRENT_SC->SCp.buffer++;
2026 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
2027 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
2028 }
2029 }
2030 } else if (fifodata > 0) {
2031 scmd_printk(KERN_ERR, CURRENT_SC,
2032 "no buffers left for %d(%d) bytes"
2033 " (data overrun!?)\n",
2034 fifodata, GETPORT(FIFOSTAT));
2035 SETPORT(DMACNTRL0, ENDMA|_8BIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 while(fifodata>0) {
2037 int data;
2038 data=GETPORT(DATAPORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 fifodata--;
2040 DATA_LEN++;
2041 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002042 SETPORT(DMACNTRL0, ENDMA|_8BIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
2044 }
2045
2046 if(TESTLO(DMASTAT, INTSTAT) ||
2047 TESTLO(DMASTAT, DFIFOEMP) ||
2048 TESTLO(SSTAT2, SEMPTY) ||
2049 GETPORT(FIFOSTAT)>0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002050 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 * something went wrong, if there's something left in the fifos
2052 * or the phase didn't change
2053 */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002054 scmd_printk(KERN_ERR, CURRENT_SC,
2055 "fifos should be empty and phase should have changed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 }
2057
2058 if(DATA_LEN!=GETSTCNT()) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002059 scmd_printk(KERN_ERR, CURRENT_SC,
2060 "manual transfer count differs from automatic "
2061 "(count=%d;stcnt=%d;diff=%d;fifostat=%d)",
2062 DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN,
2063 GETPORT(FIFOSTAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 mdelay(10000);
2065 }
2066}
2067
2068static void datai_end(struct Scsi_Host *shpnt)
2069{
Boaz Harrosh23385452007-07-29 22:29:02 +03002070 CMD_INC_RESID(CURRENT_SC, -GETSTCNT());
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
2073 SETPORT(DMACNTRL0, 0);
2074}
2075
2076/*
2077 * data out phase
2078 *
2079 */
2080static void datao_init(struct Scsi_Host *shpnt)
2081{
2082 SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO);
2083 SETPORT(DMACNTRL0, WRITE_READ | ENDMA);
2084
2085 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
2086 SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
2087
2088 SETPORT(SIMODE0, 0);
2089 SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE );
2090
Boaz Harrosh23385452007-07-29 22:29:02 +03002091 DATA_LEN = scsi_get_resid(CURRENT_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092}
2093
2094static void datao_run(struct Scsi_Host *shpnt)
2095{
2096 unsigned long the_time;
2097 int data_count;
2098
2099 /* until phase changes or all data sent */
2100 while(TESTLO(DMASTAT, INTSTAT) && CURRENT_SC->SCp.this_residual>0) {
2101 data_count = 128;
2102 if(data_count > CURRENT_SC->SCp.this_residual)
2103 data_count=CURRENT_SC->SCp.this_residual;
2104
2105 if(TESTLO(DMASTAT, DFIFOEMP)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002106 scmd_printk(KERN_ERR, CURRENT_SC,
2107 "datao fifo not empty (%d)",
2108 GETPORT(FIFOSTAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 break;
2110 }
2111
2112 if(data_count & 1) {
2113 SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT);
2114 SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
2115 CURRENT_SC->SCp.this_residual--;
Boaz Harrosh23385452007-07-29 22:29:02 +03002116 CMD_INC_RESID(CURRENT_SC, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 SETPORT(DMACNTRL0,WRITE_READ|ENDMA);
2118 }
2119
2120 if(data_count > 1) {
2121 data_count >>= 1;
2122 outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
2123 CURRENT_SC->SCp.ptr += 2 * data_count;
2124 CURRENT_SC->SCp.this_residual -= 2 * data_count;
Boaz Harrosh23385452007-07-29 22:29:02 +03002125 CMD_INC_RESID(CURRENT_SC, -2 * data_count);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
2128 if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) {
2129 /* advance to next buffer */
2130 CURRENT_SC->SCp.buffers_residual--;
2131 CURRENT_SC->SCp.buffer++;
2132 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
2133 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
2134 }
2135
2136 the_time=jiffies + 100*HZ;
2137 while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
2138 barrier();
2139
2140 if(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002141 scmd_printk(KERN_ERR, CURRENT_SC, "dataout timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 break;
2143 }
2144 }
2145}
2146
2147static void datao_end(struct Scsi_Host *shpnt)
2148{
2149 if(TESTLO(DMASTAT, DFIFOEMP)) {
Boaz Harrosh23385452007-07-29 22:29:02 +03002150 int data_count = (DATA_LEN - scsi_get_resid(CURRENT_SC)) -
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002151 GETSTCNT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Boaz Harrosh23385452007-07-29 22:29:02 +03002153 CMD_INC_RESID(CURRENT_SC, data_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
Boaz Harrosh23385452007-07-29 22:29:02 +03002155 data_count -= CURRENT_SC->SCp.ptr -
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002156 SG_ADDRESS(CURRENT_SC->SCp.buffer);
Boaz Harrosh23385452007-07-29 22:29:02 +03002157 while(data_count>0) {
2158 CURRENT_SC->SCp.buffer--;
2159 CURRENT_SC->SCp.buffers_residual++;
2160 data_count -= CURRENT_SC->SCp.buffer->length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
Boaz Harrosh23385452007-07-29 22:29:02 +03002162 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) -
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002163 data_count;
Boaz Harrosh23385452007-07-29 22:29:02 +03002164 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length +
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002165 data_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 }
2167
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
2169 SETPORT(SXFRCTL0, CH1);
2170
2171 SETPORT(DMACNTRL0, 0);
2172}
2173
2174/*
2175 * figure out what state we're in
2176 *
2177 */
2178static int update_state(struct Scsi_Host *shpnt)
2179{
2180 int dataphase=0;
2181 unsigned int stat0 = GETPORT(SSTAT0);
2182 unsigned int stat1 = GETPORT(SSTAT1);
2183
2184 PREVSTATE = STATE;
2185 STATE=unknown;
2186
2187 if(stat1 & SCSIRSTI) {
2188 STATE=rsti;
2189 SETPORT(SCSISEQ,0);
2190 SETPORT(SSTAT1,SCSIRSTI);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002191 } else if (stat0 & SELDI && PREVSTATE == busfree) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 STATE=seldi;
2193 } else if(stat0 & SELDO && CURRENT_SC && (CURRENT_SC->SCp.phase & selecting)) {
2194 STATE=seldo;
2195 } else if(stat1 & SELTO) {
2196 STATE=selto;
2197 } else if(stat1 & BUSFREE) {
2198 STATE=busfree;
2199 SETPORT(SSTAT1,BUSFREE);
2200 } else if(stat1 & SCSIPERR) {
2201 STATE=parerr;
2202 SETPORT(SSTAT1,SCSIPERR);
2203 } else if(stat1 & REQINIT) {
2204 switch(GETPORT(SCSISIG) & P_MASK) {
2205 case P_MSGI: STATE=msgi; break;
2206 case P_MSGO: STATE=msgo; break;
2207 case P_DATAO: STATE=datao; break;
2208 case P_DATAI: STATE=datai; break;
2209 case P_STATUS: STATE=status; break;
2210 case P_CMD: STATE=cmd; break;
2211 }
2212 dataphase=1;
2213 }
2214
2215 if((stat0 & SELDI) && STATE!=seldi && !dataphase) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002216 scmd_printk(KERN_INFO, CURRENT_SC, "reselection missed?");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 }
2218
2219 if(STATE!=PREVSTATE) {
2220 LASTSTATE=PREVSTATE;
2221 }
2222
2223 return dataphase;
2224}
2225
2226/*
2227 * handle parity error
2228 *
2229 * FIXME: in which phase?
2230 *
2231 */
2232static void parerr_run(struct Scsi_Host *shpnt)
2233{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002234 scmd_printk(KERN_ERR, CURRENT_SC, "parity error\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 done(shpnt, DID_PARITY << 16);
2236}
2237
2238/*
2239 * handle reset in
2240 *
2241 */
2242static void rsti_run(struct Scsi_Host *shpnt)
2243{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002244 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002246 shost_printk(KERN_NOTICE, shpnt, "scsi reset in\n");
2247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 ptr=DISCONNECTED_SC;
2249 while(ptr) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002250 struct scsi_cmnd *next = SCNEXT(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 if (!ptr->device->soft_reset) {
2253 remove_SC(&DISCONNECTED_SC, ptr);
2254
2255 kfree(ptr->host_scribble);
2256 ptr->host_scribble=NULL;
2257
2258 ptr->result = DID_RESET << 16;
2259 ptr->scsi_done(ptr);
2260 }
2261
2262 ptr = next;
2263 }
2264
2265 if(CURRENT_SC && !CURRENT_SC->device->soft_reset)
2266 done(shpnt, DID_RESET << 16 );
2267}
2268
2269
2270/*
2271 * bottom-half handler
2272 *
2273 */
2274static void is_complete(struct Scsi_Host *shpnt)
2275{
2276 int dataphase;
2277 unsigned long flags;
2278 int pending;
2279
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01002280 if(!shpnt)
2281 return;
2282
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 DO_LOCK(flags);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01002284
2285 if( HOSTDATA(shpnt)->service==0 ) {
2286 DO_UNLOCK(flags);
2287 return;
2288 }
2289
2290 HOSTDATA(shpnt)->service = 0;
2291
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 if(HOSTDATA(shpnt)->in_intr) {
2293 DO_UNLOCK(flags);
2294 /* aha152x_error never returns.. */
2295 aha152x_error(shpnt, "bottom-half already running!?");
2296 }
2297 HOSTDATA(shpnt)->in_intr++;
2298
2299 /*
2300 * loop while there are interrupt conditions pending
2301 *
2302 */
2303 do {
2304 unsigned long start = jiffies;
2305 DO_UNLOCK(flags);
2306
2307 dataphase=update_state(shpnt);
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 /*
2310 * end previous state
2311 *
2312 */
2313 if(PREVSTATE!=STATE && states[PREVSTATE].end)
2314 states[PREVSTATE].end(shpnt);
2315
2316 /*
2317 * disable SPIO mode if previous phase used it
2318 * and this one doesn't
2319 *
2320 */
2321 if(states[PREVSTATE].spio && !states[STATE].spio) {
2322 SETPORT(SXFRCTL0, CH1);
2323 SETPORT(DMACNTRL0, 0);
2324 if(CURRENT_SC)
2325 CURRENT_SC->SCp.phase &= ~spiordy;
2326 }
2327
2328 /*
2329 * accept current dataphase phase
2330 *
2331 */
2332 if(dataphase) {
2333 SETPORT(SSTAT0, REQINIT);
2334 SETPORT(SCSISIG, GETPORT(SCSISIG) & P_MASK);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002335 SETPORT(SSTAT1, PHASECHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002337
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 /*
2339 * enable SPIO mode if previous didn't use it
2340 * and this one does
2341 *
2342 */
2343 if(!states[PREVSTATE].spio && states[STATE].spio) {
2344 SETPORT(DMACNTRL0, 0);
2345 SETPORT(SXFRCTL0, CH1|SPIOEN);
2346 if(CURRENT_SC)
2347 CURRENT_SC->SCp.phase |= spiordy;
2348 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 /*
2351 * initialize for new state
2352 *
2353 */
2354 if(PREVSTATE!=STATE && states[STATE].init)
2355 states[STATE].init(shpnt);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002356
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 /*
2358 * handle current state
2359 *
2360 */
2361 if(states[STATE].run)
2362 states[STATE].run(shpnt);
2363 else
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002364 scmd_printk(KERN_ERR, CURRENT_SC,
2365 "unexpected state (%x)\n", STATE);
2366
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 /*
2368 * setup controller to interrupt on
2369 * the next expected condition and
2370 * loop if it's already there
2371 *
2372 */
2373 DO_LOCK(flags);
2374 pending=setup_expected_interrupts(shpnt);
2375#if defined(AHA152X_STAT)
2376 HOSTDATA(shpnt)->count[STATE]++;
2377 if(PREVSTATE!=STATE)
2378 HOSTDATA(shpnt)->count_trans[STATE]++;
2379 HOSTDATA(shpnt)->time[STATE] += jiffies-start;
2380#endif
2381
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 } while(pending);
2383
2384 /*
2385 * enable interrupts and leave bottom-half
2386 *
2387 */
2388 HOSTDATA(shpnt)->in_intr--;
2389 SETBITS(DMACNTRL0, INTEN);
2390 DO_UNLOCK(flags);
2391}
2392
2393
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002394/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 * Dump the current driver status and panic
2396 */
2397static void aha152x_error(struct Scsi_Host *shpnt, char *msg)
2398{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002399 shost_printk(KERN_EMERG, shpnt, "%s\n", msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 show_queues(shpnt);
2401 panic("aha152x panic\n");
2402}
2403
2404/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 * display enabled interrupts
2406 */
2407static void disp_enintr(struct Scsi_Host *shpnt)
2408{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002409 int s0, s1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002411 s0 = GETPORT(SIMODE0);
2412 s1 = GETPORT(SIMODE1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002414 shost_printk(KERN_DEBUG, shpnt,
2415 "enabled interrupts (%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
2416 (s0 & ENSELDO) ? "ENSELDO " : "",
2417 (s0 & ENSELDI) ? "ENSELDI " : "",
2418 (s0 & ENSELINGO) ? "ENSELINGO " : "",
2419 (s0 & ENSWRAP) ? "ENSWRAP " : "",
2420 (s0 & ENSDONE) ? "ENSDONE " : "",
2421 (s0 & ENSPIORDY) ? "ENSPIORDY " : "",
2422 (s0 & ENDMADONE) ? "ENDMADONE " : "",
2423 (s1 & ENSELTIMO) ? "ENSELTIMO " : "",
2424 (s1 & ENATNTARG) ? "ENATNTARG " : "",
2425 (s1 & ENPHASEMIS) ? "ENPHASEMIS " : "",
2426 (s1 & ENBUSFREE) ? "ENBUSFREE " : "",
2427 (s1 & ENSCSIPERR) ? "ENSCSIPERR " : "",
2428 (s1 & ENPHASECHG) ? "ENPHASECHG " : "",
2429 (s1 & ENREQINIT) ? "ENREQINIT " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430}
2431
2432/*
2433 * Show the command data of a command
2434 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002435static void show_command(struct scsi_cmnd *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002437 scsi_print_command(ptr);
2438 scmd_printk(KERN_DEBUG, ptr,
2439 "request_bufflen=%d; resid=%d; "
2440 "phase |%s%s%s%s%s%s%s%s%s; next=0x%p",
2441 scsi_bufflen(ptr), scsi_get_resid(ptr),
2442 (ptr->SCp.phase & not_issued) ? "not issued|" : "",
2443 (ptr->SCp.phase & selecting) ? "selecting|" : "",
2444 (ptr->SCp.phase & identified) ? "identified|" : "",
2445 (ptr->SCp.phase & disconnected) ? "disconnected|" : "",
2446 (ptr->SCp.phase & completed) ? "completed|" : "",
2447 (ptr->SCp.phase & spiordy) ? "spiordy|" : "",
2448 (ptr->SCp.phase & syncneg) ? "syncneg|" : "",
2449 (ptr->SCp.phase & aborted) ? "aborted|" : "",
2450 (ptr->SCp.phase & resetted) ? "resetted|" : "",
2451 (SCDATA(ptr)) ? SCNEXT(ptr) : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452}
2453
2454/*
2455 * Dump the queued data
2456 */
2457static void show_queues(struct Scsi_Host *shpnt)
2458{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002459 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 unsigned long flags;
2461
2462 DO_LOCK(flags);
2463 printk(KERN_DEBUG "\nqueue status:\nissue_SC:\n");
2464 for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
2465 show_command(ptr);
2466 DO_UNLOCK(flags);
2467
2468 printk(KERN_DEBUG "current_SC:\n");
2469 if (CURRENT_SC)
2470 show_command(CURRENT_SC);
2471 else
2472 printk(KERN_DEBUG "none\n");
2473
2474 printk(KERN_DEBUG "disconnected_SC:\n");
2475 for (ptr = DISCONNECTED_SC; ptr; ptr = SCDATA(ptr) ? SCNEXT(ptr) : NULL)
2476 show_command(ptr);
2477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 disp_enintr(shpnt);
2479}
2480
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002481static void get_command(struct seq_file *m, struct scsi_cmnd * ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 int i;
2484
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002485 seq_printf(m, "%p: target=%d; lun=%d; cmnd=( ",
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002486 ptr, ptr->device->id, (u8)ptr->device->lun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
2488 for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002489 seq_printf(m, "0x%02x ", ptr->cmnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002491 seq_printf(m, "); resid=%d; residual=%d; buffers=%d; phase |",
Boaz Harrosh23385452007-07-29 22:29:02 +03002492 scsi_get_resid(ptr), ptr->SCp.this_residual,
2493 ptr->SCp.buffers_residual);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 if (ptr->SCp.phase & not_issued)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002496 seq_puts(m, "not issued|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 if (ptr->SCp.phase & selecting)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002498 seq_puts(m, "selecting|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 if (ptr->SCp.phase & disconnected)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002500 seq_puts(m, "disconnected|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 if (ptr->SCp.phase & aborted)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002502 seq_puts(m, "aborted|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 if (ptr->SCp.phase & identified)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002504 seq_puts(m, "identified|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 if (ptr->SCp.phase & completed)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002506 seq_puts(m, "completed|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 if (ptr->SCp.phase & spiordy)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002508 seq_puts(m, "spiordy|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 if (ptr->SCp.phase & syncneg)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002510 seq_puts(m, "syncneg|");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002511 seq_printf(m, "; next=0x%p\n", SCNEXT(ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512}
2513
Al Viro275084c2013-03-31 03:12:15 -04002514static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 int s;
2517
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002518 seq_printf(m, "\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 s = GETPORT(SCSISEQ);
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002521 seq_puts(m, "SCSISEQ( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 if (s & TEMODEO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002523 seq_puts(m, "TARGET MODE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 if (s & ENSELO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002525 seq_puts(m, "SELO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 if (s & ENSELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002527 seq_puts(m, "SELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 if (s & ENRESELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002529 seq_puts(m, "RESELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 if (s & ENAUTOATNO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002531 seq_puts(m, "AUTOATNO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 if (s & ENAUTOATNI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002533 seq_puts(m, "AUTOATNI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 if (s & ENAUTOATNP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002535 seq_puts(m, "AUTOATNP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 if (s & SCSIRSTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002537 seq_puts(m, "SCSIRSTO ");
2538 seq_puts(m, ");");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002540 seq_puts(m, " SCSISIG(");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 s = GETPORT(SCSISIG);
2542 switch (s & P_MASK) {
2543 case P_DATAO:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002544 seq_puts(m, "DATA OUT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 break;
2546 case P_DATAI:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002547 seq_puts(m, "DATA IN");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 break;
2549 case P_CMD:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002550 seq_puts(m, "COMMAND");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 break;
2552 case P_STATUS:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002553 seq_puts(m, "STATUS");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 break;
2555 case P_MSGO:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002556 seq_puts(m, "MESSAGE OUT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 break;
2558 case P_MSGI:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002559 seq_puts(m, "MESSAGE IN");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 break;
2561 default:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002562 seq_puts(m, "*invalid*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 break;
2564 }
2565
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002566 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002568 seq_printf(m, "INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002570 seq_puts(m, "SSTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 s = GETPORT(SSTAT0);
2572 if (s & TARGET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002573 seq_puts(m, "TARGET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 if (s & SELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002575 seq_puts(m, "SELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 if (s & SELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002577 seq_puts(m, "SELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 if (s & SELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002579 seq_puts(m, "SELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if (s & SWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002581 seq_puts(m, "SWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 if (s & SDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002583 seq_puts(m, "SDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 if (s & SPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002585 seq_puts(m, "SPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 if (s & DMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002587 seq_puts(m, "DMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 s = GETPORT(SSTAT1);
2590 if (s & SELTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002591 seq_puts(m, "SELTO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 if (s & ATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002593 seq_puts(m, "ATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 if (s & SCSIRSTI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002595 seq_puts(m, "SCSIRSTI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 if (s & PHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002597 seq_puts(m, "PHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 if (s & BUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002599 seq_puts(m, "BUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 if (s & SCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002601 seq_puts(m, "SCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 if (s & PHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002603 seq_puts(m, "PHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if (s & REQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002605 seq_puts(m, "REQINIT ");
2606 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
2608
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002609 seq_puts(m, "SSTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
2612
2613 if (s & TARGET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002614 seq_puts(m, "TARGET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 if (s & SELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002616 seq_puts(m, "SELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 if (s & SELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002618 seq_puts(m, "SELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 if (s & SELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002620 seq_puts(m, "SELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 if (s & SWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002622 seq_puts(m, "SWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 if (s & SDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002624 seq_puts(m, "SDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 if (s & SPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002626 seq_puts(m, "SPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 if (s & DMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002628 seq_puts(m, "DMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
2630 s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
2631
2632 if (s & SELTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002633 seq_puts(m, "SELTO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 if (s & ATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002635 seq_puts(m, "ATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 if (s & SCSIRSTI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002637 seq_puts(m, "SCSIRSTI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 if (s & PHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002639 seq_puts(m, "PHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 if (s & BUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002641 seq_puts(m, "BUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 if (s & SCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002643 seq_puts(m, "SCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 if (s & PHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002645 seq_puts(m, "PHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 if (s & REQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002647 seq_puts(m, "REQINIT ");
2648 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002650 seq_puts(m, "SXFRCTL0( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
2652 s = GETPORT(SXFRCTL0);
2653 if (s & SCSIEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002654 seq_puts(m, "SCSIEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 if (s & DMAEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002656 seq_puts(m, "DMAEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 if (s & CH1)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002658 seq_puts(m, "CH1 ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 if (s & CLRSTCNT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002660 seq_puts(m, "CLRSTCNT ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 if (s & SPIOEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002662 seq_puts(m, "SPIOEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 if (s & CLRCH1)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002664 seq_puts(m, "CLRCH1 ");
2665 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002667 seq_puts(m, "SIGNAL( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
2669 s = GETPORT(SCSISIG);
2670 if (s & SIG_ATNI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002671 seq_puts(m, "ATNI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 if (s & SIG_SELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002673 seq_puts(m, "SELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 if (s & SIG_BSYI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002675 seq_puts(m, "BSYI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 if (s & SIG_REQI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002677 seq_puts(m, "REQI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 if (s & SIG_ACKI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002679 seq_puts(m, "ACKI ");
2680 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002682 seq_printf(m, "SELID(%02x), ", GETPORT(SELID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002684 seq_printf(m, "STCNT(%d), ", GETSTCNT());
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002686 seq_puts(m, "SSTAT2( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
2688 s = GETPORT(SSTAT2);
2689 if (s & SOFFSET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002690 seq_puts(m, "SOFFSET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if (s & SEMPTY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002692 seq_puts(m, "SEMPTY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 if (s & SFULL)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002694 seq_puts(m, "SFULL ");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002695 seq_printf(m, "); SFCNT (%d); ", s & (SFULL | SFCNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697 s = GETPORT(SSTAT3);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002698 seq_printf(m, "SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002700 seq_puts(m, "SSTAT4( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 s = GETPORT(SSTAT4);
2702 if (s & SYNCERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002703 seq_puts(m, "SYNCERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 if (s & FWERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002705 seq_puts(m, "FWERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 if (s & FRERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002707 seq_puts(m, "FRERR ");
2708 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002710 seq_puts(m, "DMACNTRL0( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 s = GETPORT(DMACNTRL0);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002712 seq_printf(m, "%s ", s & _8BIT ? "8BIT" : "16BIT");
2713 seq_printf(m, "%s ", s & DMA ? "DMA" : "PIO");
2714 seq_printf(m, "%s ", s & WRITE_READ ? "WRITE" : "READ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (s & ENDMA)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002716 seq_puts(m, "ENDMA ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 if (s & INTEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002718 seq_puts(m, "INTEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 if (s & RSTFIFO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002720 seq_puts(m, "RSTFIFO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 if (s & SWINT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002722 seq_puts(m, "SWINT ");
2723 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002725 seq_puts(m, "DMASTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 s = GETPORT(DMASTAT);
2727 if (s & ATDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002728 seq_puts(m, "ATDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 if (s & WORDRDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002730 seq_puts(m, "WORDRDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 if (s & DFIFOFULL)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002732 seq_puts(m, "DFIFOFULL ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 if (s & DFIFOEMP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002734 seq_puts(m, "DFIFOEMP ");
2735 seq_puts(m, ")\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002737 seq_puts(m, "enabled interrupts( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739 s = GETPORT(SIMODE0);
2740 if (s & ENSELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002741 seq_puts(m, "ENSELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 if (s & ENSELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002743 seq_puts(m, "ENSELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 if (s & ENSELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002745 seq_puts(m, "ENSELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 if (s & ENSWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002747 seq_puts(m, "ENSWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (s & ENSDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002749 seq_puts(m, "ENSDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 if (s & ENSPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002751 seq_puts(m, "ENSPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 if (s & ENDMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002753 seq_puts(m, "ENDMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 s = GETPORT(SIMODE1);
2756 if (s & ENSELTIMO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002757 seq_puts(m, "ENSELTIMO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 if (s & ENATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002759 seq_puts(m, "ENATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 if (s & ENPHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002761 seq_puts(m, "ENPHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 if (s & ENBUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002763 seq_puts(m, "ENBUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 if (s & ENSCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002765 seq_puts(m, "ENSCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 if (s & ENPHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002767 seq_puts(m, "ENPHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 if (s & ENREQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002769 seq_puts(m, "ENREQINIT ");
2770 seq_puts(m, ")\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771}
2772
Al Viro275084c2013-03-31 03:12:15 -04002773static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774{
2775 if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
2776 return -EINVAL;
2777
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778#if defined(AHA152X_STAT)
2779 if(length>13 && strncmp("reset", buffer+8, 5)==0) {
2780 int i;
2781
2782 HOSTDATA(shpnt)->total_commands=0;
2783 HOSTDATA(shpnt)->disconnections=0;
2784 HOSTDATA(shpnt)->busfree_without_any_action=0;
2785 HOSTDATA(shpnt)->busfree_without_old_command=0;
2786 HOSTDATA(shpnt)->busfree_without_new_command=0;
2787 HOSTDATA(shpnt)->busfree_without_done_command=0;
2788 HOSTDATA(shpnt)->busfree_with_check_condition=0;
2789 for (i = idle; i<maxstate; i++) {
2790 HOSTDATA(shpnt)->count[i]=0;
2791 HOSTDATA(shpnt)->count_trans[i]=0;
2792 HOSTDATA(shpnt)->time[i]=0;
2793 }
2794
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002795 shost_printk(KERN_INFO, shpnt, "aha152x: stats reset.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
2797 } else
2798#endif
2799 {
2800 return -EINVAL;
2801 }
2802
2803
2804 return length;
2805}
2806
Al Viro275084c2013-03-31 03:12:15 -04002807static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808{
2809 int i;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002810 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002813 seq_puts(m, AHA152X_REVID "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002815 seq_printf(m, "ioports 0x%04lx to 0x%04lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002817 seq_printf(m, "interrupt 0x%02x\n", shpnt->irq);
2818 seq_printf(m, "disconnection/reconnection %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 RECONNECT ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002820 seq_printf(m, "parity checking %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 PARITY ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002822 seq_printf(m, "synchronous transfers %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 SYNCHRONOUS ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002824 seq_printf(m, "%d commands currently queued\n", HOSTDATA(shpnt)->commands);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
2826 if(SYNCHRONOUS) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002827 seq_puts(m, "synchronously operating targets (tick=50 ns):\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 for (i = 0; i < 8; i++)
2829 if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002830 seq_printf(m, "target %d: period %dT/%dns; req/ack offset %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 i,
2832 (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
2833 (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
2834 HOSTDATA(shpnt)->syncrate[i] & 0x0f);
2835 }
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002836 seq_puts(m, "\nqueue status:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 DO_LOCK(flags);
2838 if (ISSUE_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002839 seq_puts(m, "not yet issued commands:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
Al Viro275084c2013-03-31 03:12:15 -04002841 get_command(m, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002843 seq_puts(m, "no not yet issued commands\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 DO_UNLOCK(flags);
2845
2846 if (CURRENT_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002847 seq_puts(m, "current command:\n");
Al Viro275084c2013-03-31 03:12:15 -04002848 get_command(m, CURRENT_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002850 seq_puts(m, "no current command\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
2852 if (DISCONNECTED_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002853 seq_puts(m, "disconnected commands:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
Al Viro275084c2013-03-31 03:12:15 -04002855 get_command(m, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002857 seq_puts(m, "no disconnected commands\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Al Viro275084c2013-03-31 03:12:15 -04002859 get_ports(m, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
2861#if defined(AHA152X_STAT)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002862 seq_printf(m, "statistics:\n"
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002863 "total commands: %d\n"
2864 "disconnections: %d\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 "busfree with check condition: %d\n"
2866 "busfree without old command: %d\n"
2867 "busfree without new command: %d\n"
2868 "busfree without done command: %d\n"
2869 "busfree without any action: %d\n"
2870 "state "
2871 "transitions "
2872 "count "
2873 "time\n",
2874 HOSTDATA(shpnt)->total_commands,
2875 HOSTDATA(shpnt)->disconnections,
2876 HOSTDATA(shpnt)->busfree_with_check_condition,
2877 HOSTDATA(shpnt)->busfree_without_old_command,
2878 HOSTDATA(shpnt)->busfree_without_new_command,
2879 HOSTDATA(shpnt)->busfree_without_done_command,
2880 HOSTDATA(shpnt)->busfree_without_any_action);
2881 for(i=0; i<maxstate; i++) {
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002882 seq_printf(m, "%-10s %-12d %-12d %-12ld\n",
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002883 states[i].name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 HOSTDATA(shpnt)->count_trans[i],
2885 HOSTDATA(shpnt)->count[i],
2886 HOSTDATA(shpnt)->time[i]);
2887 }
2888#endif
Al Viro275084c2013-03-31 03:12:15 -04002889 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890}
2891
Boaz Harroshb1ee0792007-07-29 22:18:20 +03002892static int aha152x_adjust_queue(struct scsi_device *device)
2893{
2894 blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
2895 return 0;
2896}
2897
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01002898static struct scsi_host_template aha152x_driver_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 .module = THIS_MODULE,
2900 .name = AHA152X_REVID,
2901 .proc_name = "aha152x",
Al Viro275084c2013-03-31 03:12:15 -04002902 .show_info = aha152x_show_info,
2903 .write_info = aha152x_set_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 .queuecommand = aha152x_queue,
2905 .eh_abort_handler = aha152x_abort,
2906 .eh_device_reset_handler = aha152x_device_reset,
2907 .eh_bus_reset_handler = aha152x_bus_reset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 .bios_param = aha152x_biosparam,
2909 .can_queue = 1,
2910 .this_id = 7,
2911 .sg_tablesize = SG_ALL,
Christoph Hellwig4af14d12018-12-13 16:17:09 +01002912 .dma_boundary = PAGE_SIZE - 1,
Boaz Harroshb1ee0792007-07-29 22:18:20 +03002913 .slave_alloc = aha152x_adjust_queue,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914};
2915
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +02002916#if !defined(AHA152X_PCMCIA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917static int setup_count;
2918static struct aha152x_setup setup[2];
2919
2920/* possible i/o addresses for the AIC-6260; default first */
2921static unsigned short ports[] = { 0x340, 0x140 };
2922
2923#if !defined(SKIP_BIOSTEST)
2924/* possible locations for the Adaptec BIOS; defaults first */
2925static unsigned int addresses[] =
2926{
2927 0xdc000, /* default first */
2928 0xc8000,
2929 0xcc000,
2930 0xd0000,
2931 0xd4000,
2932 0xd8000,
2933 0xe0000,
2934 0xeb800, /* VTech Platinum SMP */
2935 0xf0000,
2936};
2937
2938/* signatures for various AIC-6[23]60 based controllers.
2939 The point in detecting signatures is to avoid useless and maybe
2940 harmful probes on ports. I'm not sure that all listed boards pass
2941 auto-configuration. For those which fail the BIOS signature is
2942 obsolete, because user intervention to supply the configuration is
2943 needed anyway. May be an information whether or not the BIOS supports
2944 extended translation could be also useful here. */
2945static struct signature {
2946 unsigned char *signature;
2947 int sig_offset;
2948 int sig_length;
2949} signatures[] =
2950{
2951 { "Adaptec AHA-1520 BIOS", 0x102e, 21 },
2952 /* Adaptec 152x */
2953 { "Adaptec AHA-1520B", 0x000b, 17 },
2954 /* Adaptec 152x rev B */
2955 { "Adaptec AHA-1520B", 0x0026, 17 },
2956 /* Iomega Jaz Jet ISA (AIC6370Q) */
2957 { "Adaptec ASW-B626 BIOS", 0x1029, 21 },
2958 /* on-board controller */
2959 { "Adaptec BIOS: ASW-B626", 0x000f, 22 },
2960 /* on-board controller */
2961 { "Adaptec ASW-B626 S2", 0x2e6c, 19 },
2962 /* on-board controller */
2963 { "Adaptec BIOS:AIC-6360", 0x000c, 21 },
2964 /* on-board controller */
2965 { "ScsiPro SP-360 BIOS", 0x2873, 19 },
2966 /* ScsiPro-Controller */
2967 { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },
2968 /* Gigabyte Local-Bus-SCSI */
2969 { "Adaptec BIOS:AVA-282X", 0x000c, 21 },
2970 /* Adaptec 282x */
2971 { "Adaptec IBM Dock II SCSI", 0x2edd, 24 },
2972 /* IBM Thinkpad Dock II */
2973 { "Adaptec BIOS:AHA-1532P", 0x001c, 22 },
2974 /* IBM Thinkpad Dock II SCSI */
2975 { "DTC3520A Host Adapter BIOS", 0x318a, 26 },
2976 /* DTC 3520A ISA SCSI */
2977};
2978#endif /* !SKIP_BIOSTEST */
2979
2980/*
2981 * Test, if port_base is valid.
2982 *
2983 */
2984static int aha152x_porttest(int io_port)
2985{
2986 int i;
2987
2988 SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
2989 for (i = 0; i < 16; i++)
2990 SETPORT(io_port + O_STACK, i);
2991
2992 SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
2993 for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++)
2994 ;
2995
2996 return (i == 16);
2997}
2998
2999static int tc1550_porttest(int io_port)
3000{
3001 int i;
3002
3003 SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
3004 for (i = 0; i < 16; i++)
3005 SETPORT(io_port + O_STACK, i);
3006
3007 SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
3008 for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++)
3009 ;
3010
3011 return (i == 16);
3012}
3013
3014
3015static int checksetup(struct aha152x_setup *setup)
3016{
3017 int i;
3018 for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
3019 ;
3020
3021 if (i == ARRAY_SIZE(ports))
3022 return 0;
3023
Harvey Harrison9bcf0912008-05-22 15:45:07 -07003024 if (!request_region(setup->io_port, IO_RANGE, "aha152x")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port);
3026 return 0;
3027 }
3028
3029 if( aha152x_porttest(setup->io_port) ) {
3030 setup->tc1550=0;
3031 } else if( tc1550_porttest(setup->io_port) ) {
3032 setup->tc1550=1;
3033 } else {
3034 release_region(setup->io_port, IO_RANGE);
3035 return 0;
3036 }
3037
3038 release_region(setup->io_port, IO_RANGE);
3039
3040 if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
3041 return 0;
3042
3043 if ((setup->scsiid < 0) || (setup->scsiid > 7))
3044 return 0;
3045
3046 if ((setup->reconnect < 0) || (setup->reconnect > 1))
3047 return 0;
3048
3049 if ((setup->parity < 0) || (setup->parity > 1))
3050 return 0;
3051
3052 if ((setup->synchronous < 0) || (setup->synchronous > 1))
3053 return 0;
3054
3055 if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
3056 return 0;
3057
3058
3059 return 1;
3060}
3061
3062
3063static int __init aha152x_init(void)
3064{
3065 int i, j, ok;
3066#if defined(AUTOCONF)
3067 aha152x_config conf;
3068#endif
3069#ifdef __ISAPNP__
3070 struct pnp_dev *dev=NULL, *pnpdev[2] = {NULL, NULL};
3071#endif
3072
3073 if ( setup_count ) {
3074 printk(KERN_INFO "aha152x: processing commandline: ");
3075
3076 for (i = 0; i<setup_count; i++) {
3077 if (!checksetup(&setup[i])) {
3078 printk(KERN_ERR "\naha152x: %s\n", setup[i].conf);
3079 printk(KERN_ERR "aha152x: invalid line\n");
3080 }
3081 }
3082 printk("ok\n");
3083 }
3084
3085#if defined(SETUP0)
3086 if (setup_count < ARRAY_SIZE(setup)) {
3087 struct aha152x_setup override = SETUP0;
3088
3089 if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
3090 if (!checksetup(&override)) {
3091 printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
3092 override.io_port,
3093 override.irq,
3094 override.scsiid,
3095 override.reconnect,
3096 override.parity,
3097 override.synchronous,
3098 override.delay,
3099 override.ext_trans);
3100 } else
3101 setup[setup_count++] = override;
3102 }
3103 }
3104#endif
3105
3106#if defined(SETUP1)
3107 if (setup_count < ARRAY_SIZE(setup)) {
3108 struct aha152x_setup override = SETUP1;
3109
3110 if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
3111 if (!checksetup(&override)) {
3112 printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
3113 override.io_port,
3114 override.irq,
3115 override.scsiid,
3116 override.reconnect,
3117 override.parity,
3118 override.synchronous,
3119 override.delay,
3120 override.ext_trans);
3121 } else
3122 setup[setup_count++] = override;
3123 }
3124 }
3125#endif
3126
3127#if defined(MODULE)
3128 if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
3129 if(aha152x[0]!=0) {
3130 setup[setup_count].conf = "";
3131 setup[setup_count].io_port = aha152x[0];
3132 setup[setup_count].irq = aha152x[1];
3133 setup[setup_count].scsiid = aha152x[2];
3134 setup[setup_count].reconnect = aha152x[3];
3135 setup[setup_count].parity = aha152x[4];
3136 setup[setup_count].synchronous = aha152x[5];
3137 setup[setup_count].delay = aha152x[6];
3138 setup[setup_count].ext_trans = aha152x[7];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003139 } else if (io[0] != 0 || irq[0] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 if(io[0]!=0) setup[setup_count].io_port = io[0];
3141 if(irq[0]!=0) setup[setup_count].irq = irq[0];
3142
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003143 setup[setup_count].scsiid = scsiid[0];
3144 setup[setup_count].reconnect = reconnect[0];
3145 setup[setup_count].parity = parity[0];
3146 setup[setup_count].synchronous = sync[0];
3147 setup[setup_count].delay = delay[0];
3148 setup[setup_count].ext_trans = exttrans[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 }
3150
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003151 if (checksetup(&setup[setup_count]))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 setup_count++;
3153 else
3154 printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
3155 setup[setup_count].io_port,
3156 setup[setup_count].irq,
3157 setup[setup_count].scsiid,
3158 setup[setup_count].reconnect,
3159 setup[setup_count].parity,
3160 setup[setup_count].synchronous,
3161 setup[setup_count].delay,
3162 setup[setup_count].ext_trans);
3163 }
3164
3165 if (setup_count<ARRAY_SIZE(setup) && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) {
3166 if(aha152x1[0]!=0) {
3167 setup[setup_count].conf = "";
3168 setup[setup_count].io_port = aha152x1[0];
3169 setup[setup_count].irq = aha152x1[1];
3170 setup[setup_count].scsiid = aha152x1[2];
3171 setup[setup_count].reconnect = aha152x1[3];
3172 setup[setup_count].parity = aha152x1[4];
3173 setup[setup_count].synchronous = aha152x1[5];
3174 setup[setup_count].delay = aha152x1[6];
3175 setup[setup_count].ext_trans = aha152x1[7];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003176 } else if (io[1] != 0 || irq[1] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 if(io[1]!=0) setup[setup_count].io_port = io[1];
3178 if(irq[1]!=0) setup[setup_count].irq = irq[1];
3179
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003180 setup[setup_count].scsiid = scsiid[1];
3181 setup[setup_count].reconnect = reconnect[1];
3182 setup[setup_count].parity = parity[1];
3183 setup[setup_count].synchronous = sync[1];
3184 setup[setup_count].delay = delay[1];
3185 setup[setup_count].ext_trans = exttrans[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 }
3187 if (checksetup(&setup[setup_count]))
3188 setup_count++;
3189 else
3190 printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
3191 setup[setup_count].io_port,
3192 setup[setup_count].irq,
3193 setup[setup_count].scsiid,
3194 setup[setup_count].reconnect,
3195 setup[setup_count].parity,
3196 setup[setup_count].synchronous,
3197 setup[setup_count].delay,
3198 setup[setup_count].ext_trans);
3199 }
3200#endif
3201
3202#ifdef __ISAPNP__
3203 for(i=0; setup_count<ARRAY_SIZE(setup) && id_table[i].vendor; i++) {
3204 while ( setup_count<ARRAY_SIZE(setup) &&
3205 (dev=pnp_find_dev(NULL, id_table[i].vendor, id_table[i].function, dev)) ) {
3206 if (pnp_device_attach(dev) < 0)
3207 continue;
3208
3209 if (pnp_activate_dev(dev) < 0) {
3210 pnp_device_detach(dev);
3211 continue;
3212 }
3213
3214 if (!pnp_port_valid(dev, 0)) {
3215 pnp_device_detach(dev);
3216 continue;
3217 }
3218
3219 if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
3220 pnp_device_detach(dev);
3221 continue;
3222 }
3223
3224 setup[setup_count].io_port = pnp_port_start(dev, 0);
3225 setup[setup_count].irq = pnp_irq(dev, 0);
3226 setup[setup_count].scsiid = 7;
3227 setup[setup_count].reconnect = 1;
3228 setup[setup_count].parity = 1;
3229 setup[setup_count].synchronous = 1;
3230 setup[setup_count].delay = DELAY_DEFAULT;
3231 setup[setup_count].ext_trans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232#if defined(__ISAPNP__)
3233 pnpdev[setup_count] = dev;
3234#endif
3235 printk (KERN_INFO
3236 "aha152x: found ISAPnP adapter at io=0x%03x, irq=%d\n",
3237 setup[setup_count].io_port, setup[setup_count].irq);
3238 setup_count++;
3239 }
3240 }
3241#endif
3242
3243#if defined(AUTOCONF)
3244 if (setup_count<ARRAY_SIZE(setup)) {
3245#if !defined(SKIP_BIOSTEST)
3246 ok = 0;
3247 for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++) {
3248 void __iomem *p = ioremap(addresses[i], 0x4000);
3249 if (!p)
3250 continue;
3251 for (j = 0; j<ARRAY_SIZE(signatures) && !ok; j++)
3252 ok = check_signature(p + signatures[j].sig_offset,
3253 signatures[j].signature, signatures[j].sig_length);
3254 iounmap(p);
3255 }
3256 if (!ok && setup_count == 0)
James Bottomleyad2fa422008-05-10 08:33:58 -05003257 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
3259 printk(KERN_INFO "aha152x: BIOS test: passed, ");
3260#else
3261 printk(KERN_INFO "aha152x: ");
3262#endif /* !SKIP_BIOSTEST */
3263
3264 ok = 0;
3265 for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
3266 if ((setup_count == 1) && (setup[0].io_port == ports[i]))
3267 continue;
3268
Harvey Harrison9bcf0912008-05-22 15:45:07 -07003269 if (!request_region(ports[i], IO_RANGE, "aha152x")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]);
3271 continue;
3272 }
3273
3274 if (aha152x_porttest(ports[i])) {
3275 setup[setup_count].tc1550 = 0;
3276
3277 conf.cf_port =
3278 (GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
3279 } else if (tc1550_porttest(ports[i])) {
3280 setup[setup_count].tc1550 = 1;
3281
3282 conf.cf_port =
3283 (GETPORT(ports[i] + O_TC_PORTA) << 8) + GETPORT(ports[i] + O_TC_PORTB);
3284 } else {
3285 release_region(ports[i], IO_RANGE);
3286 continue;
3287 }
3288
3289 release_region(ports[i], IO_RANGE);
3290
3291 ok++;
3292 setup[setup_count].io_port = ports[i];
3293 setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
3294 setup[setup_count].scsiid = conf.cf_id;
3295 setup[setup_count].reconnect = conf.cf_tardisc;
3296 setup[setup_count].parity = !conf.cf_parity;
3297 setup[setup_count].synchronous = conf.cf_syncneg;
3298 setup[setup_count].delay = DELAY_DEFAULT;
3299 setup[setup_count].ext_trans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 setup_count++;
3301
3302 }
3303
3304 if (ok)
3305 printk("auto configuration: ok, ");
3306 }
3307#endif
3308
3309 printk("%d controller(s) configured\n", setup_count);
3310
3311 for (i=0; i<setup_count; i++) {
3312 if ( request_region(setup[i].io_port, IO_RANGE, "aha152x") ) {
3313 struct Scsi_Host *shpnt = aha152x_probe_one(&setup[i]);
3314
3315 if( !shpnt ) {
3316 release_region(setup[i].io_port, IO_RANGE);
3317#if defined(__ISAPNP__)
3318 } else if( pnpdev[i] ) {
3319 HOSTDATA(shpnt)->pnpdev=pnpdev[i];
3320 pnpdev[i]=NULL;
3321#endif
3322 }
3323 } else {
3324 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup[i].io_port);
3325 }
3326
3327#if defined(__ISAPNP__)
3328 if( pnpdev[i] )
3329 pnp_device_detach(pnpdev[i]);
3330#endif
3331 }
3332
James Bottomleyad2fa422008-05-10 08:33:58 -05003333 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334}
3335
3336static void __exit aha152x_exit(void)
3337{
James Bottomley64976a02008-05-10 14:08:40 -05003338 struct aha152x_hostdata *hd, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
James Bottomley64976a02008-05-10 14:08:40 -05003340 list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) {
James Bottomley5fcda422006-09-14 17:04:58 -05003341 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
3342
3343 aha152x_release(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 }
3345}
3346
3347module_init(aha152x_init);
3348module_exit(aha152x_exit);
3349
3350#if !defined(MODULE)
3351static int __init aha152x_setup(char *str)
3352{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 int ints[10];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003354
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 get_options(str, ARRAY_SIZE(ints), ints);
3356
3357 if(setup_count>=ARRAY_SIZE(setup)) {
3358 printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
3359 return 1;
3360 }
3361
3362 setup[setup_count].conf = str;
3363 setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
3364 setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
3365 setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
3366 setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
3367 setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
3368 setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
3369 setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
3370 setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 if (ints[0] > 8) { /*}*/
3372 printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
3373 "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 } else {
3375 setup_count++;
3376 return 0;
3377 }
3378
3379 return 1;
3380}
3381__setup("aha152x=", aha152x_setup);
3382#endif
3383
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +02003384#endif /* !AHA152X_PCMCIA */