blob: d8e19afa7a14071aafc7ea44d5fd6913f7436a41 [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
Mauro Carvalho Chehab94b55302020-03-02 09:15:39 +0100223 see Documentation/scsi/aha152x.rst for configuration details
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 SCp.phase : current state of the command */
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300941
Boaz Harrosh73d2cb12007-11-01 18:54:44 +0200942 if ((phase & resetting) || !scsi_sglist(SCpnt)) {
943 SCpnt->SCp.ptr = NULL;
944 SCpnt->SCp.this_residual = 0;
945 scsi_set_resid(SCpnt, 0);
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300946 SCpnt->SCp.buffer = NULL;
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300947 } else {
Boaz Harrosh23385452007-07-29 22:29:02 +0300948 scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
949 SCpnt->SCp.buffer = scsi_sglist(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer);
951 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
Boaz Harrosh66acdb02007-07-29 22:24:09 +0300952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954 DO_LOCK(flags);
955
956#if defined(AHA152X_STAT)
957 HOSTDATA(shpnt)->total_commands++;
958#endif
959
960 /* Turn led on, when this is the first command. */
961 HOSTDATA(shpnt)->commands++;
962 if (HOSTDATA(shpnt)->commands==1)
963 SETPORT(PORTA, 1);
964
965 append_SC(&ISSUE_SC, SCpnt);
966
967 if(!HOSTDATA(shpnt)->in_intr)
968 setup_expected_interrupts(shpnt);
969
970 DO_UNLOCK(flags);
971
972 return 0;
973}
974
975/*
976 * queue a command
977 *
978 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200979static int aha152x_queue_lck(struct scsi_cmnd *SCpnt,
980 void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 return aha152x_internal_queue(SCpnt, NULL, 0, done);
983}
984
Jeff Garzikf2812332010-11-16 02:10:29 -0500985static DEF_SCSI_QCMD(aha152x_queue)
986
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 *
990 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +0200991static void reset_done(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 if(SCSEM(SCpnt)) {
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200994 complete(SCSEM(SCpnt));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 } else {
Christoph Hellwig0f06bb32007-05-13 17:52:12 +0200996 printk(KERN_ERR "aha152x: reset_done w/o completion\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
998}
999
1000/*
1001 * Abort a command
1002 *
1003 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001004static int aha152x_abort(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005{
1006 struct Scsi_Host *shpnt = SCpnt->device->host;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001007 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 unsigned long flags;
1009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 DO_LOCK(flags);
1011
1012 ptr=remove_SC(&ISSUE_SC, SCpnt);
1013
1014 if(ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 HOSTDATA(shpnt)->commands--;
1016 if (!HOSTDATA(shpnt)->commands)
1017 SETPORT(PORTA, 0);
1018 DO_UNLOCK(flags);
1019
1020 kfree(SCpnt->host_scribble);
1021 SCpnt->host_scribble=NULL;
1022
1023 return SUCCESS;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
1026 DO_UNLOCK(flags);
1027
1028 /*
1029 * FIXME:
1030 * for current command: queue ABORT for message out and raise ATN
1031 * for disconnected command: pseudo SC with ABORT message or ABORT on reselection?
1032 *
1033 */
1034
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001035 scmd_printk(KERN_ERR, SCpnt,
1036 "cannot abort running or disconnected command\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
1038 return FAILED;
1039}
1040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041/*
1042 * Reset a device
1043 *
1044 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001045static int aha152x_device_reset(struct scsi_cmnd * SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
1047 struct Scsi_Host *shpnt = SCpnt->device->host;
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001048 DECLARE_COMPLETION(done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 int ret, issued, disconnected;
Christoph Hellwig631c2282006-07-08 20:42:15 +02001050 unsigned char old_cmd_len = SCpnt->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 unsigned long flags;
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001052 unsigned long timeleft;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 if(CURRENT_SC==SCpnt) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001055 scmd_printk(KERN_ERR, SCpnt, "cannot reset current device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 return FAILED;
1057 }
1058
1059 DO_LOCK(flags);
Harvey Harrison172c1222008-04-28 16:50:03 -07001060 issued = remove_SC(&ISSUE_SC, SCpnt) == NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 disconnected = issued && remove_SC(&DISCONNECTED_SC, SCpnt);
1062 DO_UNLOCK(flags);
1063
1064 SCpnt->cmd_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001066 aha152x_internal_queue(SCpnt, &done, resetting, reset_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Christoph Hellwig0f06bb32007-05-13 17:52:12 +02001068 timeleft = wait_for_completion_timeout(&done, 100*HZ);
1069 if (!timeleft) {
1070 /* remove command from issue queue */
1071 DO_LOCK(flags);
1072 remove_SC(&ISSUE_SC, SCpnt);
1073 DO_UNLOCK(flags);
1074 }
Christoph Hellwig631c2282006-07-08 20:42:15 +02001075
1076 SCpnt->cmd_len = old_cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
1078 DO_LOCK(flags);
1079
1080 if(SCpnt->SCp.phase & resetted) {
1081 HOSTDATA(shpnt)->commands--;
1082 if (!HOSTDATA(shpnt)->commands)
1083 SETPORT(PORTA, 0);
1084 kfree(SCpnt->host_scribble);
1085 SCpnt->host_scribble=NULL;
1086
1087 ret = SUCCESS;
1088 } else {
1089 /* requeue */
1090 if(!issued) {
1091 append_SC(&ISSUE_SC, SCpnt);
1092 } else if(disconnected) {
1093 append_SC(&DISCONNECTED_SC, SCpnt);
1094 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 ret = FAILED;
1097 }
1098
1099 DO_UNLOCK(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 return ret;
1101}
1102
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001103static void free_hard_reset_SCs(struct Scsi_Host *shpnt,
1104 struct scsi_cmnd **SCs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001106 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 ptr=*SCs;
1109 while(ptr) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001110 struct scsi_cmnd *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 if(SCDATA(ptr)) {
1113 next = SCNEXT(ptr);
1114 } else {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001115 scmd_printk(KERN_DEBUG, ptr,
1116 "queue corrupted at %p\n", ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 next = NULL;
1118 }
1119
1120 if (!ptr->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 remove_SC(SCs, ptr);
1122 HOSTDATA(shpnt)->commands--;
1123 kfree(ptr->host_scribble);
1124 ptr->host_scribble=NULL;
1125 }
1126
1127 ptr = next;
1128 }
1129}
1130
1131/*
1132 * Reset the bus
1133 *
Hannes Reinecke819f80c2017-08-25 13:57:16 +02001134 * AIC-6260 has a hard reset (MRST signal), but apparently
1135 * one cannot trigger it via software. So live with
1136 * a soft reset; no-one seemed to have cared.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 */
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001138static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 unsigned long flags;
1141
1142 DO_LOCK(flags);
1143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 free_hard_reset_SCs(shpnt, &ISSUE_SC);
1145 free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 SETPORT(SCSISEQ, SCSIRSTO);
1148 mdelay(256);
1149 SETPORT(SCSISEQ, 0);
1150 mdelay(DELAY);
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 setup_expected_interrupts(shpnt);
1153 if(HOSTDATA(shpnt)->commands==0)
1154 SETPORT(PORTA, 0);
1155
1156 DO_UNLOCK(flags);
1157
1158 return SUCCESS;
1159}
1160
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001161/*
1162 * Reset the bus
1163 *
1164 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001165static int aha152x_bus_reset(struct scsi_cmnd *SCpnt)
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001166{
1167 return aha152x_bus_reset_host(SCpnt->device->host);
1168}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
1170/*
1171 * Restore default values to the AIC-6260 registers and reset the fifos
1172 *
1173 */
1174static void reset_ports(struct Scsi_Host *shpnt)
1175{
1176 unsigned long flags;
1177
1178 /* disable interrupts */
1179 SETPORT(DMACNTRL0, RSTFIFO);
1180
1181 SETPORT(SCSISEQ, 0);
1182
1183 SETPORT(SXFRCTL1, 0);
1184 SETPORT(SCSISIG, 0);
1185 SETRATE(0);
1186
1187 /* clear all interrupt conditions */
1188 SETPORT(SSTAT0, 0x7f);
1189 SETPORT(SSTAT1, 0xef);
1190
1191 SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);
1192
1193 SETPORT(DMACNTRL0, 0);
1194 SETPORT(DMACNTRL1, 0);
1195
1196 SETPORT(BRSTCNTRL, 0xf1);
1197
1198 /* clear SCSI fifos and transfer count */
1199 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
1200 SETPORT(SXFRCTL0, CH1);
1201
1202 DO_LOCK(flags);
1203 setup_expected_interrupts(shpnt);
1204 DO_UNLOCK(flags);
1205}
1206
1207/*
1208 * Reset the host (bus and controller)
1209 *
1210 */
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001211int aha152x_host_reset_host(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212{
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001213 aha152x_bus_reset_host(shpnt);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001214 reset_ports(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 return SUCCESS;
1217}
1218
1219/*
1220 * Return the "logical geometry"
1221 *
1222 */
1223static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1224 sector_t capacity, int *info_array)
1225{
1226 struct Scsi_Host *shpnt = sdev->host;
1227
1228 /* try default translation */
1229 info_array[0] = 64;
1230 info_array[1] = 32;
1231 info_array[2] = (unsigned long)capacity / (64 * 32);
1232
1233 /* for disks >1GB do some guessing */
1234 if (info_array[2] >= 1024) {
1235 int info[3];
1236
1237 /* try to figure out the geometry from the partition table */
1238 if (scsicam_bios_param(bdev, capacity, info) < 0 ||
1239 !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) {
1240 if (EXT_TRANS) {
1241 printk(KERN_NOTICE
1242 "aha152x: unable to verify geometry for disk with >1GB.\n"
1243 " using extended translation.\n");
1244 info_array[0] = 255;
1245 info_array[1] = 63;
1246 info_array[2] = (unsigned long)capacity / (255 * 63);
1247 } else {
1248 printk(KERN_NOTICE
1249 "aha152x: unable to verify geometry for disk with >1GB.\n"
1250 " Using default translation. Please verify yourself.\n"
1251 " Perhaps you need to enable extended translation in the driver.\n"
Mauro Carvalho Chehab94b55302020-03-02 09:15:39 +01001252 " See Documentation/scsi/aha152x.rst for details.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 }
1254 } else {
1255 info_array[0] = info[0];
1256 info_array[1] = info[1];
1257 info_array[2] = info[2];
1258
1259 if (info[0] == 255 && !EXT_TRANS) {
1260 printk(KERN_NOTICE
1261 "aha152x: current partition table is using extended translation.\n"
1262 " using it also, although it's not explicitly enabled.\n");
1263 }
1264 }
1265 }
1266
1267 return 0;
1268}
1269
1270/*
1271 * Internal done function
1272 *
1273 */
1274static void done(struct Scsi_Host *shpnt, int error)
1275{
1276 if (CURRENT_SC) {
1277 if(DONE_SC)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001278 scmd_printk(KERN_ERR, CURRENT_SC,
1279 "there's already a completed command %p "
1280 "- will cause abort\n", DONE_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 DONE_SC = CURRENT_SC;
1283 CURRENT_SC = NULL;
1284 DONE_SC->result = error;
1285 } else
1286 printk(KERN_ERR "aha152x: done() called outside of command\n");
1287}
1288
1289static struct work_struct aha152x_tq;
1290
1291/*
1292 * Run service completions on the card with interrupts enabled.
1293 *
1294 */
David Howellsc4028952006-11-22 14:57:56 +00001295static void run(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296{
James Bottomley5fcda422006-09-14 17:04:58 -05001297 struct aha152x_hostdata *hd;
1298
1299 list_for_each_entry(hd, &aha152x_host_list, host_list) {
1300 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
1301
1302 is_complete(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 }
1304}
1305
1306/*
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001307 * Interrupt handler
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 *
1309 */
David Howells7d12e782006-10-05 14:55:46 +01001310static irqreturn_t intr(int irqno, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
Jeff Garzike19166d2008-04-18 19:22:52 -04001312 struct Scsi_Host *shpnt = dev_id;
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001313 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 unsigned char rev, dmacntrl0;
1315
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 /*
1317 * Read a couple of registers that are known to not be all 1's. If
1318 * we read all 1's (-1), that means that either:
1319 *
1320 * a. The host adapter chip has gone bad, and we cannot control it,
1321 * OR
1322 * b. The host adapter is a PCMCIA card that has been ejected
1323 *
1324 * In either case, we cannot do anything with the host adapter at
1325 * this point in time. So just ignore the interrupt and return.
1326 * In the latter case, the interrupt might actually be meant for
1327 * someone else sharing this IRQ, and that driver will handle it.
1328 */
1329 rev = GETPORT(REV);
1330 dmacntrl0 = GETPORT(DMACNTRL0);
1331 if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
1332 return IRQ_NONE;
1333
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001334 if( TESTLO(DMASTAT, INTSTAT) )
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001335 return IRQ_NONE;
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001336
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 /* no more interrupts from the controller, while we're busy.
1338 INTEN is restored by the BH handler */
1339 CLRBITS(DMACNTRL0, INTEN);
1340
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001341 DO_LOCK(flags);
1342 if( HOSTDATA(shpnt)->service==0 ) {
1343 HOSTDATA(shpnt)->service=1;
1344
1345 /* Poke the BH handler */
David Howellsc4028952006-11-22 14:57:56 +00001346 INIT_WORK(&aha152x_tq, run);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001347 schedule_work(&aha152x_tq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 }
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01001349 DO_UNLOCK(flags);
1350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return IRQ_HANDLED;
1352}
1353
1354/*
1355 * busfree phase
1356 * - handle completition/disconnection/error of current command
1357 * - start selection for next command (if any)
1358 */
1359static void busfree_run(struct Scsi_Host *shpnt)
1360{
1361 unsigned long flags;
1362#if defined(AHA152X_STAT)
1363 int action=0;
1364#endif
1365
1366 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
1367 SETPORT(SXFRCTL0, CH1);
1368
1369 SETPORT(SSTAT1, CLRBUSFREE);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 if(CURRENT_SC) {
1372#if defined(AHA152X_STAT)
1373 action++;
1374#endif
1375 CURRENT_SC->SCp.phase &= ~syncneg;
1376
1377 if(CURRENT_SC->SCp.phase & completed) {
1378 /* target sent COMMAND COMPLETE */
1379 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1380
1381 } else if(CURRENT_SC->SCp.phase & aborted) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16));
1383
1384 } else if(CURRENT_SC->SCp.phase & resetted) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16));
1386
1387 } else if(CURRENT_SC->SCp.phase & disconnected) {
1388 /* target sent DISCONNECT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389#if defined(AHA152X_STAT)
1390 HOSTDATA(shpnt)->disconnections++;
1391#endif
1392 append_SC(&DISCONNECTED_SC, CURRENT_SC);
1393 CURRENT_SC->SCp.phase |= 1 << 16;
1394 CURRENT_SC = NULL;
1395
1396 } else {
1397 done(shpnt, DID_ERROR << 16);
1398 }
1399#if defined(AHA152X_STAT)
1400 } else {
1401 HOSTDATA(shpnt)->busfree_without_old_command++;
1402#endif
1403 }
1404
1405 DO_LOCK(flags);
1406
1407 if(DONE_SC) {
1408#if defined(AHA152X_STAT)
1409 action++;
1410#endif
1411
1412 if(DONE_SC->SCp.phase & check_condition) {
Christoph Hellwig5e13cdf2006-07-08 20:39:30 +02001413 struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
1414 struct aha152x_scdata *sc = SCDATA(cmd);
1415
Boaz Harrosh73d2cb12007-11-01 18:54:44 +02001416 scsi_eh_restore_cmnd(cmd, &sc->ses);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001418 cmd->SCp.Status = SAM_STAT_CHECK_CONDITION;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420 HOSTDATA(shpnt)->commands--;
1421 if (!HOSTDATA(shpnt)->commands)
1422 SETPORT(PORTA, 0); /* turn led off */
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001423 } else if(DONE_SC->SCp.Status==SAM_STAT_CHECK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424#if defined(AHA152X_STAT)
1425 HOSTDATA(shpnt)->busfree_with_check_condition++;
1426#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
Boaz Harrosh0ceb4792007-07-29 22:22:04 +03001428 if(!(DONE_SC->SCp.phase & not_issued)) {
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001429 struct aha152x_scdata *sc;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001430 struct scsi_cmnd *ptr = DONE_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 DONE_SC=NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001433 sc = SCDATA(ptr);
1434 /* It was allocated in aha152x_internal_queue? */
1435 BUG_ON(!sc);
Boaz Harrosh73d2cb12007-11-01 18:54:44 +02001436 scsi_eh_prep_cmnd(ptr, &sc->ses, NULL, 0, ~0);
Boaz Harrosh45333ff2007-07-29 22:27:06 +03001437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 DO_UNLOCK(flags);
1439 aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done);
1440 DO_LOCK(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 }
1442 }
1443
1444 if(DONE_SC && DONE_SC->scsi_done) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02001445 struct scsi_cmnd *ptr = DONE_SC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 DONE_SC=NULL;
1447
1448 /* turn led off, when no commands are in the driver */
1449 HOSTDATA(shpnt)->commands--;
1450 if (!HOSTDATA(shpnt)->commands)
1451 SETPORT(PORTA, 0); /* turn led off */
1452
1453 if(ptr->scsi_done != reset_done) {
1454 kfree(ptr->host_scribble);
1455 ptr->host_scribble=NULL;
1456 }
1457
1458 DO_UNLOCK(flags);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001459 ptr->scsi_done(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 DO_LOCK(flags);
1461 }
1462
1463 DONE_SC=NULL;
1464#if defined(AHA152X_STAT)
1465 } else {
1466 HOSTDATA(shpnt)->busfree_without_done_command++;
1467#endif
1468 }
1469
1470 if(ISSUE_SC)
1471 CURRENT_SC = remove_first_SC(&ISSUE_SC);
1472
1473 DO_UNLOCK(flags);
1474
1475 if(CURRENT_SC) {
1476#if defined(AHA152X_STAT)
1477 action++;
1478#endif
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001479 CURRENT_SC->SCp.phase |= selecting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
1481 /* clear selection timeout */
1482 SETPORT(SSTAT1, SELTO);
1483
1484 SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->device->id);
1485 SETPORT(SXFRCTL1, (PARITY ? ENSPCHK : 0 ) | ENSTIMER);
1486 SETPORT(SCSISEQ, ENSELO | ENAUTOATNO | (DISCONNECTED_SC ? ENRESELI : 0));
1487 } else {
1488#if defined(AHA152X_STAT)
1489 HOSTDATA(shpnt)->busfree_without_new_command++;
1490#endif
1491 SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
1492 }
1493
1494#if defined(AHA152X_STAT)
1495 if(!action)
1496 HOSTDATA(shpnt)->busfree_without_any_action++;
1497#endif
1498}
1499
1500/*
1501 * Selection done (OUT)
1502 * - queue IDENTIFY message and SDTR to selected target for message out
1503 * (ATN asserted automagically via ENAUTOATNO in busfree())
1504 */
1505static void seldo_run(struct Scsi_Host *shpnt)
1506{
1507 SETPORT(SCSISIG, 0);
1508 SETPORT(SSTAT1, CLRBUSFREE);
1509 SETPORT(SSTAT1, CLRPHASECHG);
1510
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001511 CURRENT_SC->SCp.phase &= ~(selecting|not_issued);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
1513 SETPORT(SCSISEQ, 0);
1514
1515 if (TESTLO(SSTAT0, SELDO)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001516 scmd_printk(KERN_ERR, CURRENT_SC,
1517 "aha152x: passing bus free condition\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 done(shpnt, DID_NO_CONNECT << 16);
1519 return;
1520 }
1521
1522 SETPORT(SSTAT0, CLRSELDO);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
1525
1526 if (CURRENT_SC->SCp.phase & aborting) {
1527 ADDMSGO(ABORT);
1528 } else if (CURRENT_SC->SCp.phase & resetting) {
1529 ADDMSGO(BUS_DEVICE_RESET);
1530 } else if (SYNCNEG==0 && SYNCHRONOUS) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001531 CURRENT_SC->SCp.phase |= syncneg;
Matthew Wilcox6ea3c0b2006-02-07 07:54:46 -07001532 MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 SYNCNEG=1; /* negotiation in progress */
1534 }
1535
1536 SETRATE(SYNCRATE);
1537}
1538
1539/*
1540 * Selection timeout
1541 * - return command to mid-level with failure cause
1542 *
1543 */
1544static void selto_run(struct Scsi_Host *shpnt)
1545{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001546 SETPORT(SCSISEQ, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 SETPORT(SSTAT1, CLRSELTIMO);
1548
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001549 if (!CURRENT_SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001552 CURRENT_SC->SCp.phase &= ~selecting;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001554 if (CURRENT_SC->SCp.phase & aborted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 done(shpnt, DID_ABORT << 16);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001556 else if (TESTLO(SSTAT0, SELINGO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 done(shpnt, DID_BUS_BUSY << 16);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001558 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 /* ARBITRATION won, but SELECTION failed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 done(shpnt, DID_NO_CONNECT << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561}
1562
1563/*
1564 * Selection in done
1565 * - put current command back to issue queue
1566 * (reconnection of a disconnected nexus instead
1567 * of successful selection out)
1568 *
1569 */
1570static void seldi_run(struct Scsi_Host *shpnt)
1571{
1572 int selid;
1573 int target;
1574 unsigned long flags;
1575
1576 SETPORT(SCSISIG, 0);
1577 SETPORT(SSTAT0, CLRSELDI);
1578 SETPORT(SSTAT1, CLRBUSFREE);
1579 SETPORT(SSTAT1, CLRPHASECHG);
1580
1581 if(CURRENT_SC) {
1582 if(!(CURRENT_SC->SCp.phase & not_issued))
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001583 scmd_printk(KERN_ERR, CURRENT_SC,
1584 "command should not have been issued yet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
1586 DO_LOCK(flags);
1587 append_SC(&ISSUE_SC, CURRENT_SC);
1588 DO_UNLOCK(flags);
1589
1590 CURRENT_SC = NULL;
1591 }
1592
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001593 if (!DISCONNECTED_SC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
1596 RECONN_TARGET=-1;
1597
1598 selid = GETPORT(SELID) & ~(1 << shpnt->this_id);
1599
1600 if (selid==0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001601 shost_printk(KERN_INFO, shpnt,
1602 "target id unknown (%02x)\n", selid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 return;
1604 }
1605
1606 for(target=7; !(selid & (1 << target)); target--)
1607 ;
1608
1609 if(selid & ~(1 << target)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001610 shost_printk(KERN_INFO, shpnt,
1611 "multiple targets reconnected (%02x)\n", selid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 }
1613
1614
1615 SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
1616 SETPORT(SCSISEQ, 0);
1617
1618 SETRATE(HOSTDATA(shpnt)->syncrate[target]);
1619
1620 RECONN_TARGET=target;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621}
1622
1623/*
1624 * message in phase
1625 * - handle initial message after reconnection to identify
1626 * reconnecting nexus
1627 * - queue command on DISCONNECTED_SC on DISCONNECT message
1628 * - set completed flag on COMMAND COMPLETE
1629 * (other completition code moved to busfree_run)
1630 * - handle response to SDTR
1631 * - clear synchronous transfer agreements on BUS RESET
1632 *
1633 * FIXME: what about SAVE POINTERS, RESTORE POINTERS?
1634 *
1635 */
1636static void msgi_run(struct Scsi_Host *shpnt)
1637{
1638 for(;;) {
1639 int sstat1 = GETPORT(SSTAT1);
1640
1641 if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT))
1642 return;
1643
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001644 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 ADDMSGI(GETPORT(SCSIDAT));
1648
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 if(!CURRENT_SC) {
1650 if(LASTSTATE!=seldi) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001651 shost_printk(KERN_ERR, shpnt,
1652 "message in w/o current command"
1653 " not after reselection\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 }
1655
1656 /*
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001657 * Handle reselection
1658 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 if(!(MSGI(0) & IDENTIFY_BASE)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001660 shost_printk(KERN_ERR, shpnt,
1661 "target didn't identify after reselection\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 continue;
1663 }
1664
1665 CURRENT_SC = remove_lun_SC(&DISCONNECTED_SC, RECONN_TARGET, MSGI(0) & 0x3f);
1666
1667 if (!CURRENT_SC) {
1668 show_queues(shpnt);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001669 shost_printk(KERN_ERR, shpnt,
1670 "no disconnected command"
1671 " for target %d/%d\n",
1672 RECONN_TARGET, MSGI(0) & 0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 continue;
1674 }
1675
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 CURRENT_SC->SCp.Message = MSGI(0);
1677 CURRENT_SC->SCp.phase &= ~disconnected;
1678
1679 MSGILEN=0;
1680
1681 /* next message if any */
1682 continue;
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
1685 CURRENT_SC->SCp.Message = MSGI(0);
1686
1687 switch (MSGI(0)) {
1688 case DISCONNECT:
1689 if (!RECONNECT)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001690 scmd_printk(KERN_WARNING, CURRENT_SC,
1691 "target was not allowed to disconnect\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
1693 CURRENT_SC->SCp.phase |= disconnected;
1694 break;
1695
1696 case COMMAND_COMPLETE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 CURRENT_SC->SCp.phase |= completed;
1698 break;
1699
1700 case MESSAGE_REJECT:
1701 if (SYNCNEG==1) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001702 scmd_printk(KERN_INFO, CURRENT_SC,
1703 "Synchronous Data Transfer Request"
1704 " was rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 SYNCNEG=2; /* negotiation completed */
1706 } else
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001707 scmd_printk(KERN_INFO, CURRENT_SC,
1708 "inbound message (MESSAGE REJECT)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 break;
1710
1711 case SAVE_POINTERS:
1712 break;
1713
1714 case RESTORE_POINTERS:
1715 break;
1716
1717 case EXTENDED_MESSAGE:
1718 if(MSGILEN<2 || MSGILEN<MSGI(1)+2) {
1719 /* not yet completed */
1720 continue;
1721 }
1722
1723 switch (MSGI(2)) {
1724 case EXTENDED_SDTR:
1725 {
1726 long ticks;
1727
1728 if (MSGI(1) != 3) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001729 scmd_printk(KERN_ERR, CURRENT_SC,
1730 "SDTR message length!=3\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 break;
1732 }
1733
1734 if (!HOSTDATA(shpnt)->synchronous)
1735 break;
1736
1737 printk(INFO_LEAD, CMDINFO(CURRENT_SC));
Matthew Wilcox1abfd372005-12-15 16:22:01 -05001738 spi_print_msg(&MSGI(0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 printk("\n");
1740
1741 ticks = (MSGI(3) * 4 + 49) / 50;
1742
1743 if (syncneg) {
1744 /* negotiation in progress */
1745 if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) {
1746 ADDMSGO(MESSAGE_REJECT);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001747 scmd_printk(KERN_INFO,
1748 CURRENT_SC,
1749 "received Synchronous Data Transfer Request invalid - rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 break;
1751 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
1754 } else if (ticks <= 9 && MSGI(4) >= 1) {
1755 ADDMSGO(EXTENDED_MESSAGE);
1756 ADDMSGO(3);
1757 ADDMSGO(EXTENDED_SDTR);
1758 if (ticks < 4) {
1759 ticks = 4;
1760 ADDMSGO(50);
1761 } else
1762 ADDMSGO(MSGI(3));
1763
1764 if (MSGI(4) > 8)
1765 MSGI(4) = 8;
1766
1767 ADDMSGO(MSGI(4));
1768
1769 SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
1770 } else {
1771 /* requested SDTR is too slow, do it asynchronously */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001772 scmd_printk(KERN_INFO,
1773 CURRENT_SC,
1774 "Synchronous Data Transfer Request too slow - Rejecting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 ADDMSGO(MESSAGE_REJECT);
1776 }
1777
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001778 /* negotiation completed */
1779 SYNCNEG=2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 SETRATE(SYNCRATE);
1781 }
1782 break;
1783
1784 case BUS_DEVICE_RESET:
1785 {
1786 int i;
1787
1788 for(i=0; i<8; i++) {
1789 HOSTDATA(shpnt)->syncrate[i]=0;
1790 HOSTDATA(shpnt)->syncneg[i]=0;
1791 }
1792
1793 }
1794 break;
1795
1796 case EXTENDED_MODIFY_DATA_POINTER:
1797 case EXTENDED_EXTENDED_IDENTIFY:
1798 case EXTENDED_WDTR:
1799 default:
1800 ADDMSGO(MESSAGE_REJECT);
1801 break;
1802 }
1803 break;
1804 }
1805
1806 MSGILEN=0;
1807 }
1808}
1809
1810static void msgi_end(struct Scsi_Host *shpnt)
1811{
1812 if(MSGILEN>0)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001813 scmd_printk(KERN_WARNING, CURRENT_SC,
1814 "target left before message completed (%d)\n",
1815 MSGILEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001817 if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 SETPORT(SCSISIG, P_MSGI | SIG_ATNO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819}
1820
1821/*
1822 * message out phase
1823 *
1824 */
1825static void msgo_init(struct Scsi_Host *shpnt)
1826{
1827 if(MSGOLEN==0) {
1828 if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) {
1829 ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
1830 } else {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001831 scmd_printk(KERN_INFO, CURRENT_SC,
1832 "unexpected MESSAGE OUT phase; rejecting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 ADDMSGO(MESSAGE_REJECT);
1834 }
1835 }
1836
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837}
1838
1839/*
1840 * message out phase
1841 *
1842 */
1843static void msgo_run(struct Scsi_Host *shpnt)
1844{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 while(MSGO_I<MSGOLEN) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001846 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
1849 if (MSGO_I==MSGOLEN-1) {
1850 /* Leave MESSAGE OUT after transfer */
1851 SETPORT(SSTAT1, CLRATNO);
1852 }
1853
1854
1855 if (MSGO(MSGO_I) & IDENTIFY_BASE)
1856 CURRENT_SC->SCp.phase |= identified;
1857
1858 if (MSGO(MSGO_I)==ABORT)
1859 CURRENT_SC->SCp.phase |= aborted;
1860
1861 if (MSGO(MSGO_I)==BUS_DEVICE_RESET)
1862 CURRENT_SC->SCp.phase |= resetted;
1863
1864 SETPORT(SCSIDAT, MSGO(MSGO_I++));
1865 }
1866}
1867
1868static void msgo_end(struct Scsi_Host *shpnt)
1869{
1870 if(MSGO_I<MSGOLEN) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001871 scmd_printk(KERN_ERR, CURRENT_SC,
1872 "message sent incompletely (%d/%d)\n",
1873 MSGO_I, MSGOLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if(SYNCNEG==1) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001875 scmd_printk(KERN_INFO, CURRENT_SC,
1876 "Synchronous Data Transfer Request was rejected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 SYNCNEG=2;
1878 }
1879 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001880
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 MSGO_I = 0;
1882 MSGOLEN = 0;
1883}
1884
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001885/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 * command phase
1887 *
1888 */
1889static void cmd_init(struct Scsi_Host *shpnt)
1890{
1891 if (CURRENT_SC->SCp.sent_command) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001892 scmd_printk(KERN_ERR, CURRENT_SC,
1893 "command already sent\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 done(shpnt, DID_ERROR << 16);
1895 return;
1896 }
1897
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 CMD_I=0;
1899}
1900
1901/*
1902 * command phase
1903 *
1904 */
1905static void cmd_run(struct Scsi_Host *shpnt)
1906{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 while(CMD_I<CURRENT_SC->cmd_len) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001908 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
1911 SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]);
1912 }
1913}
1914
1915static void cmd_end(struct Scsi_Host *shpnt)
1916{
1917 if(CMD_I<CURRENT_SC->cmd_len)
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001918 scmd_printk(KERN_ERR, CURRENT_SC,
1919 "command sent incompletely (%d/%d)\n",
1920 CMD_I, CURRENT_SC->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 else
1922 CURRENT_SC->SCp.sent_command++;
1923}
1924
1925/*
1926 * status phase
1927 *
1928 */
1929static void status_run(struct Scsi_Host *shpnt)
1930{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001931 if (TESTLO(SSTAT0, SPIORDY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933
1934 CURRENT_SC->SCp.Status = GETPORT(SCSIDAT);
1935
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936}
1937
1938/*
1939 * data in phase
1940 *
1941 */
1942static void datai_init(struct Scsi_Host *shpnt)
1943{
1944 SETPORT(DMACNTRL0, RSTFIFO);
1945 SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
1946
1947 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
1948 SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
1949
1950 SETPORT(SIMODE0, 0);
1951 SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE);
1952
1953 DATA_LEN=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954}
1955
1956static void datai_run(struct Scsi_Host *shpnt)
1957{
1958 unsigned long the_time;
1959 int fifodata, data_count;
1960
1961 /*
1962 * loop while the phase persists or the fifos are not empty
1963 *
1964 */
1965 while(TESTLO(DMASTAT, INTSTAT) || TESTLO(DMASTAT, DFIFOEMP) || TESTLO(SSTAT2, SEMPTY)) {
1966 /* FIXME: maybe this should be done by setting up
1967 * STCNT to trigger ENSWRAP interrupt, instead of
1968 * polling for DFIFOFULL
1969 */
1970 the_time=jiffies + 100*HZ;
1971 while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time))
1972 barrier();
1973
1974 if(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001975 scmd_printk(KERN_ERR, CURRENT_SC, "datai timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 break;
1977 }
1978
1979 if(TESTHI(DMASTAT, DFIFOFULL)) {
1980 fifodata = 128;
1981 } else {
1982 the_time=jiffies + 100*HZ;
1983 while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
1984 barrier();
1985
1986 if(TESTLO(SSTAT2, SEMPTY)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001987 scmd_printk(KERN_ERR, CURRENT_SC,
1988 "datai sempty timeout");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 break;
1990 }
1991
1992 fifodata = GETPORT(FIFOSTAT);
1993 }
1994
1995 if(CURRENT_SC->SCp.this_residual>0) {
1996 while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02001997 data_count = fifodata > CURRENT_SC->SCp.this_residual ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 CURRENT_SC->SCp.this_residual :
1999 fifodata;
2000 fifodata -= data_count;
2001
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002002 if (data_count & 1) {
2003 SETPORT(DMACNTRL0, ENDMA|_8BIT);
2004 *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
2005 CURRENT_SC->SCp.this_residual--;
2006 DATA_LEN++;
2007 SETPORT(DMACNTRL0, ENDMA);
2008 }
2009
2010 if (data_count > 1) {
2011 data_count >>= 1;
2012 insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
2013 CURRENT_SC->SCp.ptr += 2 * data_count;
2014 CURRENT_SC->SCp.this_residual -= 2 * data_count;
2015 DATA_LEN += 2 * data_count;
2016 }
2017
2018 if (CURRENT_SC->SCp.this_residual == 0 &&
Finn Thaina7a253b2019-06-18 09:37:52 +08002019 !sg_is_last(CURRENT_SC->SCp.buffer)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002020 /* advance to next buffer */
Finn Thaina7a253b2019-06-18 09:37:52 +08002021 CURRENT_SC->SCp.buffer = sg_next(CURRENT_SC->SCp.buffer);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002022 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
2023 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
2024 }
2025 }
2026 } else if (fifodata > 0) {
2027 scmd_printk(KERN_ERR, CURRENT_SC,
2028 "no buffers left for %d(%d) bytes"
2029 " (data overrun!?)\n",
2030 fifodata, GETPORT(FIFOSTAT));
2031 SETPORT(DMACNTRL0, ENDMA|_8BIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 while(fifodata>0) {
Lee Jones3c011792020-07-07 15:00:51 +01002033 GETPORT(DATAPORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 fifodata--;
2035 DATA_LEN++;
2036 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002037 SETPORT(DMACNTRL0, ENDMA|_8BIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 }
2039 }
2040
2041 if(TESTLO(DMASTAT, INTSTAT) ||
2042 TESTLO(DMASTAT, DFIFOEMP) ||
2043 TESTLO(SSTAT2, SEMPTY) ||
2044 GETPORT(FIFOSTAT)>0) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002045 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 * something went wrong, if there's something left in the fifos
2047 * or the phase didn't change
2048 */
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002049 scmd_printk(KERN_ERR, CURRENT_SC,
2050 "fifos should be empty and phase should have changed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 }
2052
2053 if(DATA_LEN!=GETSTCNT()) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002054 scmd_printk(KERN_ERR, CURRENT_SC,
2055 "manual transfer count differs from automatic "
2056 "(count=%d;stcnt=%d;diff=%d;fifostat=%d)",
2057 DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN,
2058 GETPORT(FIFOSTAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 mdelay(10000);
2060 }
2061}
2062
2063static void datai_end(struct Scsi_Host *shpnt)
2064{
Boaz Harrosh23385452007-07-29 22:29:02 +03002065 CMD_INC_RESID(CURRENT_SC, -GETSTCNT());
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
2068 SETPORT(DMACNTRL0, 0);
2069}
2070
2071/*
2072 * data out phase
2073 *
2074 */
2075static void datao_init(struct Scsi_Host *shpnt)
2076{
2077 SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO);
2078 SETPORT(DMACNTRL0, WRITE_READ | ENDMA);
2079
2080 SETPORT(SXFRCTL0, CH1|CLRSTCNT);
2081 SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
2082
2083 SETPORT(SIMODE0, 0);
2084 SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE );
2085
Boaz Harrosh23385452007-07-29 22:29:02 +03002086 DATA_LEN = scsi_get_resid(CURRENT_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087}
2088
2089static void datao_run(struct Scsi_Host *shpnt)
2090{
2091 unsigned long the_time;
2092 int data_count;
2093
2094 /* until phase changes or all data sent */
2095 while(TESTLO(DMASTAT, INTSTAT) && CURRENT_SC->SCp.this_residual>0) {
2096 data_count = 128;
2097 if(data_count > CURRENT_SC->SCp.this_residual)
2098 data_count=CURRENT_SC->SCp.this_residual;
2099
2100 if(TESTLO(DMASTAT, DFIFOEMP)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002101 scmd_printk(KERN_ERR, CURRENT_SC,
2102 "datao fifo not empty (%d)",
2103 GETPORT(FIFOSTAT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 break;
2105 }
2106
2107 if(data_count & 1) {
2108 SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT);
2109 SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
2110 CURRENT_SC->SCp.this_residual--;
Boaz Harrosh23385452007-07-29 22:29:02 +03002111 CMD_INC_RESID(CURRENT_SC, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 SETPORT(DMACNTRL0,WRITE_READ|ENDMA);
2113 }
2114
2115 if(data_count > 1) {
2116 data_count >>= 1;
2117 outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
2118 CURRENT_SC->SCp.ptr += 2 * data_count;
2119 CURRENT_SC->SCp.this_residual -= 2 * data_count;
Boaz Harrosh23385452007-07-29 22:29:02 +03002120 CMD_INC_RESID(CURRENT_SC, -2 * data_count);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
Finn Thaina7a253b2019-06-18 09:37:52 +08002123 if (CURRENT_SC->SCp.this_residual == 0 &&
2124 !sg_is_last(CURRENT_SC->SCp.buffer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 /* advance to next buffer */
Finn Thaina7a253b2019-06-18 09:37:52 +08002126 CURRENT_SC->SCp.buffer = sg_next(CURRENT_SC->SCp.buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
2128 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
2129 }
2130
2131 the_time=jiffies + 100*HZ;
2132 while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
2133 barrier();
2134
2135 if(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002136 scmd_printk(KERN_ERR, CURRENT_SC, "dataout timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 break;
2138 }
2139 }
2140}
2141
2142static void datao_end(struct Scsi_Host *shpnt)
2143{
2144 if(TESTLO(DMASTAT, DFIFOEMP)) {
Finn Thaina7a253b2019-06-18 09:37:52 +08002145 u32 datao_cnt = GETSTCNT();
2146 int datao_out = DATA_LEN - scsi_get_resid(CURRENT_SC);
2147 int done;
2148 struct scatterlist *sg = scsi_sglist(CURRENT_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
Finn Thaina7a253b2019-06-18 09:37:52 +08002150 CMD_INC_RESID(CURRENT_SC, datao_out - datao_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Finn Thaina7a253b2019-06-18 09:37:52 +08002152 done = scsi_bufflen(CURRENT_SC) - scsi_get_resid(CURRENT_SC);
2153 /* Locate the first SG entry not yet sent */
2154 while (done > 0 && !sg_is_last(sg)) {
2155 if (done < sg->length)
2156 break;
2157 done -= sg->length;
2158 sg = sg_next(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 }
Finn Thaina7a253b2019-06-18 09:37:52 +08002160
2161 CURRENT_SC->SCp.buffer = sg;
2162 CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) + done;
2163 CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length -
2164 done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 }
2166
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
2168 SETPORT(SXFRCTL0, CH1);
2169
2170 SETPORT(DMACNTRL0, 0);
2171}
2172
2173/*
2174 * figure out what state we're in
2175 *
2176 */
2177static int update_state(struct Scsi_Host *shpnt)
2178{
2179 int dataphase=0;
2180 unsigned int stat0 = GETPORT(SSTAT0);
2181 unsigned int stat1 = GETPORT(SSTAT1);
2182
2183 PREVSTATE = STATE;
2184 STATE=unknown;
2185
2186 if(stat1 & SCSIRSTI) {
2187 STATE=rsti;
2188 SETPORT(SCSISEQ,0);
2189 SETPORT(SSTAT1,SCSIRSTI);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002190 } else if (stat0 & SELDI && PREVSTATE == busfree) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 STATE=seldi;
2192 } else if(stat0 & SELDO && CURRENT_SC && (CURRENT_SC->SCp.phase & selecting)) {
2193 STATE=seldo;
2194 } else if(stat1 & SELTO) {
2195 STATE=selto;
2196 } else if(stat1 & BUSFREE) {
2197 STATE=busfree;
2198 SETPORT(SSTAT1,BUSFREE);
2199 } else if(stat1 & SCSIPERR) {
2200 STATE=parerr;
2201 SETPORT(SSTAT1,SCSIPERR);
2202 } else if(stat1 & REQINIT) {
2203 switch(GETPORT(SCSISIG) & P_MASK) {
2204 case P_MSGI: STATE=msgi; break;
2205 case P_MSGO: STATE=msgo; break;
2206 case P_DATAO: STATE=datao; break;
2207 case P_DATAI: STATE=datai; break;
2208 case P_STATUS: STATE=status; break;
2209 case P_CMD: STATE=cmd; break;
2210 }
2211 dataphase=1;
2212 }
2213
2214 if((stat0 & SELDI) && STATE!=seldi && !dataphase) {
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002215 scmd_printk(KERN_INFO, CURRENT_SC, "reselection missed?");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 }
2217
2218 if(STATE!=PREVSTATE) {
2219 LASTSTATE=PREVSTATE;
2220 }
2221
2222 return dataphase;
2223}
2224
2225/*
2226 * handle parity error
2227 *
2228 * FIXME: in which phase?
2229 *
2230 */
2231static void parerr_run(struct Scsi_Host *shpnt)
2232{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002233 scmd_printk(KERN_ERR, CURRENT_SC, "parity error\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 done(shpnt, DID_PARITY << 16);
2235}
2236
2237/*
2238 * handle reset in
2239 *
2240 */
2241static void rsti_run(struct Scsi_Host *shpnt)
2242{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002243 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002245 shost_printk(KERN_NOTICE, shpnt, "scsi reset in\n");
2246
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 ptr=DISCONNECTED_SC;
2248 while(ptr) {
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002249 struct scsi_cmnd *next = SCNEXT(ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
2251 if (!ptr->device->soft_reset) {
2252 remove_SC(&DISCONNECTED_SC, ptr);
2253
2254 kfree(ptr->host_scribble);
2255 ptr->host_scribble=NULL;
2256
2257 ptr->result = DID_RESET << 16;
2258 ptr->scsi_done(ptr);
2259 }
2260
2261 ptr = next;
2262 }
2263
2264 if(CURRENT_SC && !CURRENT_SC->device->soft_reset)
2265 done(shpnt, DID_RESET << 16 );
2266}
2267
2268
2269/*
2270 * bottom-half handler
2271 *
2272 */
2273static void is_complete(struct Scsi_Host *shpnt)
2274{
2275 int dataphase;
2276 unsigned long flags;
2277 int pending;
2278
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01002279 if(!shpnt)
2280 return;
2281
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 DO_LOCK(flags);
Jürgen E. Fischere2482fa2006-02-19 00:31:51 +01002283
2284 if( HOSTDATA(shpnt)->service==0 ) {
2285 DO_UNLOCK(flags);
2286 return;
2287 }
2288
2289 HOSTDATA(shpnt)->service = 0;
2290
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 if(HOSTDATA(shpnt)->in_intr) {
2292 DO_UNLOCK(flags);
2293 /* aha152x_error never returns.. */
2294 aha152x_error(shpnt, "bottom-half already running!?");
2295 }
2296 HOSTDATA(shpnt)->in_intr++;
2297
2298 /*
2299 * loop while there are interrupt conditions pending
2300 *
2301 */
2302 do {
2303 unsigned long start = jiffies;
2304 DO_UNLOCK(flags);
2305
2306 dataphase=update_state(shpnt);
2307
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 /*
2309 * end previous state
2310 *
2311 */
2312 if(PREVSTATE!=STATE && states[PREVSTATE].end)
2313 states[PREVSTATE].end(shpnt);
2314
2315 /*
2316 * disable SPIO mode if previous phase used it
2317 * and this one doesn't
2318 *
2319 */
2320 if(states[PREVSTATE].spio && !states[STATE].spio) {
2321 SETPORT(SXFRCTL0, CH1);
2322 SETPORT(DMACNTRL0, 0);
2323 if(CURRENT_SC)
2324 CURRENT_SC->SCp.phase &= ~spiordy;
2325 }
2326
2327 /*
2328 * accept current dataphase phase
2329 *
2330 */
2331 if(dataphase) {
2332 SETPORT(SSTAT0, REQINIT);
2333 SETPORT(SCSISIG, GETPORT(SCSISIG) & P_MASK);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002334 SETPORT(SSTAT1, PHASECHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 /*
2338 * enable SPIO mode if previous didn't use it
2339 * and this one does
2340 *
2341 */
2342 if(!states[PREVSTATE].spio && states[STATE].spio) {
2343 SETPORT(DMACNTRL0, 0);
2344 SETPORT(SXFRCTL0, CH1|SPIOEN);
2345 if(CURRENT_SC)
2346 CURRENT_SC->SCp.phase |= spiordy;
2347 }
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002348
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 /*
2350 * initialize for new state
2351 *
2352 */
2353 if(PREVSTATE!=STATE && states[STATE].init)
2354 states[STATE].init(shpnt);
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 /*
2357 * handle current state
2358 *
2359 */
2360 if(states[STATE].run)
2361 states[STATE].run(shpnt);
2362 else
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002363 scmd_printk(KERN_ERR, CURRENT_SC,
2364 "unexpected state (%x)\n", STATE);
2365
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 /*
2367 * setup controller to interrupt on
2368 * the next expected condition and
2369 * loop if it's already there
2370 *
2371 */
2372 DO_LOCK(flags);
2373 pending=setup_expected_interrupts(shpnt);
2374#if defined(AHA152X_STAT)
2375 HOSTDATA(shpnt)->count[STATE]++;
2376 if(PREVSTATE!=STATE)
2377 HOSTDATA(shpnt)->count_trans[STATE]++;
2378 HOSTDATA(shpnt)->time[STATE] += jiffies-start;
2379#endif
2380
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 } while(pending);
2382
2383 /*
2384 * enable interrupts and leave bottom-half
2385 *
2386 */
2387 HOSTDATA(shpnt)->in_intr--;
2388 SETBITS(DMACNTRL0, INTEN);
2389 DO_UNLOCK(flags);
2390}
2391
2392
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002393/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 * Dump the current driver status and panic
2395 */
2396static void aha152x_error(struct Scsi_Host *shpnt, char *msg)
2397{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002398 shost_printk(KERN_EMERG, shpnt, "%s\n", msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 show_queues(shpnt);
2400 panic("aha152x panic\n");
2401}
2402
2403/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 * display enabled interrupts
2405 */
2406static void disp_enintr(struct Scsi_Host *shpnt)
2407{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002408 int s0, s1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002410 s0 = GETPORT(SIMODE0);
2411 s1 = GETPORT(SIMODE1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002413 shost_printk(KERN_DEBUG, shpnt,
2414 "enabled interrupts (%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
2415 (s0 & ENSELDO) ? "ENSELDO " : "",
2416 (s0 & ENSELDI) ? "ENSELDI " : "",
2417 (s0 & ENSELINGO) ? "ENSELINGO " : "",
2418 (s0 & ENSWRAP) ? "ENSWRAP " : "",
2419 (s0 & ENSDONE) ? "ENSDONE " : "",
2420 (s0 & ENSPIORDY) ? "ENSPIORDY " : "",
2421 (s0 & ENDMADONE) ? "ENDMADONE " : "",
2422 (s1 & ENSELTIMO) ? "ENSELTIMO " : "",
2423 (s1 & ENATNTARG) ? "ENATNTARG " : "",
2424 (s1 & ENPHASEMIS) ? "ENPHASEMIS " : "",
2425 (s1 & ENBUSFREE) ? "ENBUSFREE " : "",
2426 (s1 & ENSCSIPERR) ? "ENSCSIPERR " : "",
2427 (s1 & ENPHASECHG) ? "ENPHASECHG " : "",
2428 (s1 & ENREQINIT) ? "ENREQINIT " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429}
2430
2431/*
2432 * Show the command data of a command
2433 */
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002434static void show_command(struct scsi_cmnd *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435{
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002436 scsi_print_command(ptr);
2437 scmd_printk(KERN_DEBUG, ptr,
2438 "request_bufflen=%d; resid=%d; "
2439 "phase |%s%s%s%s%s%s%s%s%s; next=0x%p",
2440 scsi_bufflen(ptr), scsi_get_resid(ptr),
2441 (ptr->SCp.phase & not_issued) ? "not issued|" : "",
2442 (ptr->SCp.phase & selecting) ? "selecting|" : "",
2443 (ptr->SCp.phase & identified) ? "identified|" : "",
2444 (ptr->SCp.phase & disconnected) ? "disconnected|" : "",
2445 (ptr->SCp.phase & completed) ? "completed|" : "",
2446 (ptr->SCp.phase & spiordy) ? "spiordy|" : "",
2447 (ptr->SCp.phase & syncneg) ? "syncneg|" : "",
2448 (ptr->SCp.phase & aborted) ? "aborted|" : "",
2449 (ptr->SCp.phase & resetted) ? "resetted|" : "",
2450 (SCDATA(ptr)) ? SCNEXT(ptr) : NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451}
2452
2453/*
2454 * Dump the queued data
2455 */
2456static void show_queues(struct Scsi_Host *shpnt)
2457{
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002458 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 unsigned long flags;
2460
2461 DO_LOCK(flags);
2462 printk(KERN_DEBUG "\nqueue status:\nissue_SC:\n");
2463 for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
2464 show_command(ptr);
2465 DO_UNLOCK(flags);
2466
2467 printk(KERN_DEBUG "current_SC:\n");
2468 if (CURRENT_SC)
2469 show_command(CURRENT_SC);
2470 else
2471 printk(KERN_DEBUG "none\n");
2472
2473 printk(KERN_DEBUG "disconnected_SC:\n");
2474 for (ptr = DISCONNECTED_SC; ptr; ptr = SCDATA(ptr) ? SCNEXT(ptr) : NULL)
2475 show_command(ptr);
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 disp_enintr(shpnt);
2478}
2479
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002480static void get_command(struct seq_file *m, struct scsi_cmnd * ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 int i;
2483
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002484 seq_printf(m, "%p: target=%d; lun=%d; cmnd=( ",
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002485 ptr, ptr->device->id, (u8)ptr->device->lun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
2487 for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002488 seq_printf(m, "0x%02x ", ptr->cmnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002490 seq_printf(m, "); resid=%d; residual=%d; buffers=%d; phase |",
Boaz Harrosh23385452007-07-29 22:29:02 +03002491 scsi_get_resid(ptr), ptr->SCp.this_residual,
Finn Thaina7a253b2019-06-18 09:37:52 +08002492 sg_nents(ptr->SCp.buffer) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 if (ptr->SCp.phase & not_issued)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002495 seq_puts(m, "not issued|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 if (ptr->SCp.phase & selecting)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002497 seq_puts(m, "selecting|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 if (ptr->SCp.phase & disconnected)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002499 seq_puts(m, "disconnected|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 if (ptr->SCp.phase & aborted)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002501 seq_puts(m, "aborted|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 if (ptr->SCp.phase & identified)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002503 seq_puts(m, "identified|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 if (ptr->SCp.phase & completed)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002505 seq_puts(m, "completed|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 if (ptr->SCp.phase & spiordy)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002507 seq_puts(m, "spiordy|");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 if (ptr->SCp.phase & syncneg)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002509 seq_puts(m, "syncneg|");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002510 seq_printf(m, "; next=0x%p\n", SCNEXT(ptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511}
2512
Al Viro275084c2013-03-31 03:12:15 -04002513static void get_ports(struct seq_file *m, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 int s;
2516
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002517 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 -07002518
2519 s = GETPORT(SCSISEQ);
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002520 seq_puts(m, "SCSISEQ( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 if (s & TEMODEO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002522 seq_puts(m, "TARGET MODE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 if (s & ENSELO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002524 seq_puts(m, "SELO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 if (s & ENSELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002526 seq_puts(m, "SELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 if (s & ENRESELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002528 seq_puts(m, "RESELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 if (s & ENAUTOATNO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002530 seq_puts(m, "AUTOATNO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 if (s & ENAUTOATNI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002532 seq_puts(m, "AUTOATNI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 if (s & ENAUTOATNP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002534 seq_puts(m, "AUTOATNP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 if (s & SCSIRSTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002536 seq_puts(m, "SCSIRSTO ");
2537 seq_puts(m, ");");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002539 seq_puts(m, " SCSISIG(");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 s = GETPORT(SCSISIG);
2541 switch (s & P_MASK) {
2542 case P_DATAO:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002543 seq_puts(m, "DATA OUT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 break;
2545 case P_DATAI:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002546 seq_puts(m, "DATA IN");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 break;
2548 case P_CMD:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002549 seq_puts(m, "COMMAND");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 break;
2551 case P_STATUS:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002552 seq_puts(m, "STATUS");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 break;
2554 case P_MSGO:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002555 seq_puts(m, "MESSAGE OUT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 break;
2557 case P_MSGI:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002558 seq_puts(m, "MESSAGE IN");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 break;
2560 default:
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002561 seq_puts(m, "*invalid*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 break;
2563 }
2564
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002565 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002567 seq_printf(m, "INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002569 seq_puts(m, "SSTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 s = GETPORT(SSTAT0);
2571 if (s & TARGET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002572 seq_puts(m, "TARGET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 if (s & SELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002574 seq_puts(m, "SELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 if (s & SELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002576 seq_puts(m, "SELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 if (s & SELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002578 seq_puts(m, "SELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 if (s & SWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002580 seq_puts(m, "SWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 if (s & SDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002582 seq_puts(m, "SDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 if (s & SPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002584 seq_puts(m, "SPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 if (s & DMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002586 seq_puts(m, "DMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
2588 s = GETPORT(SSTAT1);
2589 if (s & SELTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002590 seq_puts(m, "SELTO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 if (s & ATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002592 seq_puts(m, "ATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 if (s & SCSIRSTI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002594 seq_puts(m, "SCSIRSTI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 if (s & PHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002596 seq_puts(m, "PHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 if (s & BUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002598 seq_puts(m, "BUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 if (s & SCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002600 seq_puts(m, "SCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if (s & PHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002602 seq_puts(m, "PHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 if (s & REQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002604 seq_puts(m, "REQINIT ");
2605 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002608 seq_puts(m, "SSTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
2610 s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
2611
2612 if (s & TARGET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002613 seq_puts(m, "TARGET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 if (s & SELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002615 seq_puts(m, "SELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 if (s & SELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002617 seq_puts(m, "SELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 if (s & SELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002619 seq_puts(m, "SELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 if (s & SWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002621 seq_puts(m, "SWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 if (s & SDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002623 seq_puts(m, "SDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 if (s & SPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002625 seq_puts(m, "SPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 if (s & DMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002627 seq_puts(m, "DMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628
2629 s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
2630
2631 if (s & SELTO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002632 seq_puts(m, "SELTO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 if (s & ATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002634 seq_puts(m, "ATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 if (s & SCSIRSTI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002636 seq_puts(m, "SCSIRSTI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 if (s & PHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002638 seq_puts(m, "PHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 if (s & BUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002640 seq_puts(m, "BUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 if (s & SCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002642 seq_puts(m, "SCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 if (s & PHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002644 seq_puts(m, "PHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 if (s & REQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002646 seq_puts(m, "REQINIT ");
2647 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002649 seq_puts(m, "SXFRCTL0( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
2651 s = GETPORT(SXFRCTL0);
2652 if (s & SCSIEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002653 seq_puts(m, "SCSIEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 if (s & DMAEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002655 seq_puts(m, "DMAEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (s & CH1)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002657 seq_puts(m, "CH1 ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 if (s & CLRSTCNT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002659 seq_puts(m, "CLRSTCNT ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 if (s & SPIOEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002661 seq_puts(m, "SPIOEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 if (s & CLRCH1)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002663 seq_puts(m, "CLRCH1 ");
2664 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002666 seq_puts(m, "SIGNAL( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
2668 s = GETPORT(SCSISIG);
2669 if (s & SIG_ATNI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002670 seq_puts(m, "ATNI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 if (s & SIG_SELI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002672 seq_puts(m, "SELI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 if (s & SIG_BSYI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002674 seq_puts(m, "BSYI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 if (s & SIG_REQI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002676 seq_puts(m, "REQI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 if (s & SIG_ACKI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002678 seq_puts(m, "ACKI ");
2679 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002681 seq_printf(m, "SELID(%02x), ", GETPORT(SELID));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002683 seq_printf(m, "STCNT(%d), ", GETSTCNT());
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002685 seq_puts(m, "SSTAT2( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
2687 s = GETPORT(SSTAT2);
2688 if (s & SOFFSET)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002689 seq_puts(m, "SOFFSET ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 if (s & SEMPTY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002691 seq_puts(m, "SEMPTY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 if (s & SFULL)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002693 seq_puts(m, "SFULL ");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002694 seq_printf(m, "); SFCNT (%d); ", s & (SFULL | SFCNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695
2696 s = GETPORT(SSTAT3);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002697 seq_printf(m, "SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002699 seq_puts(m, "SSTAT4( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 s = GETPORT(SSTAT4);
2701 if (s & SYNCERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002702 seq_puts(m, "SYNCERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 if (s & FWERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002704 seq_puts(m, "FWERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 if (s & FRERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002706 seq_puts(m, "FRERR ");
2707 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002709 seq_puts(m, "DMACNTRL0( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 s = GETPORT(DMACNTRL0);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002711 seq_printf(m, "%s ", s & _8BIT ? "8BIT" : "16BIT");
2712 seq_printf(m, "%s ", s & DMA ? "DMA" : "PIO");
2713 seq_printf(m, "%s ", s & WRITE_READ ? "WRITE" : "READ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 if (s & ENDMA)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002715 seq_puts(m, "ENDMA ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 if (s & INTEN)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002717 seq_puts(m, "INTEN ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 if (s & RSTFIFO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002719 seq_puts(m, "RSTFIFO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 if (s & SWINT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002721 seq_puts(m, "SWINT ");
2722 seq_puts(m, "); ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002724 seq_puts(m, "DMASTAT( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 s = GETPORT(DMASTAT);
2726 if (s & ATDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002727 seq_puts(m, "ATDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 if (s & WORDRDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002729 seq_puts(m, "WORDRDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 if (s & DFIFOFULL)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002731 seq_puts(m, "DFIFOFULL ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 if (s & DFIFOEMP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002733 seq_puts(m, "DFIFOEMP ");
2734 seq_puts(m, ")\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002736 seq_puts(m, "enabled interrupts( ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738 s = GETPORT(SIMODE0);
2739 if (s & ENSELDO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002740 seq_puts(m, "ENSELDO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 if (s & ENSELDI)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002742 seq_puts(m, "ENSELDI ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 if (s & ENSELINGO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002744 seq_puts(m, "ENSELINGO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 if (s & ENSWRAP)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002746 seq_puts(m, "ENSWRAP ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 if (s & ENSDONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002748 seq_puts(m, "ENSDONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 if (s & ENSPIORDY)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002750 seq_puts(m, "ENSPIORDY ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 if (s & ENDMADONE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002752 seq_puts(m, "ENDMADONE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
2754 s = GETPORT(SIMODE1);
2755 if (s & ENSELTIMO)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002756 seq_puts(m, "ENSELTIMO ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 if (s & ENATNTARG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002758 seq_puts(m, "ENATNTARG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 if (s & ENPHASEMIS)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002760 seq_puts(m, "ENPHASEMIS ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 if (s & ENBUSFREE)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002762 seq_puts(m, "ENBUSFREE ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 if (s & ENSCSIPERR)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002764 seq_puts(m, "ENSCSIPERR ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 if (s & ENPHASECHG)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002766 seq_puts(m, "ENPHASECHG ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 if (s & ENREQINIT)
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002768 seq_puts(m, "ENREQINIT ");
2769 seq_puts(m, ")\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770}
2771
Al Viro275084c2013-03-31 03:12:15 -04002772static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773{
2774 if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
2775 return -EINVAL;
2776
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777#if defined(AHA152X_STAT)
2778 if(length>13 && strncmp("reset", buffer+8, 5)==0) {
2779 int i;
2780
2781 HOSTDATA(shpnt)->total_commands=0;
2782 HOSTDATA(shpnt)->disconnections=0;
2783 HOSTDATA(shpnt)->busfree_without_any_action=0;
2784 HOSTDATA(shpnt)->busfree_without_old_command=0;
2785 HOSTDATA(shpnt)->busfree_without_new_command=0;
2786 HOSTDATA(shpnt)->busfree_without_done_command=0;
2787 HOSTDATA(shpnt)->busfree_with_check_condition=0;
2788 for (i = idle; i<maxstate; i++) {
2789 HOSTDATA(shpnt)->count[i]=0;
2790 HOSTDATA(shpnt)->count_trans[i]=0;
2791 HOSTDATA(shpnt)->time[i]=0;
2792 }
2793
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002794 shost_printk(KERN_INFO, shpnt, "aha152x: stats reset.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796 } else
2797#endif
2798 {
2799 return -EINVAL;
2800 }
2801
2802
2803 return length;
2804}
2805
Al Viro275084c2013-03-31 03:12:15 -04002806static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
2808 int i;
Johannes Thumshirn91ebc1f2018-06-13 09:53:47 +02002809 struct scsi_cmnd *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002812 seq_puts(m, AHA152X_REVID "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002814 seq_printf(m, "ioports 0x%04lx to 0x%04lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002816 seq_printf(m, "interrupt 0x%02x\n", shpnt->irq);
2817 seq_printf(m, "disconnection/reconnection %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 RECONNECT ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002819 seq_printf(m, "parity checking %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 PARITY ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002821 seq_printf(m, "synchronous transfers %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 SYNCHRONOUS ? "enabled" : "disabled");
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002823 seq_printf(m, "%d commands currently queued\n", HOSTDATA(shpnt)->commands);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
2825 if(SYNCHRONOUS) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002826 seq_puts(m, "synchronously operating targets (tick=50 ns):\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 for (i = 0; i < 8; i++)
2828 if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002829 seq_printf(m, "target %d: period %dT/%dns; req/ack offset %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 i,
2831 (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
2832 (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
2833 HOSTDATA(shpnt)->syncrate[i] & 0x0f);
2834 }
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002835 seq_puts(m, "\nqueue status:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 DO_LOCK(flags);
2837 if (ISSUE_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002838 seq_puts(m, "not yet issued commands:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
Al Viro275084c2013-03-31 03:12:15 -04002840 get_command(m, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002842 seq_puts(m, "no not yet issued commands\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 DO_UNLOCK(flags);
2844
2845 if (CURRENT_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002846 seq_puts(m, "current command:\n");
Al Viro275084c2013-03-31 03:12:15 -04002847 get_command(m, CURRENT_SC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002849 seq_puts(m, "no current command\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
2851 if (DISCONNECTED_SC) {
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002852 seq_puts(m, "disconnected commands:\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
Al Viro275084c2013-03-31 03:12:15 -04002854 get_command(m, ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 } else
Rasmus Villemoesee7c7272014-12-03 00:10:51 +01002856 seq_puts(m, "no disconnected commands\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
Al Viro275084c2013-03-31 03:12:15 -04002858 get_ports(m, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859
2860#if defined(AHA152X_STAT)
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002861 seq_printf(m, "statistics:\n"
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002862 "total commands: %d\n"
2863 "disconnections: %d\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 "busfree with check condition: %d\n"
2865 "busfree without old command: %d\n"
2866 "busfree without new command: %d\n"
2867 "busfree without done command: %d\n"
2868 "busfree without any action: %d\n"
2869 "state "
2870 "transitions "
2871 "count "
2872 "time\n",
2873 HOSTDATA(shpnt)->total_commands,
2874 HOSTDATA(shpnt)->disconnections,
2875 HOSTDATA(shpnt)->busfree_with_check_condition,
2876 HOSTDATA(shpnt)->busfree_without_old_command,
2877 HOSTDATA(shpnt)->busfree_without_new_command,
2878 HOSTDATA(shpnt)->busfree_without_done_command,
2879 HOSTDATA(shpnt)->busfree_without_any_action);
2880 for(i=0; i<maxstate; i++) {
Rasmus Villemoes0c3de382014-12-03 00:10:49 +01002881 seq_printf(m, "%-10s %-12d %-12d %-12ld\n",
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02002882 states[i].name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 HOSTDATA(shpnt)->count_trans[i],
2884 HOSTDATA(shpnt)->count[i],
2885 HOSTDATA(shpnt)->time[i]);
2886 }
2887#endif
Al Viro275084c2013-03-31 03:12:15 -04002888 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889}
2890
Boaz Harroshb1ee0792007-07-29 22:18:20 +03002891static int aha152x_adjust_queue(struct scsi_device *device)
2892{
2893 blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
2894 return 0;
2895}
2896
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01002897static struct scsi_host_template aha152x_driver_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 .module = THIS_MODULE,
2899 .name = AHA152X_REVID,
2900 .proc_name = "aha152x",
Al Viro275084c2013-03-31 03:12:15 -04002901 .show_info = aha152x_show_info,
2902 .write_info = aha152x_set_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 .queuecommand = aha152x_queue,
2904 .eh_abort_handler = aha152x_abort,
2905 .eh_device_reset_handler = aha152x_device_reset,
2906 .eh_bus_reset_handler = aha152x_bus_reset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 .bios_param = aha152x_biosparam,
2908 .can_queue = 1,
2909 .this_id = 7,
2910 .sg_tablesize = SG_ALL,
Christoph Hellwig4af14d12018-12-13 16:17:09 +01002911 .dma_boundary = PAGE_SIZE - 1,
Boaz Harroshb1ee0792007-07-29 22:18:20 +03002912 .slave_alloc = aha152x_adjust_queue,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913};
2914
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +02002915#if !defined(AHA152X_PCMCIA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916static int setup_count;
2917static struct aha152x_setup setup[2];
2918
2919/* possible i/o addresses for the AIC-6260; default first */
2920static unsigned short ports[] = { 0x340, 0x140 };
2921
2922#if !defined(SKIP_BIOSTEST)
2923/* possible locations for the Adaptec BIOS; defaults first */
2924static unsigned int addresses[] =
2925{
2926 0xdc000, /* default first */
2927 0xc8000,
2928 0xcc000,
2929 0xd0000,
2930 0xd4000,
2931 0xd8000,
2932 0xe0000,
2933 0xeb800, /* VTech Platinum SMP */
2934 0xf0000,
2935};
2936
2937/* signatures for various AIC-6[23]60 based controllers.
2938 The point in detecting signatures is to avoid useless and maybe
2939 harmful probes on ports. I'm not sure that all listed boards pass
2940 auto-configuration. For those which fail the BIOS signature is
2941 obsolete, because user intervention to supply the configuration is
2942 needed anyway. May be an information whether or not the BIOS supports
2943 extended translation could be also useful here. */
2944static struct signature {
2945 unsigned char *signature;
2946 int sig_offset;
2947 int sig_length;
2948} signatures[] =
2949{
2950 { "Adaptec AHA-1520 BIOS", 0x102e, 21 },
2951 /* Adaptec 152x */
2952 { "Adaptec AHA-1520B", 0x000b, 17 },
2953 /* Adaptec 152x rev B */
2954 { "Adaptec AHA-1520B", 0x0026, 17 },
2955 /* Iomega Jaz Jet ISA (AIC6370Q) */
2956 { "Adaptec ASW-B626 BIOS", 0x1029, 21 },
2957 /* on-board controller */
2958 { "Adaptec BIOS: ASW-B626", 0x000f, 22 },
2959 /* on-board controller */
2960 { "Adaptec ASW-B626 S2", 0x2e6c, 19 },
2961 /* on-board controller */
2962 { "Adaptec BIOS:AIC-6360", 0x000c, 21 },
2963 /* on-board controller */
2964 { "ScsiPro SP-360 BIOS", 0x2873, 19 },
2965 /* ScsiPro-Controller */
2966 { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },
2967 /* Gigabyte Local-Bus-SCSI */
2968 { "Adaptec BIOS:AVA-282X", 0x000c, 21 },
2969 /* Adaptec 282x */
2970 { "Adaptec IBM Dock II SCSI", 0x2edd, 24 },
2971 /* IBM Thinkpad Dock II */
2972 { "Adaptec BIOS:AHA-1532P", 0x001c, 22 },
2973 /* IBM Thinkpad Dock II SCSI */
2974 { "DTC3520A Host Adapter BIOS", 0x318a, 26 },
2975 /* DTC 3520A ISA SCSI */
2976};
2977#endif /* !SKIP_BIOSTEST */
2978
2979/*
2980 * Test, if port_base is valid.
2981 *
2982 */
2983static int aha152x_porttest(int io_port)
2984{
2985 int i;
2986
2987 SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
2988 for (i = 0; i < 16; i++)
2989 SETPORT(io_port + O_STACK, i);
2990
2991 SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
2992 for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++)
2993 ;
2994
2995 return (i == 16);
2996}
2997
2998static int tc1550_porttest(int io_port)
2999{
3000 int i;
3001
3002 SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
3003 for (i = 0; i < 16; i++)
3004 SETPORT(io_port + O_STACK, i);
3005
3006 SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
3007 for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++)
3008 ;
3009
3010 return (i == 16);
3011}
3012
3013
3014static int checksetup(struct aha152x_setup *setup)
3015{
3016 int i;
3017 for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
3018 ;
3019
3020 if (i == ARRAY_SIZE(ports))
3021 return 0;
3022
Harvey Harrison9bcf0912008-05-22 15:45:07 -07003023 if (!request_region(setup->io_port, IO_RANGE, "aha152x")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port);
3025 return 0;
3026 }
3027
3028 if( aha152x_porttest(setup->io_port) ) {
3029 setup->tc1550=0;
3030 } else if( tc1550_porttest(setup->io_port) ) {
3031 setup->tc1550=1;
3032 } else {
3033 release_region(setup->io_port, IO_RANGE);
3034 return 0;
3035 }
3036
3037 release_region(setup->io_port, IO_RANGE);
3038
3039 if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
3040 return 0;
3041
3042 if ((setup->scsiid < 0) || (setup->scsiid > 7))
3043 return 0;
3044
3045 if ((setup->reconnect < 0) || (setup->reconnect > 1))
3046 return 0;
3047
3048 if ((setup->parity < 0) || (setup->parity > 1))
3049 return 0;
3050
3051 if ((setup->synchronous < 0) || (setup->synchronous > 1))
3052 return 0;
3053
3054 if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
3055 return 0;
3056
3057
3058 return 1;
3059}
3060
3061
3062static int __init aha152x_init(void)
3063{
3064 int i, j, ok;
3065#if defined(AUTOCONF)
3066 aha152x_config conf;
3067#endif
3068#ifdef __ISAPNP__
3069 struct pnp_dev *dev=NULL, *pnpdev[2] = {NULL, NULL};
3070#endif
3071
3072 if ( setup_count ) {
3073 printk(KERN_INFO "aha152x: processing commandline: ");
3074
3075 for (i = 0; i<setup_count; i++) {
3076 if (!checksetup(&setup[i])) {
3077 printk(KERN_ERR "\naha152x: %s\n", setup[i].conf);
3078 printk(KERN_ERR "aha152x: invalid line\n");
3079 }
3080 }
3081 printk("ok\n");
3082 }
3083
3084#if defined(SETUP0)
3085 if (setup_count < ARRAY_SIZE(setup)) {
3086 struct aha152x_setup override = SETUP0;
3087
3088 if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
3089 if (!checksetup(&override)) {
3090 printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
3091 override.io_port,
3092 override.irq,
3093 override.scsiid,
3094 override.reconnect,
3095 override.parity,
3096 override.synchronous,
3097 override.delay,
3098 override.ext_trans);
3099 } else
3100 setup[setup_count++] = override;
3101 }
3102 }
3103#endif
3104
3105#if defined(SETUP1)
3106 if (setup_count < ARRAY_SIZE(setup)) {
3107 struct aha152x_setup override = SETUP1;
3108
3109 if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
3110 if (!checksetup(&override)) {
3111 printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
3112 override.io_port,
3113 override.irq,
3114 override.scsiid,
3115 override.reconnect,
3116 override.parity,
3117 override.synchronous,
3118 override.delay,
3119 override.ext_trans);
3120 } else
3121 setup[setup_count++] = override;
3122 }
3123 }
3124#endif
3125
3126#if defined(MODULE)
3127 if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
3128 if(aha152x[0]!=0) {
3129 setup[setup_count].conf = "";
3130 setup[setup_count].io_port = aha152x[0];
3131 setup[setup_count].irq = aha152x[1];
3132 setup[setup_count].scsiid = aha152x[2];
3133 setup[setup_count].reconnect = aha152x[3];
3134 setup[setup_count].parity = aha152x[4];
3135 setup[setup_count].synchronous = aha152x[5];
3136 setup[setup_count].delay = aha152x[6];
3137 setup[setup_count].ext_trans = aha152x[7];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003138 } else if (io[0] != 0 || irq[0] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 if(io[0]!=0) setup[setup_count].io_port = io[0];
3140 if(irq[0]!=0) setup[setup_count].irq = irq[0];
3141
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003142 setup[setup_count].scsiid = scsiid[0];
3143 setup[setup_count].reconnect = reconnect[0];
3144 setup[setup_count].parity = parity[0];
3145 setup[setup_count].synchronous = sync[0];
3146 setup[setup_count].delay = delay[0];
3147 setup[setup_count].ext_trans = exttrans[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 }
3149
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003150 if (checksetup(&setup[setup_count]))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 setup_count++;
3152 else
3153 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",
3154 setup[setup_count].io_port,
3155 setup[setup_count].irq,
3156 setup[setup_count].scsiid,
3157 setup[setup_count].reconnect,
3158 setup[setup_count].parity,
3159 setup[setup_count].synchronous,
3160 setup[setup_count].delay,
3161 setup[setup_count].ext_trans);
3162 }
3163
3164 if (setup_count<ARRAY_SIZE(setup) && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) {
3165 if(aha152x1[0]!=0) {
3166 setup[setup_count].conf = "";
3167 setup[setup_count].io_port = aha152x1[0];
3168 setup[setup_count].irq = aha152x1[1];
3169 setup[setup_count].scsiid = aha152x1[2];
3170 setup[setup_count].reconnect = aha152x1[3];
3171 setup[setup_count].parity = aha152x1[4];
3172 setup[setup_count].synchronous = aha152x1[5];
3173 setup[setup_count].delay = aha152x1[6];
3174 setup[setup_count].ext_trans = aha152x1[7];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003175 } else if (io[1] != 0 || irq[1] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 if(io[1]!=0) setup[setup_count].io_port = io[1];
3177 if(irq[1]!=0) setup[setup_count].irq = irq[1];
3178
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003179 setup[setup_count].scsiid = scsiid[1];
3180 setup[setup_count].reconnect = reconnect[1];
3181 setup[setup_count].parity = parity[1];
3182 setup[setup_count].synchronous = sync[1];
3183 setup[setup_count].delay = delay[1];
3184 setup[setup_count].ext_trans = exttrans[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 }
3186 if (checksetup(&setup[setup_count]))
3187 setup_count++;
3188 else
3189 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",
3190 setup[setup_count].io_port,
3191 setup[setup_count].irq,
3192 setup[setup_count].scsiid,
3193 setup[setup_count].reconnect,
3194 setup[setup_count].parity,
3195 setup[setup_count].synchronous,
3196 setup[setup_count].delay,
3197 setup[setup_count].ext_trans);
3198 }
3199#endif
3200
3201#ifdef __ISAPNP__
3202 for(i=0; setup_count<ARRAY_SIZE(setup) && id_table[i].vendor; i++) {
3203 while ( setup_count<ARRAY_SIZE(setup) &&
3204 (dev=pnp_find_dev(NULL, id_table[i].vendor, id_table[i].function, dev)) ) {
3205 if (pnp_device_attach(dev) < 0)
3206 continue;
3207
3208 if (pnp_activate_dev(dev) < 0) {
3209 pnp_device_detach(dev);
3210 continue;
3211 }
3212
3213 if (!pnp_port_valid(dev, 0)) {
3214 pnp_device_detach(dev);
3215 continue;
3216 }
3217
3218 if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
3219 pnp_device_detach(dev);
3220 continue;
3221 }
3222
3223 setup[setup_count].io_port = pnp_port_start(dev, 0);
3224 setup[setup_count].irq = pnp_irq(dev, 0);
3225 setup[setup_count].scsiid = 7;
3226 setup[setup_count].reconnect = 1;
3227 setup[setup_count].parity = 1;
3228 setup[setup_count].synchronous = 1;
3229 setup[setup_count].delay = DELAY_DEFAULT;
3230 setup[setup_count].ext_trans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231#if defined(__ISAPNP__)
3232 pnpdev[setup_count] = dev;
3233#endif
3234 printk (KERN_INFO
3235 "aha152x: found ISAPnP adapter at io=0x%03x, irq=%d\n",
3236 setup[setup_count].io_port, setup[setup_count].irq);
3237 setup_count++;
3238 }
3239 }
3240#endif
3241
3242#if defined(AUTOCONF)
3243 if (setup_count<ARRAY_SIZE(setup)) {
3244#if !defined(SKIP_BIOSTEST)
3245 ok = 0;
3246 for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++) {
3247 void __iomem *p = ioremap(addresses[i], 0x4000);
3248 if (!p)
3249 continue;
3250 for (j = 0; j<ARRAY_SIZE(signatures) && !ok; j++)
3251 ok = check_signature(p + signatures[j].sig_offset,
3252 signatures[j].signature, signatures[j].sig_length);
3253 iounmap(p);
3254 }
3255 if (!ok && setup_count == 0)
James Bottomleyad2fa422008-05-10 08:33:58 -05003256 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257
3258 printk(KERN_INFO "aha152x: BIOS test: passed, ");
3259#else
3260 printk(KERN_INFO "aha152x: ");
3261#endif /* !SKIP_BIOSTEST */
3262
3263 ok = 0;
3264 for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
3265 if ((setup_count == 1) && (setup[0].io_port == ports[i]))
3266 continue;
3267
Harvey Harrison9bcf0912008-05-22 15:45:07 -07003268 if (!request_region(ports[i], IO_RANGE, "aha152x")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]);
3270 continue;
3271 }
3272
3273 if (aha152x_porttest(ports[i])) {
3274 setup[setup_count].tc1550 = 0;
3275
3276 conf.cf_port =
3277 (GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
3278 } else if (tc1550_porttest(ports[i])) {
3279 setup[setup_count].tc1550 = 1;
3280
3281 conf.cf_port =
3282 (GETPORT(ports[i] + O_TC_PORTA) << 8) + GETPORT(ports[i] + O_TC_PORTB);
3283 } else {
3284 release_region(ports[i], IO_RANGE);
3285 continue;
3286 }
3287
3288 release_region(ports[i], IO_RANGE);
3289
3290 ok++;
3291 setup[setup_count].io_port = ports[i];
3292 setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
3293 setup[setup_count].scsiid = conf.cf_id;
3294 setup[setup_count].reconnect = conf.cf_tardisc;
3295 setup[setup_count].parity = !conf.cf_parity;
3296 setup[setup_count].synchronous = conf.cf_syncneg;
3297 setup[setup_count].delay = DELAY_DEFAULT;
3298 setup[setup_count].ext_trans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 setup_count++;
3300
3301 }
3302
3303 if (ok)
3304 printk("auto configuration: ok, ");
3305 }
3306#endif
3307
3308 printk("%d controller(s) configured\n", setup_count);
3309
3310 for (i=0; i<setup_count; i++) {
3311 if ( request_region(setup[i].io_port, IO_RANGE, "aha152x") ) {
3312 struct Scsi_Host *shpnt = aha152x_probe_one(&setup[i]);
3313
3314 if( !shpnt ) {
3315 release_region(setup[i].io_port, IO_RANGE);
3316#if defined(__ISAPNP__)
3317 } else if( pnpdev[i] ) {
3318 HOSTDATA(shpnt)->pnpdev=pnpdev[i];
3319 pnpdev[i]=NULL;
3320#endif
3321 }
3322 } else {
3323 printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup[i].io_port);
3324 }
3325
3326#if defined(__ISAPNP__)
3327 if( pnpdev[i] )
3328 pnp_device_detach(pnpdev[i]);
3329#endif
3330 }
3331
James Bottomleyad2fa422008-05-10 08:33:58 -05003332 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333}
3334
3335static void __exit aha152x_exit(void)
3336{
James Bottomley64976a02008-05-10 14:08:40 -05003337 struct aha152x_hostdata *hd, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
James Bottomley64976a02008-05-10 14:08:40 -05003339 list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) {
James Bottomley5fcda422006-09-14 17:04:58 -05003340 struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
3341
3342 aha152x_release(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343 }
3344}
3345
3346module_init(aha152x_init);
3347module_exit(aha152x_exit);
3348
3349#if !defined(MODULE)
3350static int __init aha152x_setup(char *str)
3351{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 int ints[10];
Hannes Reineckef75ae8e2014-10-24 14:26:43 +02003353
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 get_options(str, ARRAY_SIZE(ints), ints);
3355
3356 if(setup_count>=ARRAY_SIZE(setup)) {
3357 printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
3358 return 1;
3359 }
3360
3361 setup[setup_count].conf = str;
3362 setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
3363 setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
3364 setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
3365 setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
3366 setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
3367 setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
3368 setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
3369 setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 if (ints[0] > 8) { /*}*/
3371 printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
3372 "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 } else {
3374 setup_count++;
3375 return 0;
3376 }
3377
3378 return 1;
3379}
3380__setup("aha152x=", aha152x_setup);
3381#endif
3382
Christoph Hellwig3eb2ebc2018-10-19 14:09:44 +02003383#endif /* !AHA152X_PCMCIA */