blob: 859b32febbb403521edcd8a49031be8f67973968 [file] [log] [blame]
Finn Thainaff0cf92016-01-03 16:06:09 +11001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * NCR 5380 generic driver routines. These should make it *trivial*
Finn Thain594d4ba2016-01-03 16:06:10 +11003 * to implement 5380 SCSI drivers under Linux with a non-trantor
4 * architecture.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Finn Thain594d4ba2016-01-03 16:06:10 +11006 * Note that these routines also work with NR53c400 family chips.
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
8 * Copyright 1993, Drew Eckhardt
Finn Thain594d4ba2016-01-03 16:06:10 +11009 * Visionary Computing
10 * (Unix and Linux consulting and custom programming)
11 * drew@colorado.edu
12 * +1 (303) 666-5836
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
Finn Thainaff0cf92016-01-03 16:06:09 +110014 * For more information, please consult
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 *
16 * NCR 5380 Family
17 * SCSI Protocol Controller
18 * Databook
19 *
20 * NCR Microelectronics
21 * 1635 Aeroplaza Drive
22 * Colorado Springs, CO 80916
23 * 1+ (719) 578-3400
24 * 1+ (800) 334-5454
25 */
26
27/*
Finn Thainc16df322016-01-03 16:06:08 +110028 * With contributions from Ray Van Tassle, Ingmar Baumgart,
29 * Ronald van Cuijlenborg, Alan Cox and others.
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 */
31
Finn Thain52d3e562016-03-23 21:10:20 +110032/* Ported to Atari by Roman Hodek and others. */
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034/*
Finn Thainaff0cf92016-01-03 16:06:09 +110035 * Further development / testing that should be done :
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 *
Finn Thainaff0cf92016-01-03 16:06:09 +110037 * 4. Test SCSI-II tagged queueing (I have no devices which support
Finn Thain594d4ba2016-01-03 16:06:10 +110038 * tagged queueing)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 */
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041/*
42 * Design
43 *
Finn Thainaff0cf92016-01-03 16:06:09 +110044 * This is a generic 5380 driver. To use it on a different platform,
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 * one simply writes appropriate system specific macros (ie, data
Finn Thainaff0cf92016-01-03 16:06:09 +110046 * transfer - some PC's will use the I/O bus, 68K's must use
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 * memory mapped) and drops this file in their 'C' wrapper.
48 *
Finn Thainaff0cf92016-01-03 16:06:09 +110049 * As far as command queueing, two queues are maintained for
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 * each 5380 in the system - commands that haven't been issued yet,
Finn Thainaff0cf92016-01-03 16:06:09 +110051 * and commands that are currently executing. This means that an
52 * unlimited number of commands may be queued, letting
53 * more commands propagate from the higher driver levels giving higher
54 * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported,
55 * allowing multiple commands to propagate all the way to a SCSI-II device
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 * while a command is already executing.
57 *
58 *
Finn Thainaff0cf92016-01-03 16:06:09 +110059 * Issues specific to the NCR5380 :
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 *
Finn Thainaff0cf92016-01-03 16:06:09 +110061 * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
62 * piece of hardware that requires you to sit in a loop polling for
63 * the REQ signal as long as you are connected. Some devices are
64 * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
Finn Thain686f3992016-01-03 16:05:26 +110065 * while doing long seek operations. [...] These
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 * broken devices are the exception rather than the rule and I'd rather
67 * spend my time optimizing for the normal case.
68 *
69 * Architecture :
70 *
71 * At the heart of the design is a coroutine, NCR5380_main,
72 * which is started from a workqueue for each NCR5380 host in the
73 * system. It attempts to establish I_T_L or I_T_L_Q nexuses by
74 * removing the commands from the issue queue and calling
Finn Thainaff0cf92016-01-03 16:06:09 +110075 * NCR5380_select() if a nexus is not established.
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 *
77 * Once a nexus is established, the NCR5380_information_transfer()
78 * phase goes through the various phases as instructed by the target.
79 * if the target goes into MSG IN and sends a DISCONNECT message,
80 * the command structure is placed into the per instance disconnected
Finn Thainaff0cf92016-01-03 16:06:09 +110081 * queue, and NCR5380_main tries to find more work. If the target is
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 * idle for too long, the system will try to sleep.
83 *
84 * If a command has disconnected, eventually an interrupt will trigger,
85 * calling NCR5380_intr() which will in turn call NCR5380_reselect
86 * to reestablish a nexus. This will run main if necessary.
87 *
Finn Thainaff0cf92016-01-03 16:06:09 +110088 * On command termination, the done function will be called as
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 * appropriate.
90 *
Finn Thainaff0cf92016-01-03 16:06:09 +110091 * SCSI pointers are maintained in the SCp field of SCSI command
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 * structures, being initialized after the command is connected
93 * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
94 * Note that in violation of the standard, an implicit SAVE POINTERS operation
95 * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS.
96 */
97
98/*
99 * Using this file :
100 * This file a skeleton Linux SCSI driver for the NCR 5380 series
Finn Thainaff0cf92016-01-03 16:06:09 +1100101 * of chips. To use it, you write an architecture specific functions
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 * and macros and include this file in your driver.
103 *
Finn Thainaff0cf92016-01-03 16:06:09 +1100104 * These macros control options :
105 * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be
Finn Thain594d4ba2016-01-03 16:06:10 +1100106 * defined.
Finn Thainaff0cf92016-01-03 16:06:09 +1100107 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
Finn Thain594d4ba2016-01-03 16:06:10 +1100109 * for commands that return with a CHECK CONDITION status.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 *
111 * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
Finn Thain594d4ba2016-01-03 16:06:10 +1100112 * transceivers.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 *
114 * DONT_USE_INTR - if defined, never use interrupts, even if we probe or
Finn Thain594d4ba2016-01-03 16:06:10 +1100115 * override-configure an IRQ.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases.
118 *
Finn Thain8053b0e2016-03-23 21:10:19 +1100119 * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
120 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 * These macros MUST be defined :
Finn Thainaff0cf92016-01-03 16:06:09 +1100122 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 * NCR5380_read(register) - read from the specified register
124 *
Finn Thainaff0cf92016-01-03 16:06:09 +1100125 * NCR5380_write(register, value) - write to the specific register
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 *
Finn Thainaff0cf92016-01-03 16:06:09 +1100127 * NCR5380_implementation_fields - additional fields needed for this
Finn Thain594d4ba2016-01-03 16:06:10 +1100128 * specific implementation of the NCR5380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 *
130 * Either real DMA *or* pseudo DMA may be implemented
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 * NCR5380_dma_write_setup(instance, src, count) - initialize
133 * NCR5380_dma_read_setup(instance, dst, count) - initialize
134 * NCR5380_dma_residual(instance); - residual count
135 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 * The generic driver is initialized by calling NCR5380_init(instance),
Finn Thainaff0cf92016-01-03 16:06:09 +1100137 * after setting the appropriate host specific fields and ID. If the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
139 * possible) function may be used.
140 */
141
Finn Thaine5d55d12016-03-23 21:10:16 +1100142#ifndef NCR5380_io_delay
143#define NCR5380_io_delay(x)
144#endif
145
Finn Thain52d3e562016-03-23 21:10:20 +1100146#ifndef NCR5380_acquire_dma_irq
147#define NCR5380_acquire_dma_irq(x) (1)
148#endif
149
150#ifndef NCR5380_release_dma_irq
151#define NCR5380_release_dma_irq(x)
152#endif
153
Finn Thain54d8fe42016-01-03 16:05:06 +1100154static int do_abort(struct Scsi_Host *);
155static void do_reset(struct Scsi_Host *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Finn Thainc16df322016-01-03 16:06:08 +1100157/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100158 * initialize_SCp - init the scsi pointer field
Finn Thain594d4ba2016-01-03 16:06:10 +1100159 * @cmd: command block to set up
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100161 * Set up the internal fields in the SCSI command.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 */
163
Finn Thain710ddd02014-11-12 16:12:02 +1100164static inline void initialize_SCp(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165{
Finn Thainaff0cf92016-01-03 16:06:09 +1100166 /*
167 * Initialize the Scsi Pointer field so that all of the commands in the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 * various queues are valid.
169 */
170
Boaz Harrosh9e0fe442007-11-05 11:23:35 +0200171 if (scsi_bufflen(cmd)) {
172 cmd->SCp.buffer = scsi_sglist(cmd);
173 cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
Jens Axboe45711f12007-10-22 21:19:53 +0200174 cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 cmd->SCp.this_residual = cmd->SCp.buffer->length;
176 } else {
177 cmd->SCp.buffer = NULL;
178 cmd->SCp.buffers_residual = 0;
Boaz Harrosh9e0fe442007-11-05 11:23:35 +0200179 cmd->SCp.ptr = NULL;
180 cmd->SCp.this_residual = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
Finn Thainf27db8e2016-01-03 16:06:00 +1100182
183 cmd->SCp.Status = 0;
184 cmd->SCp.Message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185}
186
187/**
Finn Thainb32ade12016-01-03 16:05:41 +1100188 * NCR5380_poll_politely2 - wait for two chip register values
Finn Thain2f854b82016-01-03 16:05:22 +1100189 * @instance: controller to poll
Finn Thainb32ade12016-01-03 16:05:41 +1100190 * @reg1: 5380 register to poll
191 * @bit1: Bitmask to check
192 * @val1: Expected value
193 * @reg2: Second 5380 register to poll
194 * @bit2: Second bitmask to check
195 * @val2: Second expected value
Finn Thain2f854b82016-01-03 16:05:22 +1100196 * @wait: Time-out in jiffies
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 *
Finn Thain2f854b82016-01-03 16:05:22 +1100198 * Polls the chip in a reasonably efficient manner waiting for an
199 * event to occur. After a short quick poll we begin to yield the CPU
200 * (if possible). In irq contexts the time-out is arbitrarily limited.
201 * Callers may hold locks as long as they are held in irq mode.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 *
Finn Thainb32ade12016-01-03 16:05:41 +1100203 * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Finn Thainb32ade12016-01-03 16:05:41 +1100206static int NCR5380_poll_politely2(struct Scsi_Host *instance,
207 int reg1, int bit1, int val1,
208 int reg2, int bit2, int val2, int wait)
Finn Thain2f854b82016-01-03 16:05:22 +1100209{
210 struct NCR5380_hostdata *hostdata = shost_priv(instance);
211 unsigned long deadline = jiffies + wait;
212 unsigned long n;
213
214 /* Busy-wait for up to 10 ms */
215 n = min(10000U, jiffies_to_usecs(wait));
216 n *= hostdata->accesses_per_ms;
Finn Thainb32ade12016-01-03 16:05:41 +1100217 n /= 2000;
Finn Thain2f854b82016-01-03 16:05:22 +1100218 do {
Finn Thainb32ade12016-01-03 16:05:41 +1100219 if ((NCR5380_read(reg1) & bit1) == val1)
220 return 0;
221 if ((NCR5380_read(reg2) & bit2) == val2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 return 0;
223 cpu_relax();
Finn Thain2f854b82016-01-03 16:05:22 +1100224 } while (n--);
225
226 if (irqs_disabled() || in_interrupt())
227 return -ETIMEDOUT;
228
229 /* Repeatedly sleep for 1 ms until deadline */
230 while (time_is_after_jiffies(deadline)) {
231 schedule_timeout_uninterruptible(1);
Finn Thainb32ade12016-01-03 16:05:41 +1100232 if ((NCR5380_read(reg1) & bit1) == val1)
233 return 0;
234 if ((NCR5380_read(reg2) & bit2) == val2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 }
Finn Thain2f854b82016-01-03 16:05:22 +1100237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 return -ETIMEDOUT;
239}
240
Finn Thainb32ade12016-01-03 16:05:41 +1100241static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
242 int reg, int bit, int val, int wait)
243{
244 return NCR5380_poll_politely2(instance, reg, bit, val,
245 reg, bit, val, wait);
246}
247
viro@ZenIV.linux.org.uk185a7a12005-09-07 23:18:24 +0100248#if NDEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249static struct {
250 unsigned char mask;
251 const char *name;
Finn Thainaff0cf92016-01-03 16:06:09 +1100252} signals[] = {
253 {SR_DBP, "PARITY"},
254 {SR_RST, "RST"},
255 {SR_BSY, "BSY"},
256 {SR_REQ, "REQ"},
257 {SR_MSG, "MSG"},
258 {SR_CD, "CD"},
259 {SR_IO, "IO"},
260 {SR_SEL, "SEL"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 {0, NULL}
Finn Thainaff0cf92016-01-03 16:06:09 +1100262},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263basrs[] = {
Finn Thainaff0cf92016-01-03 16:06:09 +1100264 {BASR_ATN, "ATN"},
265 {BASR_ACK, "ACK"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 {0, NULL}
Finn Thainaff0cf92016-01-03 16:06:09 +1100267},
268icrs[] = {
269 {ICR_ASSERT_RST, "ASSERT RST"},
270 {ICR_ASSERT_ACK, "ASSERT ACK"},
271 {ICR_ASSERT_BSY, "ASSERT BSY"},
272 {ICR_ASSERT_SEL, "ASSERT SEL"},
273 {ICR_ASSERT_ATN, "ASSERT ATN"},
274 {ICR_ASSERT_DATA, "ASSERT DATA"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 {0, NULL}
Finn Thainaff0cf92016-01-03 16:06:09 +1100276},
277mrs[] = {
278 {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"},
279 {MR_TARGET, "MODE TARGET"},
280 {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"},
281 {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"},
Finn Thain0d2cf862016-01-03 16:06:11 +1100282 {MR_ENABLE_EOP_INTR, "MODE EOP INTR"},
Finn Thainaff0cf92016-01-03 16:06:09 +1100283 {MR_MONITOR_BSY, "MODE MONITOR BSY"},
284 {MR_DMA_MODE, "MODE DMA"},
285 {MR_ARBITRATE, "MODE ARBITRATION"},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 {0, NULL}
287};
288
289/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100290 * NCR5380_print - print scsi bus signals
291 * @instance: adapter state to dump
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100293 * Print the SCSI bus signals for debugging purposes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 */
295
296static void NCR5380_print(struct Scsi_Host *instance)
297{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 unsigned char status, data, basr, mr, icr, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 data = NCR5380_read(CURRENT_SCSI_DATA_REG);
301 status = NCR5380_read(STATUS_REG);
302 mr = NCR5380_read(MODE_REG);
303 icr = NCR5380_read(INITIATOR_COMMAND_REG);
304 basr = NCR5380_read(BUS_AND_STATUS_REG);
305
306 printk("STATUS_REG: %02x ", status);
307 for (i = 0; signals[i].mask; ++i)
308 if (status & signals[i].mask)
309 printk(",%s", signals[i].name);
310 printk("\nBASR: %02x ", basr);
311 for (i = 0; basrs[i].mask; ++i)
312 if (basr & basrs[i].mask)
313 printk(",%s", basrs[i].name);
314 printk("\nICR: %02x ", icr);
315 for (i = 0; icrs[i].mask; ++i)
316 if (icr & icrs[i].mask)
317 printk(",%s", icrs[i].name);
318 printk("\nMODE: %02x ", mr);
319 for (i = 0; mrs[i].mask; ++i)
320 if (mr & mrs[i].mask)
321 printk(",%s", mrs[i].name);
322 printk("\n");
323}
324
Finn Thain0d2cf862016-01-03 16:06:11 +1100325static struct {
326 unsigned char value;
327 const char *name;
328} phases[] = {
329 {PHASE_DATAOUT, "DATAOUT"},
330 {PHASE_DATAIN, "DATAIN"},
331 {PHASE_CMDOUT, "CMDOUT"},
332 {PHASE_STATIN, "STATIN"},
333 {PHASE_MSGOUT, "MSGOUT"},
334 {PHASE_MSGIN, "MSGIN"},
335 {PHASE_UNKNOWN, "UNKNOWN"}
336};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Finn Thainc16df322016-01-03 16:06:08 +1100338/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100339 * NCR5380_print_phase - show SCSI phase
Finn Thain594d4ba2016-01-03 16:06:10 +1100340 * @instance: adapter to dump
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100342 * Print the current SCSI phase for debugging purposes
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 */
344
345static void NCR5380_print_phase(struct Scsi_Host *instance)
346{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 unsigned char status;
348 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 status = NCR5380_read(STATUS_REG);
351 if (!(status & SR_REQ))
Finn Thain6a6ff4a2016-01-03 16:06:04 +1100352 shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 else {
Finn Thain0d2cf862016-01-03 16:06:11 +1100354 for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
355 (phases[i].value != (status & PHASE_MASK)); ++i)
356 ;
Finn Thain6a6ff4a2016-01-03 16:06:04 +1100357 shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 }
359}
360#endif
361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
Finn Thaind5f7e652016-01-03 16:05:03 +1100363static int probe_irq __initdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365/**
Finn Thain594d4ba2016-01-03 16:06:10 +1100366 * probe_intr - helper for IRQ autoprobe
367 * @irq: interrupt number
368 * @dev_id: unused
369 * @regs: unused
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100371 * Set a flag to indicate the IRQ in question was received. This is
372 * used by the IRQ probe code.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 */
Finn Thainaff0cf92016-01-03 16:06:09 +1100374
David Howells7d12e782006-10-05 14:55:46 +0100375static irqreturn_t __init probe_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376{
377 probe_irq = irq;
378 return IRQ_HANDLED;
379}
380
381/**
Finn Thain594d4ba2016-01-03 16:06:10 +1100382 * NCR5380_probe_irq - find the IRQ of an NCR5380
383 * @instance: NCR5380 controller
384 * @possible: bitmask of ISA IRQ lines
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100386 * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
387 * and then looking to see what interrupt actually turned up.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 */
389
Andrew Morton702809c2007-05-23 14:41:56 -0700390static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
391 int possible)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
Finn Thaine8a60142016-01-03 16:05:54 +1100393 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 unsigned long timeout;
395 int trying_irqs, i, mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Finn Thain22f5f102014-11-12 16:11:56 +1100397 for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
Michael Opdenacker4909cc22014-03-05 06:09:41 +0100398 if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 trying_irqs |= mask;
400
Nicholas Mc Guire4e5a8002015-02-04 13:30:20 -0500401 timeout = jiffies + msecs_to_jiffies(250);
Finn Thain22f5f102014-11-12 16:11:56 +1100402 probe_irq = NO_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404 /*
405 * A interrupt is triggered whenever BSY = false, SEL = true
Finn Thainaff0cf92016-01-03 16:06:09 +1100406 * and a bit set in the SELECT_ENABLE_REG is asserted on the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 * SCSI bus.
408 *
409 * Note that the bus is only driven when the phase control signals
410 * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
411 * to zero.
412 */
413
414 NCR5380_write(TARGET_COMMAND_REG, 0);
415 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
416 NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
417 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
418
Finn Thain22f5f102014-11-12 16:11:56 +1100419 while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
Nishanth Aravamudana9a30472005-11-07 01:01:20 -0800420 schedule_timeout_uninterruptible(1);
Finn Thainaff0cf92016-01-03 16:06:09 +1100421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 NCR5380_write(SELECT_ENABLE_REG, 0);
423 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
424
Finn Thain22f5f102014-11-12 16:11:56 +1100425 for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 if (trying_irqs & mask)
427 free_irq(i, NULL);
428
429 return probe_irq;
430}
431
432/**
Finn Thain594d4ba2016-01-03 16:06:10 +1100433 * NCR58380_info - report driver and host information
434 * @instance: relevant scsi host instance
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100436 * For use as the host template info() handler.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 */
438
Finn Thain8c325132014-11-12 16:11:58 +1100439static const char *NCR5380_info(struct Scsi_Host *instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Finn Thain8c325132014-11-12 16:11:58 +1100441 struct NCR5380_hostdata *hostdata = shost_priv(instance);
442
443 return hostdata->info;
444}
445
446static void prepare_info(struct Scsi_Host *instance)
447{
448 struct NCR5380_hostdata *hostdata = shost_priv(instance);
449
450 snprintf(hostdata->info, sizeof(hostdata->info),
451 "%s, io_port 0x%lx, n_io_port %d, "
452 "base 0x%lx, irq %d, "
453 "can_queue %d, cmd_per_lun %d, "
454 "sg_tablesize %d, this_id %d, "
Finn Thainbe3f4122016-01-03 16:05:50 +1100455 "flags { %s%s%s}, "
Finn Thain8c325132014-11-12 16:11:58 +1100456 "options { %s} ",
457 instance->hostt->name, instance->io_port, instance->n_io_port,
458 instance->base, instance->irq,
459 instance->can_queue, instance->cmd_per_lun,
460 instance->sg_tablesize, instance->this_id,
Finn Thain1bb46002016-03-23 21:10:14 +1100461 hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "",
Finn Thain8c325132014-11-12 16:11:58 +1100462 hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
Finn Thain9c3f0e22016-01-03 16:05:11 +1100463 hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464#ifdef AUTOPROBE_IRQ
Finn Thain8c325132014-11-12 16:11:58 +1100465 "AUTOPROBE_IRQ "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467#ifdef DIFFERENTIAL
Finn Thain8c325132014-11-12 16:11:58 +1100468 "DIFFERENTIAL "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470#ifdef PARITY
Finn Thain8c325132014-11-12 16:11:58 +1100471 "PARITY "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472#endif
Finn Thain8c325132014-11-12 16:11:58 +1100473 "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100477 * NCR5380_init - initialise an NCR5380
Finn Thain594d4ba2016-01-03 16:06:10 +1100478 * @instance: adapter to configure
479 * @flags: control flags
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100481 * Initializes *instance and corresponding 5380 chip,
482 * with flags OR'd into the initial flags value.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100484 * Notes : I assume that the host, hostno, and id bits have been
Finn Thain0d2cf862016-01-03 16:06:11 +1100485 * set correctly. I don't care about the irq and other fields.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100487 * Returns 0 for success
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 */
489
Greg Kroah-Hartman6f039792012-12-21 13:08:55 -0800490static int NCR5380_init(struct Scsi_Host *instance, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
Finn Thaine8a60142016-01-03 16:05:54 +1100492 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Finn Thainb6488f92016-01-03 16:05:08 +1100493 int i;
Finn Thain2f854b82016-01-03 16:05:22 +1100494 unsigned long deadline;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Finn Thain0d2cf862016-01-03 16:06:11 +1100496 hostdata->host = instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 hostdata->id_mask = 1 << instance->this_id;
Finn Thain0d2cf862016-01-03 16:06:11 +1100498 hostdata->id_higher_mask = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
500 if (i > hostdata->id_mask)
501 hostdata->id_higher_mask |= i;
502 for (i = 0; i < 8; ++i)
503 hostdata->busy[i] = 0;
Finn Thaine4dec682016-03-23 21:10:12 +1100504 hostdata->dma_len = 0;
505
Finn Thain11d2f632016-01-03 16:05:51 +1100506 spin_lock_init(&hostdata->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 hostdata->connected = NULL;
Finn Thainf27db8e2016-01-03 16:06:00 +1100508 hostdata->sensing = NULL;
509 INIT_LIST_HEAD(&hostdata->autosense);
Finn Thain32b26a12016-01-03 16:05:58 +1100510 INIT_LIST_HEAD(&hostdata->unissued);
511 INIT_LIST_HEAD(&hostdata->disconnected);
512
Finn Thain55181be2016-01-03 16:05:42 +1100513 hostdata->flags = flags;
Finn Thainaff0cf92016-01-03 16:06:09 +1100514
Finn Thain8d8601a2016-01-03 16:05:37 +1100515 INIT_WORK(&hostdata->main_task, NCR5380_main);
Finn Thain0ad0eff2016-01-03 16:05:21 +1100516 hostdata->work_q = alloc_workqueue("ncr5380_%d",
517 WQ_UNBOUND | WQ_MEM_RECLAIM,
518 1, instance->host_no);
519 if (!hostdata->work_q)
520 return -ENOMEM;
521
Finn Thain8c325132014-11-12 16:11:58 +1100522 prepare_info(instance);
523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
525 NCR5380_write(MODE_REG, MR_BASE);
526 NCR5380_write(TARGET_COMMAND_REG, 0);
527 NCR5380_write(SELECT_ENABLE_REG, 0);
Finn Thain2f854b82016-01-03 16:05:22 +1100528
529 /* Calibrate register polling loop */
530 i = 0;
531 deadline = jiffies + 1;
532 do {
533 cpu_relax();
534 } while (time_is_after_jiffies(deadline));
535 deadline += msecs_to_jiffies(256);
536 do {
537 NCR5380_read(STATUS_REG);
538 ++i;
539 cpu_relax();
540 } while (time_is_after_jiffies(deadline));
541 hostdata->accesses_per_ms = i / 256;
542
Finn Thainb6488f92016-01-03 16:05:08 +1100543 return 0;
544}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Finn Thainb6488f92016-01-03 16:05:08 +1100546/**
547 * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems.
548 * @instance: adapter to check
549 *
550 * If the system crashed, it may have crashed with a connected target and
551 * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the
552 * currently established nexus, which we know nothing about. Failing that
553 * do a bus reset.
554 *
555 * Note that a bus reset will cause the chip to assert IRQ.
556 *
557 * Returns 0 if successful, otherwise -ENXIO.
558 */
559
560static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
561{
Finn Thain9c3f0e22016-01-03 16:05:11 +1100562 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Finn Thainb6488f92016-01-03 16:05:08 +1100563 int pass;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565 for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) {
566 switch (pass) {
567 case 1:
568 case 3:
569 case 5:
Finn Thain636b1ec2016-01-03 16:05:10 +1100570 shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
571 NCR5380_poll_politely(instance,
572 STATUS_REG, SR_BSY, 0, 5 * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 break;
574 case 2:
Finn Thain636b1ec2016-01-03 16:05:10 +1100575 shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 do_abort(instance);
577 break;
578 case 4:
Finn Thain636b1ec2016-01-03 16:05:10 +1100579 shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 do_reset(instance);
Finn Thain9c3f0e22016-01-03 16:05:11 +1100581 /* Wait after a reset; the SCSI standard calls for
582 * 250ms, we wait 500ms to be on the safe side.
583 * But some Toshiba CD-ROMs need ten times that.
584 */
585 if (hostdata->flags & FLAG_TOSHIBA_DELAY)
586 msleep(2500);
587 else
588 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 break;
590 case 6:
Finn Thain636b1ec2016-01-03 16:05:10 +1100591 shost_printk(KERN_ERR, instance, "bus locked solid\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 return -ENXIO;
593 }
594 }
595 return 0;
596}
597
598/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100599 * NCR5380_exit - remove an NCR5380
Finn Thain594d4ba2016-01-03 16:06:10 +1100600 * @instance: adapter to remove
Finn Thain0d2cf862016-01-03 16:06:11 +1100601 *
602 * Assumes that no more work can be queued (e.g. by NCR5380_intr).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 */
604
Randy Dunlapa43cf0f2008-01-22 21:39:33 -0800605static void NCR5380_exit(struct Scsi_Host *instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
Finn Thaine8a60142016-01-03 16:05:54 +1100607 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Finn Thain8d8601a2016-01-03 16:05:37 +1100609 cancel_work_sync(&hostdata->main_task);
Finn Thain0ad0eff2016-01-03 16:05:21 +1100610 destroy_workqueue(hostdata->work_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
613/**
Finn Thain677e0192016-01-03 16:05:59 +1100614 * complete_cmd - finish processing a command and return it to the SCSI ML
615 * @instance: the host instance
616 * @cmd: command to complete
617 */
618
619static void complete_cmd(struct Scsi_Host *instance,
620 struct scsi_cmnd *cmd)
621{
622 struct NCR5380_hostdata *hostdata = shost_priv(instance);
623
624 dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd);
625
Finn Thainf27db8e2016-01-03 16:06:00 +1100626 if (hostdata->sensing == cmd) {
627 /* Autosense processing ends here */
628 if ((cmd->result & 0xff) != SAM_STAT_GOOD) {
629 scsi_eh_restore_cmnd(cmd, &hostdata->ses);
630 set_host_byte(cmd, DID_ERROR);
631 } else
632 scsi_eh_restore_cmnd(cmd, &hostdata->ses);
633 hostdata->sensing = NULL;
634 }
635
Finn Thain677e0192016-01-03 16:05:59 +1100636 hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun);
637
638 cmd->scsi_done(cmd);
639}
640
641/**
Finn Thain1bb40582016-01-03 16:05:29 +1100642 * NCR5380_queue_command - queue a command
643 * @instance: the relevant SCSI adapter
644 * @cmd: SCSI command
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 *
Finn Thain1bb40582016-01-03 16:05:29 +1100646 * cmd is added to the per-instance issue queue, with minor
647 * twiddling done to the host specific fields of cmd. If the
648 * main coroutine is not running, it is restarted.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 */
650
Finn Thain1bb40582016-01-03 16:05:29 +1100651static int NCR5380_queue_command(struct Scsi_Host *instance,
652 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
Finn Thain1bb40582016-01-03 16:05:29 +1100654 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Finn Thain32b26a12016-01-03 16:05:58 +1100655 struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
Finn Thain1bb40582016-01-03 16:05:29 +1100656 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658#if (NDEBUG & NDEBUG_NO_WRITE)
659 switch (cmd->cmnd[0]) {
660 case WRITE_6:
661 case WRITE_10:
Finn Thaindbb6b352016-01-03 16:05:53 +1100662 shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 cmd->result = (DID_ERROR << 16);
Finn Thain1bb40582016-01-03 16:05:29 +1100664 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return 0;
666 }
Finn Thain0d2cf862016-01-03 16:06:11 +1100667#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 cmd->result = 0;
670
Finn Thain52d3e562016-03-23 21:10:20 +1100671 if (!NCR5380_acquire_dma_irq(instance))
672 return SCSI_MLQUEUE_HOST_BUSY;
673
Finn Thain11d2f632016-01-03 16:05:51 +1100674 spin_lock_irqsave(&hostdata->lock, flags);
Finn Thain1bb40582016-01-03 16:05:29 +1100675
Finn Thainaff0cf92016-01-03 16:06:09 +1100676 /*
677 * Insert the cmd into the issue queue. Note that REQUEST SENSE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 * commands are added to the head of the queue since any command will
Finn Thainaff0cf92016-01-03 16:06:09 +1100679 * clear the contingent allegiance condition that exists and the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 * sense data is only guaranteed to be valid while the condition exists.
681 */
682
Finn Thain32b26a12016-01-03 16:05:58 +1100683 if (cmd->cmnd[0] == REQUEST_SENSE)
684 list_add(&ncmd->list, &hostdata->unissued);
685 else
686 list_add_tail(&ncmd->list, &hostdata->unissued);
687
Finn Thain11d2f632016-01-03 16:05:51 +1100688 spin_unlock_irqrestore(&hostdata->lock, flags);
Finn Thain1bb40582016-01-03 16:05:29 +1100689
Finn Thaindbb6b352016-01-03 16:05:53 +1100690 dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n",
691 cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 /* Kick off command processing */
Finn Thain8d8601a2016-01-03 16:05:37 +1100694 queue_work(hostdata->work_q, &hostdata->main_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 return 0;
696}
697
Finn Thain52d3e562016-03-23 21:10:20 +1100698static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
699{
700 struct NCR5380_hostdata *hostdata = shost_priv(instance);
701
702 /* Caller does the locking needed to set & test these data atomically */
703 if (list_empty(&hostdata->disconnected) &&
704 list_empty(&hostdata->unissued) &&
705 list_empty(&hostdata->autosense) &&
706 !hostdata->connected &&
707 !hostdata->selecting)
708 NCR5380_release_dma_irq(instance);
709}
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711/**
Finn Thainf27db8e2016-01-03 16:06:00 +1100712 * dequeue_next_cmd - dequeue a command for processing
713 * @instance: the scsi host instance
714 *
715 * Priority is given to commands on the autosense queue. These commands
716 * need autosense because of a CHECK CONDITION result.
717 *
718 * Returns a command pointer if a command is found for a target that is
719 * not already busy. Otherwise returns NULL.
720 */
721
722static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance)
723{
724 struct NCR5380_hostdata *hostdata = shost_priv(instance);
725 struct NCR5380_cmd *ncmd;
726 struct scsi_cmnd *cmd;
727
Finn Thain8d5dbec2016-02-23 10:07:09 +1100728 if (hostdata->sensing || list_empty(&hostdata->autosense)) {
Finn Thainf27db8e2016-01-03 16:06:00 +1100729 list_for_each_entry(ncmd, &hostdata->unissued, list) {
730 cmd = NCR5380_to_scmd(ncmd);
731 dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n",
732 cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun);
733
734 if (!(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun))) {
735 list_del(&ncmd->list);
736 dsprintk(NDEBUG_QUEUES, instance,
737 "dequeue: removed %p from issue queue\n", cmd);
738 return cmd;
739 }
740 }
741 } else {
742 /* Autosense processing begins here */
743 ncmd = list_first_entry(&hostdata->autosense,
744 struct NCR5380_cmd, list);
745 list_del(&ncmd->list);
746 cmd = NCR5380_to_scmd(ncmd);
747 dsprintk(NDEBUG_QUEUES, instance,
748 "dequeue: removed %p from autosense queue\n", cmd);
749 scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
750 hostdata->sensing = cmd;
751 return cmd;
752 }
753 return NULL;
754}
755
756static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
757{
758 struct NCR5380_hostdata *hostdata = shost_priv(instance);
759 struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
760
Finn Thain8d5dbec2016-02-23 10:07:09 +1100761 if (hostdata->sensing == cmd) {
Finn Thainf27db8e2016-01-03 16:06:00 +1100762 scsi_eh_restore_cmnd(cmd, &hostdata->ses);
763 list_add(&ncmd->list, &hostdata->autosense);
764 hostdata->sensing = NULL;
765 } else
766 list_add(&ncmd->list, &hostdata->unissued);
767}
768
769/**
Finn Thain0d2cf862016-01-03 16:06:11 +1100770 * NCR5380_main - NCR state machines
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 *
Finn Thain594d4ba2016-01-03 16:06:10 +1100772 * NCR5380_main is a coroutine that runs as long as more work can
773 * be done on the NCR5380 host adapters in a system. Both
774 * NCR5380_queue_command() and NCR5380_intr() will try to start it
775 * in case it is not running.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 */
777
David Howellsc4028952006-11-22 14:57:56 +0000778static void NCR5380_main(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
David Howellsc4028952006-11-22 14:57:56 +0000780 struct NCR5380_hostdata *hostdata =
Finn Thain8d8601a2016-01-03 16:05:37 +1100781 container_of(work, struct NCR5380_hostdata, main_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 struct Scsi_Host *instance = hostdata->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 int done;
Finn Thainaff0cf92016-01-03 16:06:09 +1100784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 done = 1;
Finn Thain11d2f632016-01-03 16:05:51 +1100787
Finn Thain0a4e3612016-01-03 16:06:07 +1100788 spin_lock_irq(&hostdata->lock);
Finn Thainccf6efd2016-02-23 10:07:08 +1100789 while (!hostdata->connected && !hostdata->selecting) {
790 struct scsi_cmnd *cmd = dequeue_next_cmd(instance);
791
792 if (!cmd)
793 break;
Finn Thainf27db8e2016-01-03 16:06:00 +1100794
795 dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd);
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /*
Finn Thainf27db8e2016-01-03 16:06:00 +1100798 * Attempt to establish an I_T_L nexus here.
799 * On success, instance->hostdata->connected is set.
800 * On failure, we must add the command back to the
801 * issue queue so we can keep trying.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 */
Finn Thainf27db8e2016-01-03 16:06:00 +1100803 /*
804 * REQUEST SENSE commands are issued without tagged
805 * queueing, even on SCSI-II devices because the
806 * contingent allegiance condition exists for the
807 * entire unit.
808 */
Finn Thain32b26a12016-01-03 16:05:58 +1100809
Finn Thainccf6efd2016-02-23 10:07:08 +1100810 if (!NCR5380_select(instance, cmd)) {
Finn Thain707d62b2016-01-03 16:06:02 +1100811 dsprintk(NDEBUG_MAIN, instance, "main: select complete\n");
Finn Thain52d3e562016-03-23 21:10:20 +1100812 maybe_release_dma_irq(instance);
Finn Thainf27db8e2016-01-03 16:06:00 +1100813 } else {
814 dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance,
815 "main: select failed, returning %p to queue\n", cmd);
816 requeue_cmd(instance, cmd);
817 }
818 }
Finn Thaine4dec682016-03-23 21:10:12 +1100819 if (hostdata->connected && !hostdata->dma_len) {
Finn Thainb7465452016-01-03 16:06:05 +1100820 dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 NCR5380_information_transfer(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 done = 0;
Finn Thain1d3db592016-01-03 16:05:24 +1100823 }
Finn Thain0a4e3612016-01-03 16:06:07 +1100824 spin_unlock_irq(&hostdata->lock);
825 if (!done)
826 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 } while (!done);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
Finn Thain8053b0e2016-03-23 21:10:19 +1100830/*
831 * NCR5380_dma_complete - finish DMA transfer
832 * @instance: the scsi host instance
833 *
834 * Called by the interrupt handler when DMA finishes or a phase
835 * mismatch occurs (which would end the DMA transfer).
836 */
837
838static void NCR5380_dma_complete(struct Scsi_Host *instance)
839{
840 struct NCR5380_hostdata *hostdata = shost_priv(instance);
841 int transferred;
842 unsigned char **data;
843 int *count;
844 int saved_data = 0, overrun = 0;
845 unsigned char p;
846
847 if (hostdata->read_overruns) {
848 p = hostdata->connected->SCp.phase;
849 if (p & SR_IO) {
850 udelay(10);
851 if ((NCR5380_read(BUS_AND_STATUS_REG) &
852 (BASR_PHASE_MATCH | BASR_ACK)) ==
853 (BASR_PHASE_MATCH | BASR_ACK)) {
854 saved_data = NCR5380_read(INPUT_DATA_REG);
855 overrun = 1;
856 dsprintk(NDEBUG_DMA, instance, "read overrun handled\n");
857 }
858 }
859 }
860
861 NCR5380_write(MODE_REG, MR_BASE);
862 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
863 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
864
865 transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
866 hostdata->dma_len = 0;
867
868 data = (unsigned char **)&hostdata->connected->SCp.ptr;
869 count = &hostdata->connected->SCp.this_residual;
870 *data += transferred;
871 *count -= transferred;
872
873 if (hostdata->read_overruns) {
874 int cnt, toPIO;
875
876 if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
877 cnt = toPIO = hostdata->read_overruns;
878 if (overrun) {
879 dsprintk(NDEBUG_DMA, instance,
880 "Got an input overrun, using saved byte\n");
881 *(*data)++ = saved_data;
882 (*count)--;
883 cnt--;
884 toPIO--;
885 }
886 if (toPIO > 0) {
887 dsprintk(NDEBUG_DMA, instance,
888 "Doing %d byte PIO to 0x%p\n", cnt, *data);
889 NCR5380_transfer_pio(instance, &p, &cnt, data);
890 *count -= toPIO - cnt;
891 }
892 }
893 }
894}
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896#ifndef DONT_USE_INTR
897
898/**
Finn Thaincd400822016-01-03 16:05:40 +1100899 * NCR5380_intr - generic NCR5380 irq handler
900 * @irq: interrupt number
901 * @dev_id: device info
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 *
Finn Thaincd400822016-01-03 16:05:40 +1100903 * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
904 * from the disconnected queue, and restarting NCR5380_main()
905 * as required.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 *
Finn Thaincd400822016-01-03 16:05:40 +1100907 * The chip can assert IRQ in any of six different conditions. The IRQ flag
908 * is then cleared by reading the Reset Parity/Interrupt Register (RPIR).
909 * Three of these six conditions are latched in the Bus and Status Register:
910 * - End of DMA (cleared by ending DMA Mode)
911 * - Parity error (cleared by reading RPIR)
912 * - Loss of BSY (cleared by reading RPIR)
913 * Two conditions have flag bits that are not latched:
914 * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode)
915 * - Bus reset (non-maskable)
916 * The remaining condition has no flag bit at all:
917 * - Selection/reselection
918 *
919 * Hence, establishing the cause(s) of any interrupt is partly guesswork.
920 * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor
921 * claimed that "the design of the [DP8490] interrupt logic ensures
922 * interrupts will not be lost (they can be on the DP5380)."
923 * The L5380/53C80 datasheet from LOGIC Devices has more details.
924 *
925 * Checking for bus reset by reading RST is futile because of interrupt
926 * latency, but a bus reset will reset chip logic. Checking for parity error
927 * is unnecessary because that interrupt is never enabled. A Loss of BSY
928 * condition will clear DMA Mode. We can tell when this occurs because the
929 * the Busy Monitor interrupt is enabled together with DMA Mode.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 */
931
Finn Thaincd400822016-01-03 16:05:40 +1100932static irqreturn_t NCR5380_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Jeff Garzikbaa9aac2007-12-13 16:14:14 -0800934 struct Scsi_Host *instance = dev_id;
Finn Thaincd400822016-01-03 16:05:40 +1100935 struct NCR5380_hostdata *hostdata = shost_priv(instance);
936 int handled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 unsigned char basr;
938 unsigned long flags;
939
Finn Thain11d2f632016-01-03 16:05:51 +1100940 spin_lock_irqsave(&hostdata->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Finn Thaincd400822016-01-03 16:05:40 +1100942 basr = NCR5380_read(BUS_AND_STATUS_REG);
943 if (basr & BASR_IRQ) {
944 unsigned char mr = NCR5380_read(MODE_REG);
945 unsigned char sr = NCR5380_read(STATUS_REG);
946
Finn Thainb7465452016-01-03 16:06:05 +1100947 dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n",
948 irq, basr, sr, mr);
Finn Thaincd400822016-01-03 16:05:40 +1100949
Finn Thain8053b0e2016-03-23 21:10:19 +1100950 if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) {
951 /* Probably End of DMA, Phase Mismatch or Loss of BSY.
952 * We ack IRQ after clearing Mode Register. Workarounds
953 * for End of DMA errata need to happen in DMA Mode.
954 */
955
956 dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n");
957
958 if (hostdata->connected) {
959 NCR5380_dma_complete(instance);
960 queue_work(hostdata->work_q, &hostdata->main_task);
961 } else {
962 NCR5380_write(MODE_REG, MR_BASE);
963 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
964 }
965 } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) &&
Finn Thaincd400822016-01-03 16:05:40 +1100966 (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) {
967 /* Probably reselected */
968 NCR5380_write(SELECT_ENABLE_REG, 0);
969 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
970
Finn Thainb7465452016-01-03 16:06:05 +1100971 dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n");
Finn Thaincd400822016-01-03 16:05:40 +1100972
973 if (!hostdata->connected) {
974 NCR5380_reselect(instance);
975 queue_work(hostdata->work_q, &hostdata->main_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 }
Finn Thaincd400822016-01-03 16:05:40 +1100977 if (!hostdata->connected)
978 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
979 } else {
980 /* Probably Bus Reset */
981 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
982
Finn Thainb7465452016-01-03 16:06:05 +1100983 dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n");
Finn Thaincd400822016-01-03 16:05:40 +1100984 }
985 handled = 1;
986 } else {
987 shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n");
988 }
989
Finn Thain11d2f632016-01-03 16:05:51 +1100990 spin_unlock_irqrestore(&hostdata->lock, flags);
Finn Thaincd400822016-01-03 16:05:40 +1100991
992 return IRQ_RETVAL(handled);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993}
994
Finn Thainaff0cf92016-01-03 16:06:09 +1100995#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Finn Thainaff0cf92016-01-03 16:06:09 +1100997/*
Finn Thain710ddd02014-11-12 16:12:02 +1100998 * Function : int NCR5380_select(struct Scsi_Host *instance,
Finn Thain594d4ba2016-01-03 16:06:10 +1100999 * struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 *
1001 * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
Finn Thain594d4ba2016-01-03 16:06:10 +11001002 * including ARBITRATION, SELECTION, and initial message out for
1003 * IDENTIFY and queue messages.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001005 * Inputs : instance - instantiation of the 5380 driver on which this
Finn Thain594d4ba2016-01-03 16:06:10 +11001006 * target lives, cmd - SCSI command to execute.
Finn Thainaff0cf92016-01-03 16:06:09 +11001007 *
Finn Thain707d62b2016-01-03 16:06:02 +11001008 * Returns cmd if selection failed but should be retried,
1009 * NULL if selection failed and should not be retried, or
1010 * NULL if selection succeeded (hostdata->connected == cmd).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001012 * Side effects :
Finn Thain594d4ba2016-01-03 16:06:10 +11001013 * If bus busy, arbitration failed, etc, NCR5380_select() will exit
1014 * with registers as they should have been on entry - ie
1015 * SELECT_ENABLE will be set appropriately, the NCR5380
1016 * will cease to drive any SCSI bus signals.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 *
Finn Thain594d4ba2016-01-03 16:06:10 +11001018 * If successful : I_T_L or I_T_L_Q nexus will be established,
1019 * instance->connected will be set to cmd.
1020 * SELECT interrupt will be disabled.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 *
Finn Thain594d4ba2016-01-03 16:06:10 +11001022 * If failed (no target) : cmd->scsi_done() will be called, and the
1023 * cmd->result host byte set to DID_BAD_TARGET.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 */
Finn Thainaff0cf92016-01-03 16:06:09 +11001025
Finn Thain707d62b2016-01-03 16:06:02 +11001026static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
1027 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Finn Thaine8a60142016-01-03 16:05:54 +11001029 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 unsigned char tmp[3], phase;
1031 unsigned char *data;
1032 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 NCR5380_dprint(NDEBUG_ARBITRATION, instance);
Finn Thainb7465452016-01-03 16:06:05 +11001036 dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n",
1037 instance->this_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Finn Thain707d62b2016-01-03 16:06:02 +11001039 /*
1040 * Arbitration and selection phases are slow and involve dropping the
1041 * lock, so we have to watch out for EH. An exception handler may
1042 * change 'selecting' to NULL. This function will then return NULL
1043 * so that the caller will forget about 'cmd'. (During information
1044 * transfer phases, EH may change 'connected' to NULL.)
1045 */
1046 hostdata->selecting = cmd;
1047
Finn Thainaff0cf92016-01-03 16:06:09 +11001048 /*
1049 * Set the phase bits to 0, otherwise the NCR5380 won't drive the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 * data bus during SELECTION.
1051 */
1052
1053 NCR5380_write(TARGET_COMMAND_REG, 0);
1054
Finn Thainaff0cf92016-01-03 16:06:09 +11001055 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 * Start arbitration.
1057 */
1058
1059 NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
1060 NCR5380_write(MODE_REG, MR_ARBITRATE);
1061
Finn Thain55500d92016-01-03 16:05:35 +11001062 /* The chip now waits for BUS FREE phase. Then after the 800 ns
1063 * Bus Free Delay, arbitration will begin.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 */
1065
Finn Thain11d2f632016-01-03 16:05:51 +11001066 spin_unlock_irq(&hostdata->lock);
Finn Thainb32ade12016-01-03 16:05:41 +11001067 err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0,
1068 INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
1069 ICR_ARBITRATION_PROGRESS, HZ);
Finn Thain11d2f632016-01-03 16:05:51 +11001070 spin_lock_irq(&hostdata->lock);
Finn Thainb32ade12016-01-03 16:05:41 +11001071 if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
1072 /* Reselection interrupt */
Finn Thain707d62b2016-01-03 16:06:02 +11001073 goto out;
Finn Thainb32ade12016-01-03 16:05:41 +11001074 }
Finn Thainccf6efd2016-02-23 10:07:08 +11001075 if (!hostdata->selecting) {
1076 /* Command was aborted */
1077 NCR5380_write(MODE_REG, MR_BASE);
1078 goto out;
1079 }
Finn Thainb32ade12016-01-03 16:05:41 +11001080 if (err < 0) {
1081 NCR5380_write(MODE_REG, MR_BASE);
1082 shost_printk(KERN_ERR, instance,
1083 "select: arbitration timeout\n");
Finn Thain707d62b2016-01-03 16:06:02 +11001084 goto out;
Finn Thain55500d92016-01-03 16:05:35 +11001085 }
Finn Thain11d2f632016-01-03 16:05:51 +11001086 spin_unlock_irq(&hostdata->lock);
Finn Thain55500d92016-01-03 16:05:35 +11001087
1088 /* The SCSI-2 arbitration delay is 2.4 us */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 udelay(3);
1090
1091 /* Check for lost arbitration */
Finn Thain0d2cf862016-01-03 16:06:11 +11001092 if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
1093 (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
1094 (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 NCR5380_write(MODE_REG, MR_BASE);
Finn Thainb7465452016-01-03 16:06:05 +11001096 dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n");
Finn Thain11d2f632016-01-03 16:05:51 +11001097 spin_lock_irq(&hostdata->lock);
Finn Thain707d62b2016-01-03 16:06:02 +11001098 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 }
Finn Thaincf13b082016-01-03 16:05:18 +11001100
1101 /* After/during arbitration, BSY should be asserted.
1102 * IBM DPES-31080 Version S31Q works now
1103 * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman)
1104 */
1105 NCR5380_write(INITIATOR_COMMAND_REG,
1106 ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Finn Thainaff0cf92016-01-03 16:06:09 +11001108 /*
1109 * Again, bus clear + bus settle time is 1.2us, however, this is
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 * a minimum so we'll udelay ceil(1.2)
1111 */
1112
Finn Thain9c3f0e22016-01-03 16:05:11 +11001113 if (hostdata->flags & FLAG_TOSHIBA_DELAY)
1114 udelay(15);
1115 else
1116 udelay(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Finn Thain11d2f632016-01-03 16:05:51 +11001118 spin_lock_irq(&hostdata->lock);
1119
Finn Thain72064a72016-01-03 16:05:44 +11001120 /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */
1121 if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE))
Finn Thain707d62b2016-01-03 16:06:02 +11001122 goto out;
1123
1124 if (!hostdata->selecting) {
1125 NCR5380_write(MODE_REG, MR_BASE);
1126 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1127 goto out;
1128 }
Finn Thain72064a72016-01-03 16:05:44 +11001129
Finn Thainb7465452016-01-03 16:06:05 +11001130 dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Finn Thainaff0cf92016-01-03 16:06:09 +11001132 /*
1133 * Now that we have won arbitration, start Selection process, asserting
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 * the host and target ID's on the SCSI bus.
1135 */
1136
Finn Thain3d07d222016-01-03 16:06:13 +11001137 NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask | (1 << scmd_id(cmd)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
Finn Thainaff0cf92016-01-03 16:06:09 +11001139 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 * Raise ATN while SEL is true before BSY goes false from arbitration,
1141 * since this is the only way to guarantee that we'll get a MESSAGE OUT
1142 * phase immediately after selection.
1143 */
1144
Finn Thain3d07d222016-01-03 16:06:13 +11001145 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY |
1146 ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 NCR5380_write(MODE_REG, MR_BASE);
1148
Finn Thainaff0cf92016-01-03 16:06:09 +11001149 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 * Reselect interrupts must be turned off prior to the dropping of BSY,
1151 * otherwise we will trigger an interrupt.
1152 */
1153 NCR5380_write(SELECT_ENABLE_REG, 0);
1154
Finn Thain11d2f632016-01-03 16:05:51 +11001155 spin_unlock_irq(&hostdata->lock);
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 /*
Finn Thainaff0cf92016-01-03 16:06:09 +11001158 * The initiator shall then wait at least two deskew delays and release
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 * the BSY signal.
1160 */
Finn Thain0d2cf862016-01-03 16:06:11 +11001161 udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163 /* Reset BSY */
Finn Thain3d07d222016-01-03 16:06:13 +11001164 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA |
1165 ICR_ASSERT_ATN | ICR_ASSERT_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
Finn Thainaff0cf92016-01-03 16:06:09 +11001167 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 * Something weird happens when we cease to drive BSY - looks
Finn Thainaff0cf92016-01-03 16:06:09 +11001169 * like the board/chip is letting us do another read before the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 * appropriate propagation delay has expired, and we're confusing
1171 * a BSY signal from ourselves as the target's response to SELECTION.
1172 *
1173 * A small delay (the 'C++' frontend breaks the pipeline with an
1174 * unnecessary jump, making it work on my 386-33/Trantor T128, the
Finn Thainaff0cf92016-01-03 16:06:09 +11001175 * tighter 'C' code breaks and requires this) solves the problem -
1176 * the 1 us delay is arbitrary, and only used because this delay will
1177 * be the same on other platforms and since it works here, it should
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 * work there.
1179 *
1180 * wingel suggests that this could be due to failing to wait
1181 * one deskew delay.
1182 */
1183
1184 udelay(1);
1185
Finn Thainb7465452016-01-03 16:06:05 +11001186 dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
Finn Thainaff0cf92016-01-03 16:06:09 +11001188 /*
1189 * The SCSI specification calls for a 250 ms timeout for the actual
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 * selection.
1191 */
1192
Finn Thainae753a32016-01-03 16:05:23 +11001193 err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY,
1194 msecs_to_jiffies(250));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
Finn Thain11d2f632016-01-03 16:05:51 +11001197 spin_lock_irq(&hostdata->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1199 NCR5380_reselect(instance);
Finn Thaincd400822016-01-03 16:05:40 +11001200 if (!hostdata->connected)
1201 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
Finn Thain6a6ff4a2016-01-03 16:06:04 +11001202 shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n");
Finn Thain707d62b2016-01-03 16:06:02 +11001203 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 }
Finn Thainae753a32016-01-03 16:05:23 +11001205
1206 if (err < 0) {
Finn Thain11d2f632016-01-03 16:05:51 +11001207 spin_lock_irq(&hostdata->lock);
Finn Thainae753a32016-01-03 16:05:23 +11001208 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
Finn Thainae753a32016-01-03 16:05:23 +11001209 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
Finn Thain707d62b2016-01-03 16:06:02 +11001210 /* Can't touch cmd if it has been reclaimed by the scsi ML */
1211 if (hostdata->selecting) {
1212 cmd->result = DID_BAD_TARGET << 16;
1213 complete_cmd(instance, cmd);
1214 dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n");
1215 cmd = NULL;
1216 }
1217 goto out;
Finn Thainae753a32016-01-03 16:05:23 +11001218 }
1219
Finn Thainaff0cf92016-01-03 16:06:09 +11001220 /*
1221 * No less than two deskew delays after the initiator detects the
1222 * BSY signal is true, it shall release the SEL signal and may
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 * change the DATA BUS. -wingel
1224 */
1225
1226 udelay(1);
1227
1228 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
1229
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 /*
Finn Thainaff0cf92016-01-03 16:06:09 +11001231 * Since we followed the SCSI spec, and raised ATN while SEL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 * was true but before BSY was false during selection, the information
1233 * transfer phase should be a MESSAGE OUT phase so that we can send the
1234 * IDENTIFY message.
Finn Thainaff0cf92016-01-03 16:06:09 +11001235 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
1237 * message (2 bytes) with a tag ID that we increment with every command
1238 * until it wraps back to 0.
1239 *
1240 * XXX - it turns out that there are some broken SCSI-II devices,
Finn Thain594d4ba2016-01-03 16:06:10 +11001241 * which claim to support tagged queuing but fail when more than
1242 * some number of commands are issued at once.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 */
1244
1245 /* Wait for start of REQ/ACK handshake */
1246
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
Finn Thain11d2f632016-01-03 16:05:51 +11001248 spin_lock_irq(&hostdata->lock);
Finn Thain1cc160e2016-01-03 16:05:32 +11001249 if (err < 0) {
Finn Thain55500d92016-01-03 16:05:35 +11001250 shost_printk(KERN_ERR, instance, "select: REQ timeout\n");
1251 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
Finn Thain707d62b2016-01-03 16:06:02 +11001253 goto out;
1254 }
1255 if (!hostdata->selecting) {
1256 do_abort(instance);
1257 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 }
1259
Finn Thainb7465452016-01-03 16:06:05 +11001260 dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n",
1261 scmd_id(cmd));
Finn Thain22f5f102014-11-12 16:11:56 +11001262 tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
1264 len = 1;
1265 cmd->tag = 0;
1266
1267 /* Send message(s) */
1268 data = tmp;
1269 phase = PHASE_MSGOUT;
1270 NCR5380_transfer_pio(instance, &phase, &len, &data);
Finn Thainb7465452016-01-03 16:06:05 +11001271 dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 /* XXX need to handle errors here */
Finn Thain11d2f632016-01-03 16:05:51 +11001273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 hostdata->connected = cmd;
Finn Thain3d07d222016-01-03 16:06:13 +11001275 hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Boaz Harrosh28424d32007-09-10 22:37:45 +03001277 initialize_SCp(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Finn Thain707d62b2016-01-03 16:06:02 +11001279 cmd = NULL;
1280
1281out:
1282 if (!hostdata->selecting)
1283 return NULL;
1284 hostdata->selecting = NULL;
1285 return cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286}
1287
Finn Thainaff0cf92016-01-03 16:06:09 +11001288/*
1289 * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
Finn Thain594d4ba2016-01-03 16:06:10 +11001290 * unsigned char *phase, int *count, unsigned char **data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 *
1292 * Purpose : transfers data in given phase using polled I/O
1293 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001294 * Inputs : instance - instance of driver, *phase - pointer to
Finn Thain594d4ba2016-01-03 16:06:10 +11001295 * what phase is expected, *count - pointer to number of
1296 * bytes to transfer, **data - pointer to data pointer.
Finn Thainaff0cf92016-01-03 16:06:09 +11001297 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 * Returns : -1 when different phase is entered without transferring
Finn Thain0d2cf862016-01-03 16:06:11 +11001299 * maximum number of bytes, 0 if all bytes are transferred or exit
Finn Thain594d4ba2016-01-03 16:06:10 +11001300 * is in same phase.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 *
Finn Thain594d4ba2016-01-03 16:06:10 +11001302 * Also, *phase, *count, *data are modified in place.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 *
1304 * XXX Note : handling for bus free may be useful.
1305 */
1306
1307/*
Finn Thainaff0cf92016-01-03 16:06:09 +11001308 * Note : this code is not as quick as it could be, however it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 * IS 100% reliable, and for the actual data transfer where speed
1310 * counts, we will always do a pseudo DMA or DMA transfer.
1311 */
1312
Finn Thain0d2cf862016-01-03 16:06:11 +11001313static int NCR5380_transfer_pio(struct Scsi_Host *instance,
1314 unsigned char *phase, int *count,
1315 unsigned char **data)
1316{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 unsigned char p = *phase, tmp;
1318 int c = *count;
1319 unsigned char *d = *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Finn Thainaff0cf92016-01-03 16:06:09 +11001321 /*
1322 * The NCR5380 chip will only drive the SCSI bus when the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 * phase specified in the appropriate bits of the TARGET COMMAND
1324 * REGISTER match the STATUS REGISTER
1325 */
1326
Finn Thain0d2cf862016-01-03 16:06:11 +11001327 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 do {
Finn Thainaff0cf92016-01-03 16:06:09 +11001330 /*
1331 * Wait for assertion of REQ, after which the phase bits will be
1332 * valid
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 */
1334
Finn Thain686f3992016-01-03 16:05:26 +11001335 if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Finn Thainb7465452016-01-03 16:06:05 +11001338 dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
1340 /* Check for phase mismatch */
Finn Thain686f3992016-01-03 16:05:26 +11001341 if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) {
Finn Thainb7465452016-01-03 16:06:05 +11001342 dsprintk(NDEBUG_PIO, instance, "phase mismatch\n");
1343 NCR5380_dprint_phase(NDEBUG_PIO, instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 break;
1345 }
Finn Thain0d2cf862016-01-03 16:06:11 +11001346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 /* Do actual transfer from SCSI bus to / from memory */
1348 if (!(p & SR_IO))
1349 NCR5380_write(OUTPUT_DATA_REG, *d);
1350 else
1351 *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
1352
1353 ++d;
1354
Finn Thainaff0cf92016-01-03 16:06:09 +11001355 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 * The SCSI standard suggests that in MSGOUT phase, the initiator
1357 * should drop ATN on the last byte of the message phase
1358 * after REQ has been asserted for the handshake but before
1359 * the initiator raises ACK.
1360 */
1361
1362 if (!(p & SR_IO)) {
1363 if (!((p & SR_MSG) && c > 1)) {
1364 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
1365 NCR5380_dprint(NDEBUG_PIO, instance);
Finn Thain3d07d222016-01-03 16:06:13 +11001366 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
1367 ICR_ASSERT_DATA | ICR_ASSERT_ACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 } else {
Finn Thain3d07d222016-01-03 16:06:13 +11001369 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
1370 ICR_ASSERT_DATA | ICR_ASSERT_ATN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 NCR5380_dprint(NDEBUG_PIO, instance);
Finn Thain3d07d222016-01-03 16:06:13 +11001372 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
1373 ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
1375 } else {
1376 NCR5380_dprint(NDEBUG_PIO, instance);
1377 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
1378 }
1379
Finn Thaina2edc4a2016-01-03 16:05:27 +11001380 if (NCR5380_poll_politely(instance,
1381 STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
1382 break;
1383
Finn Thainb7465452016-01-03 16:06:05 +11001384 dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386/*
Finn Thainaff0cf92016-01-03 16:06:09 +11001387 * We have several special cases to consider during REQ/ACK handshaking :
1388 * 1. We were in MSGOUT phase, and we are on the last byte of the
Finn Thain594d4ba2016-01-03 16:06:10 +11001389 * message. ATN must be dropped as ACK is dropped.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001391 * 2. We are in a MSGIN phase, and we are on the last byte of the
Finn Thain594d4ba2016-01-03 16:06:10 +11001392 * message. We must exit with ACK asserted, so that the calling
1393 * code may raise ATN before dropping ACK to reject the message.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 *
1395 * 3. ACK and ATN are clear and the target may proceed as normal.
1396 */
1397 if (!(p == PHASE_MSGIN && c == 1)) {
1398 if (p == PHASE_MSGOUT && c > 1)
1399 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
1400 else
1401 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1402 }
1403 } while (--c);
1404
Finn Thainb7465452016-01-03 16:06:05 +11001405 dsprintk(NDEBUG_PIO, instance, "residual %d\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
1407 *count = c;
1408 *data = d;
1409 tmp = NCR5380_read(STATUS_REG);
Finn Thaina2edc4a2016-01-03 16:05:27 +11001410 /* The phase read from the bus is valid if either REQ is (already)
1411 * asserted or if ACK hasn't been released yet. The latter applies if
1412 * we're in MSG IN, DATA IN or STATUS and all bytes have been received.
1413 */
1414 if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 *phase = tmp & PHASE_MASK;
1416 else
1417 *phase = PHASE_UNKNOWN;
1418
1419 if (!c || (*phase == p))
1420 return 0;
1421 else
1422 return -1;
1423}
1424
1425/**
Finn Thain636b1ec2016-01-03 16:05:10 +11001426 * do_reset - issue a reset command
1427 * @instance: adapter to reset
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 *
Finn Thain636b1ec2016-01-03 16:05:10 +11001429 * Issue a reset sequence to the NCR5380 and try and get the bus
1430 * back into sane shape.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 *
Finn Thain636b1ec2016-01-03 16:05:10 +11001432 * This clears the reset interrupt flag because there may be no handler for
1433 * it. When the driver is initialized, the NCR5380_intr() handler has not yet
1434 * been installed. And when in EH we may have released the ST DMA interrupt.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 */
Finn Thainaff0cf92016-01-03 16:06:09 +11001436
Finn Thain54d8fe42016-01-03 16:05:06 +11001437static void do_reset(struct Scsi_Host *instance)
1438{
Finn Thain636b1ec2016-01-03 16:05:10 +11001439 unsigned long flags;
1440
1441 local_irq_save(flags);
1442 NCR5380_write(TARGET_COMMAND_REG,
1443 PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
Finn Thain636b1ec2016-01-03 16:05:10 +11001445 udelay(50);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
Finn Thain636b1ec2016-01-03 16:05:10 +11001447 (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
1448 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449}
1450
Finn Thain80d3eb62016-01-03 16:05:34 +11001451/**
1452 * do_abort - abort the currently established nexus by going to
1453 * MESSAGE OUT phase and sending an ABORT message.
1454 * @instance: relevant scsi host instance
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 *
Finn Thain80d3eb62016-01-03 16:05:34 +11001456 * Returns 0 on success, -1 on failure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 */
1458
Finn Thain54d8fe42016-01-03 16:05:06 +11001459static int do_abort(struct Scsi_Host *instance)
1460{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 unsigned char *msgptr, phase, tmp;
1462 int len;
1463 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 /* Request message out phase */
1466 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
1467
Finn Thainaff0cf92016-01-03 16:06:09 +11001468 /*
1469 * Wait for the target to indicate a valid phase by asserting
1470 * REQ. Once this happens, we'll have either a MSGOUT phase
1471 * and can immediately send the ABORT message, or we'll have some
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 * other phase and will have to source/sink data.
Finn Thainaff0cf92016-01-03 16:06:09 +11001473 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 * We really don't care what value was on the bus or what value
1475 * the target sees, so we just handshake.
1476 */
1477
Finn Thain80d3eb62016-01-03 16:05:34 +11001478 rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
Finn Thain1cc160e2016-01-03 16:05:32 +11001479 if (rc < 0)
Finn Thain80d3eb62016-01-03 16:05:34 +11001480 goto timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Finn Thainf35d3472016-01-03 16:05:33 +11001482 tmp = NCR5380_read(STATUS_REG) & PHASE_MASK;
Finn Thainaff0cf92016-01-03 16:06:09 +11001483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
1485
Finn Thainf35d3472016-01-03 16:05:33 +11001486 if (tmp != PHASE_MSGOUT) {
Finn Thain0d2cf862016-01-03 16:06:11 +11001487 NCR5380_write(INITIATOR_COMMAND_REG,
1488 ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
Finn Thain54d8fe42016-01-03 16:05:06 +11001489 rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ);
Finn Thain1cc160e2016-01-03 16:05:32 +11001490 if (rc < 0)
Finn Thain80d3eb62016-01-03 16:05:34 +11001491 goto timeout;
1492 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 }
Finn Thain0d2cf862016-01-03 16:06:11 +11001494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 tmp = ABORT;
1496 msgptr = &tmp;
1497 len = 1;
1498 phase = PHASE_MSGOUT;
Finn Thain54d8fe42016-01-03 16:05:06 +11001499 NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 /*
1502 * If we got here, and the command completed successfully,
1503 * we're about to go into bus free state.
1504 */
1505
1506 return len ? -1 : 0;
Finn Thain80d3eb62016-01-03 16:05:34 +11001507
1508timeout:
1509 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1510 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511}
1512
Finn Thainaff0cf92016-01-03 16:06:09 +11001513/*
1514 * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
Finn Thain594d4ba2016-01-03 16:06:10 +11001515 * unsigned char *phase, int *count, unsigned char **data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 *
1517 * Purpose : transfers data in given phase using either real
Finn Thain594d4ba2016-01-03 16:06:10 +11001518 * or pseudo DMA.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001520 * Inputs : instance - instance of driver, *phase - pointer to
Finn Thain594d4ba2016-01-03 16:06:10 +11001521 * what phase is expected, *count - pointer to number of
1522 * bytes to transfer, **data - pointer to data pointer.
Finn Thainaff0cf92016-01-03 16:06:09 +11001523 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 * Returns : -1 when different phase is entered without transferring
Finn Thain594d4ba2016-01-03 16:06:10 +11001525 * maximum number of bytes, 0 if all bytes or transferred or exit
1526 * is in same phase.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 *
Finn Thain594d4ba2016-01-03 16:06:10 +11001528 * Also, *phase, *count, *data are modified in place.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 */
1530
1531
Finn Thain0d2cf862016-01-03 16:06:11 +11001532static int NCR5380_transfer_dma(struct Scsi_Host *instance,
1533 unsigned char *phase, int *count,
1534 unsigned char **data)
1535{
1536 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 register int c = *count;
1538 register unsigned char p = *phase;
1539 register unsigned char *d = *data;
1540 unsigned char tmp;
Finn Thain8053b0e2016-03-23 21:10:19 +11001541 int result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
1544 *phase = tmp;
1545 return -1;
1546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Finn Thain8053b0e2016-03-23 21:10:19 +11001548 hostdata->connected->SCp.phase = p;
1549
1550 if (p & SR_IO) {
1551 if (hostdata->read_overruns)
1552 c -= hostdata->read_overruns;
1553 else if (hostdata->flags & FLAG_DMA_FIXUP)
1554 --c;
1555 }
1556
1557 dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n",
1558 (p & SR_IO) ? "receive" : "send", c, d);
1559
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
Finn Thain8053b0e2016-03-23 21:10:19 +11001561 NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
1562 MR_ENABLE_EOP_INTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Finn Thain8053b0e2016-03-23 21:10:19 +11001564 if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) {
1565 /* On the Medusa, it is a must to initialize the DMA before
1566 * starting the NCR. This is also the cleaner way for the TT.
1567 */
1568 if (p & SR_IO)
1569 result = NCR5380_dma_recv_setup(instance, d, c);
1570 else
1571 result = NCR5380_dma_send_setup(instance, d, c);
1572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
Finn Thainaff0cf92016-01-03 16:06:09 +11001574 /*
Finn Thain594d4ba2016-01-03 16:06:10 +11001575 * On the PAS16 at least I/O recovery delays are not needed here.
1576 * Everyone else seems to want them.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 */
1578
1579 if (p & SR_IO) {
Finn Thaine5d55d12016-03-23 21:10:16 +11001580 NCR5380_io_delay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
1582 } else {
Finn Thaine5d55d12016-03-23 21:10:16 +11001583 NCR5380_io_delay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
Finn Thaine5d55d12016-03-23 21:10:16 +11001585 NCR5380_io_delay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 NCR5380_write(START_DMA_SEND_REG, 0);
Finn Thaine5d55d12016-03-23 21:10:16 +11001587 NCR5380_io_delay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 }
1589
Finn Thain8053b0e2016-03-23 21:10:19 +11001590 if (hostdata->flags & FLAG_LATE_DMA_SETUP) {
1591 /* On the Falcon, the DMA setup must be done after the last
1592 * NCR access, else the DMA setup gets trashed!
1593 */
1594 if (p & SR_IO)
1595 result = NCR5380_dma_recv_setup(instance, d, c);
1596 else
1597 result = NCR5380_dma_send_setup(instance, d, c);
1598 }
1599
1600 /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */
1601 if (result < 0)
1602 return result;
1603
1604 /* For real DMA, result is the byte count. DMA interrupt is expected. */
1605 if (result > 0) {
1606 hostdata->dma_len = result;
1607 return 0;
1608 }
1609
1610 /* The result is zero iff pseudo DMA send/receive was completed. */
1611 hostdata->dma_len = c;
1612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613/*
Finn Thaine4dec682016-03-23 21:10:12 +11001614 * A note regarding the DMA errata workarounds for early NMOS silicon.
Finn Thainc16df322016-01-03 16:06:08 +11001615 *
1616 * For DMA sends, we want to wait until the last byte has been
1617 * transferred out over the bus before we turn off DMA mode. Alas, there
1618 * seems to be no terribly good way of doing this on a 5380 under all
1619 * conditions. For non-scatter-gather operations, we can wait until REQ
1620 * and ACK both go false, or until a phase mismatch occurs. Gather-sends
1621 * are nastier, since the device will be expecting more data than we
1622 * are prepared to send it, and REQ will remain asserted. On a 53C8[01] we
1623 * could test Last Byte Sent to assure transfer (I imagine this is precisely
1624 * why this signal was added to the newer chips) but on the older 538[01]
1625 * this signal does not exist. The workaround for this lack is a watchdog;
1626 * we bail out of the wait-loop after a modest amount of wait-time if
1627 * the usual exit conditions are not met. Not a terribly clean or
1628 * correct solution :-%
1629 *
1630 * DMA receive is equally tricky due to a nasty characteristic of the NCR5380.
1631 * If the chip is in DMA receive mode, it will respond to a target's
1632 * REQ by latching the SCSI data into the INPUT DATA register and asserting
1633 * ACK, even if it has _already_ been notified by the DMA controller that
1634 * the current DMA transfer has completed! If the NCR5380 is then taken
1635 * out of DMA mode, this already-acknowledged byte is lost. This is
1636 * not a problem for "one DMA transfer per READ command", because
1637 * the situation will never arise... either all of the data is DMA'ed
1638 * properly, or the target switches to MESSAGE IN phase to signal a
1639 * disconnection (either operation bringing the DMA to a clean halt).
1640 * However, in order to handle scatter-receive, we must work around the
Finn Thaine4dec682016-03-23 21:10:12 +11001641 * problem. The chosen fix is to DMA fewer bytes, then check for the
Finn Thainc16df322016-01-03 16:06:08 +11001642 * condition before taking the NCR5380 out of DMA mode. One or two extra
1643 * bytes are transferred via PIO as necessary to fill out the original
1644 * request.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 */
1646
Finn Thain8053b0e2016-03-23 21:10:19 +11001647 if (hostdata->flags & FLAG_DMA_FIXUP) {
1648 if (p & SR_IO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 /*
Finn Thaine4dec682016-03-23 21:10:12 +11001650 * The workaround was to transfer fewer bytes than we
Finn Thainaff0cf92016-01-03 16:06:09 +11001651 * intended to with the pseudo-DMA read function, wait for
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 * the chip to latch the last byte, read it, and then disable
1653 * pseudo-DMA mode.
Finn Thainaff0cf92016-01-03 16:06:09 +11001654 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 * After REQ is asserted, the NCR5380 asserts DRQ and ACK.
1656 * REQ is deasserted when ACK is asserted, and not reasserted
1657 * until ACK goes false. Since the NCR5380 won't lower ACK
1658 * until DACK is asserted, which won't happen unless we twiddle
Finn Thainaff0cf92016-01-03 16:06:09 +11001659 * the DMA port or we take the NCR5380 out of DMA mode, we
1660 * can guarantee that we won't handshake another extra
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 * byte.
1662 */
1663
Finn Thain55181be2016-01-03 16:05:42 +11001664 if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG,
1665 BASR_DRQ, BASR_DRQ, HZ) < 0) {
Finn Thain438af512016-03-23 21:10:18 +11001666 result = -1;
Finn Thain55181be2016-01-03 16:05:42 +11001667 shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
Finn Thain55181be2016-01-03 16:05:42 +11001669 if (NCR5380_poll_politely(instance, STATUS_REG,
1670 SR_REQ, 0, HZ) < 0) {
Finn Thain438af512016-03-23 21:10:18 +11001671 result = -1;
Finn Thain55181be2016-01-03 16:05:42 +11001672 shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
1673 }
Finn Thain8053b0e2016-03-23 21:10:19 +11001674 d[*count - 1] = NCR5380_read(INPUT_DATA_REG);
1675 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 /*
Finn Thainaff0cf92016-01-03 16:06:09 +11001677 * Wait for the last byte to be sent. If REQ is being asserted for
1678 * the byte we're interested, we'll ACK it and it will go false.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 */
Finn Thain55181be2016-01-03 16:05:42 +11001680 if (NCR5380_poll_politely2(instance,
1681 BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
1682 BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) {
Finn Thain438af512016-03-23 21:10:18 +11001683 result = -1;
Finn Thain55181be2016-01-03 16:05:42 +11001684 shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 }
1686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
Finn Thain8053b0e2016-03-23 21:10:19 +11001688
1689 NCR5380_dma_complete(instance);
Finn Thain438af512016-03-23 21:10:18 +11001690 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
1693/*
1694 * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
1695 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001696 * Purpose : run through the various SCSI phases and do as the target
Finn Thain594d4ba2016-01-03 16:06:10 +11001697 * directs us to. Operates on the currently connected command,
1698 * instance->connected.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 *
1700 * Inputs : instance, instance for which we are doing commands
1701 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001702 * Side effects : SCSI things happen, the disconnected queue will be
Finn Thain594d4ba2016-01-03 16:06:10 +11001703 * modified if a command disconnects, *instance->connected will
1704 * change.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001706 * XXX Note : we need to watch for bus free or a reset condition here
Finn Thain594d4ba2016-01-03 16:06:10 +11001707 * to recover from an unexpected bus free condition.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 */
1709
Finn Thain0d2cf862016-01-03 16:06:11 +11001710static void NCR5380_information_transfer(struct Scsi_Host *instance)
1711{
Finn Thaine8a60142016-01-03 16:05:54 +11001712 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 unsigned char msgout = NOP;
1714 int sink = 0;
1715 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 int transfersize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 unsigned char *data;
1718 unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
Finn Thain11d2f632016-01-03 16:05:51 +11001719 struct scsi_cmnd *cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
Finn Thain11d2f632016-01-03 16:05:51 +11001721 while ((cmd = hostdata->connected)) {
Finn Thain32b26a12016-01-03 16:05:58 +11001722 struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
1723
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 tmp = NCR5380_read(STATUS_REG);
1725 /* We only have a valid SCSI phase when REQ is asserted */
1726 if (tmp & SR_REQ) {
1727 phase = (tmp & PHASE_MASK);
1728 if (phase != old_phase) {
1729 old_phase = phase;
1730 NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
1731 }
1732 if (sink && (phase != PHASE_MSGOUT)) {
1733 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
1734
Finn Thain3d07d222016-01-03 16:06:13 +11001735 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
1736 ICR_ASSERT_ACK);
Finn Thain0d2cf862016-01-03 16:06:11 +11001737 while (NCR5380_read(STATUS_REG) & SR_REQ)
1738 ;
Finn Thain3d07d222016-01-03 16:06:13 +11001739 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
1740 ICR_ASSERT_ATN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 sink = 0;
1742 continue;
1743 }
Finn Thain0d2cf862016-01-03 16:06:11 +11001744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 switch (phase) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 case PHASE_DATAOUT:
1747#if (NDEBUG & NDEBUG_NO_DATAOUT)
Finn Thain6a6ff4a2016-01-03 16:06:04 +11001748 shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 sink = 1;
1750 do_abort(instance);
1751 cmd->result = DID_ERROR << 16;
Finn Thain677e0192016-01-03 16:05:59 +11001752 complete_cmd(instance, cmd);
Finn Thaindc183962016-02-23 10:07:07 +11001753 hostdata->connected = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return;
1755#endif
Finn Thainbf1a0c62016-01-03 16:05:47 +11001756 case PHASE_DATAIN:
Finn Thainaff0cf92016-01-03 16:06:09 +11001757 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 * If there is no room left in the current buffer in the
1759 * scatter-gather list, move onto the next one.
1760 */
1761
1762 if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
1763 ++cmd->SCp.buffer;
1764 --cmd->SCp.buffers_residual;
1765 cmd->SCp.this_residual = cmd->SCp.buffer->length;
Jens Axboe45711f12007-10-22 21:19:53 +02001766 cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
Finn Thainb7465452016-01-03 16:06:05 +11001767 dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n",
1768 cmd->SCp.this_residual,
1769 cmd->SCp.buffers_residual);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 }
Finn Thain0d2cf862016-01-03 16:06:11 +11001771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 /*
Finn Thainaff0cf92016-01-03 16:06:09 +11001773 * The preferred transfer method is going to be
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 * PSEUDO-DMA for systems that are strictly PIO,
1775 * since we can let the hardware do the handshaking.
1776 *
1777 * For this to work, we need to know the transfersize
1778 * ahead of time, since the pseudo-DMA code will sit
1779 * in an unconditional loop.
1780 */
1781
Finn Thainff3d4572016-01-03 16:05:25 +11001782 transfersize = 0;
Finn Thain7e9ec8d2016-03-23 21:10:11 +11001783 if (!cmd->device->borken)
Finn Thainff3d4572016-01-03 16:05:25 +11001784 transfersize = NCR5380_dma_xfer_len(instance, cmd, phase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Finn Thain438af512016-03-23 21:10:18 +11001786 if (transfersize > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 len = transfersize;
Finn Thain0d2cf862016-01-03 16:06:11 +11001788 if (NCR5380_transfer_dma(instance, &phase,
1789 &len, (unsigned char **)&cmd->SCp.ptr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 /*
Finn Thain0d2cf862016-01-03 16:06:11 +11001791 * If the watchdog timer fires, all future
1792 * accesses to this device will use the
1793 * polled-IO.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 */
Jeff Garzik017560f2005-10-24 18:04:36 -04001795 scmd_printk(KERN_INFO, cmd,
Finn Thain0d2cf862016-01-03 16:06:11 +11001796 "switching to slow handshake\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 cmd->device->borken = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 sink = 1;
1799 do_abort(instance);
1800 cmd->result = DID_ERROR << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 /* XXX - need to source or sink data here, as appropriate */
Finn Thain8053b0e2016-03-23 21:10:19 +11001802 }
Finn Thainf825e402016-03-23 21:10:15 +11001803 } else {
Finn Thain16788472016-02-23 10:07:05 +11001804 /* Break up transfer into 3 ms chunks,
1805 * presuming 6 accesses per handshake.
1806 */
1807 transfersize = min((unsigned long)cmd->SCp.this_residual,
1808 hostdata->accesses_per_ms / 2);
1809 len = transfersize;
1810 NCR5380_transfer_pio(instance, &phase, &len,
Finn Thain3d07d222016-01-03 16:06:13 +11001811 (unsigned char **)&cmd->SCp.ptr);
Finn Thain16788472016-02-23 10:07:05 +11001812 cmd->SCp.this_residual -= transfersize - len;
Finn Thain11d2f632016-01-03 16:05:51 +11001813 }
Finn Thain16788472016-02-23 10:07:05 +11001814 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 case PHASE_MSGIN:
1816 len = 1;
1817 data = &tmp;
1818 NCR5380_transfer_pio(instance, &phase, &len, &data);
1819 cmd->SCp.Message = tmp;
1820
1821 switch (tmp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 case ABORT:
1823 case COMMAND_COMPLETE:
1824 /* Accept message by clearing ACK */
1825 sink = 1;
1826 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
Finn Thain0d3d9a42016-01-03 16:05:55 +11001827 dsprintk(NDEBUG_QUEUES, instance,
1828 "COMMAND COMPLETE %p target %d lun %llu\n",
1829 cmd, scmd_id(cmd), cmd->device->lun);
1830
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 hostdata->connected = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832
Finn Thainf27db8e2016-01-03 16:06:00 +11001833 cmd->result &= ~0xffff;
1834 cmd->result |= cmd->SCp.Status;
1835 cmd->result |= cmd->SCp.Message << 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Finn Thainf27db8e2016-01-03 16:06:00 +11001837 if (cmd->cmnd[0] == REQUEST_SENSE)
Finn Thain677e0192016-01-03 16:05:59 +11001838 complete_cmd(instance, cmd);
Finn Thainf27db8e2016-01-03 16:06:00 +11001839 else {
1840 if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION ||
1841 cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) {
1842 dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n",
1843 cmd);
1844 list_add_tail(&ncmd->list,
1845 &hostdata->autosense);
1846 } else
1847 complete_cmd(instance, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 }
1849
Finn Thainaff0cf92016-01-03 16:06:09 +11001850 /*
1851 * Restore phase bits to 0 so an interrupted selection,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 * arbitration can resume.
1853 */
1854 NCR5380_write(TARGET_COMMAND_REG, 0);
Finn Thain72064a72016-01-03 16:05:44 +11001855
1856 /* Enable reselect interrupts */
1857 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
Finn Thain52d3e562016-03-23 21:10:20 +11001858
1859 maybe_release_dma_irq(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 return;
1861 case MESSAGE_REJECT:
1862 /* Accept message by clearing ACK */
1863 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1864 switch (hostdata->last_message) {
1865 case HEAD_OF_QUEUE_TAG:
1866 case ORDERED_QUEUE_TAG:
1867 case SIMPLE_QUEUE_TAG:
1868 cmd->device->simple_tags = 0;
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001869 hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 break;
1871 default:
1872 break;
1873 }
Finn Thain340b9612016-01-03 16:05:31 +11001874 break;
Finn Thain0d2cf862016-01-03 16:06:11 +11001875 case DISCONNECT:
1876 /* Accept message by clearing ACK */
1877 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1878 hostdata->connected = NULL;
1879 list_add(&ncmd->list, &hostdata->disconnected);
1880 dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES,
1881 instance, "connected command %p for target %d lun %llu moved to disconnected queue\n",
1882 cmd, scmd_id(cmd), cmd->device->lun);
Finn Thain0d3d9a42016-01-03 16:05:55 +11001883
Finn Thain0d2cf862016-01-03 16:06:11 +11001884 /*
1885 * Restore phase bits to 0 so an interrupted selection,
1886 * arbitration can resume.
1887 */
1888 NCR5380_write(TARGET_COMMAND_REG, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
Finn Thain0d2cf862016-01-03 16:06:11 +11001890 /* Enable reselect interrupts */
1891 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1892 return;
Finn Thainaff0cf92016-01-03 16:06:09 +11001893 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
Finn Thainaff0cf92016-01-03 16:06:09 +11001895 * operation, in violation of the SCSI spec so we can safely
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 * ignore SAVE/RESTORE pointers calls.
1897 *
Finn Thainaff0cf92016-01-03 16:06:09 +11001898 * Unfortunately, some disks violate the SCSI spec and
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 * don't issue the required SAVE_POINTERS message before
Finn Thainaff0cf92016-01-03 16:06:09 +11001900 * disconnecting, and we have to break spec to remain
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 * compatible.
1902 */
1903 case SAVE_POINTERS:
1904 case RESTORE_POINTERS:
1905 /* Accept message by clearing ACK */
1906 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1907 break;
1908 case EXTENDED_MESSAGE:
Finn Thainc16df322016-01-03 16:06:08 +11001909 /*
1910 * Start the message buffer with the EXTENDED_MESSAGE
1911 * byte, since spi_print_msg() wants the whole thing.
1912 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 extended_msg[0] = EXTENDED_MESSAGE;
1914 /* Accept first byte by clearing ACK */
1915 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
Finn Thain11d2f632016-01-03 16:05:51 +11001916
1917 spin_unlock_irq(&hostdata->lock);
1918
Finn Thainb7465452016-01-03 16:06:05 +11001919 dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920
1921 len = 2;
1922 data = extended_msg + 1;
1923 phase = PHASE_MSGIN;
1924 NCR5380_transfer_pio(instance, &phase, &len, &data);
Finn Thainb7465452016-01-03 16:06:05 +11001925 dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n",
1926 (int)extended_msg[1],
1927 (int)extended_msg[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Finn Thaine0783ed2016-01-03 16:05:45 +11001929 if (!len && extended_msg[1] > 0 &&
1930 extended_msg[1] <= sizeof(extended_msg) - 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 /* Accept third byte by clearing ACK */
1932 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
1933 len = extended_msg[1] - 1;
1934 data = extended_msg + 3;
1935 phase = PHASE_MSGIN;
1936
1937 NCR5380_transfer_pio(instance, &phase, &len, &data);
Finn Thainb7465452016-01-03 16:06:05 +11001938 dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n",
1939 len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 switch (extended_msg[2]) {
1942 case EXTENDED_SDTR:
1943 case EXTENDED_WDTR:
1944 case EXTENDED_MODIFY_DATA_POINTER:
1945 case EXTENDED_EXTENDED_IDENTIFY:
1946 tmp = 0;
1947 }
1948 } else if (len) {
Finn Thain6a6ff4a2016-01-03 16:06:04 +11001949 shost_printk(KERN_ERR, instance, "error receiving extended message\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 tmp = 0;
1951 } else {
Finn Thain6a6ff4a2016-01-03 16:06:04 +11001952 shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n",
1953 extended_msg[2], extended_msg[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 tmp = 0;
1955 }
Finn Thain11d2f632016-01-03 16:05:51 +11001956
1957 spin_lock_irq(&hostdata->lock);
1958 if (!hostdata->connected)
1959 return;
1960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 /* Fall through to reject message */
1962
Finn Thainaff0cf92016-01-03 16:06:09 +11001963 /*
1964 * If we get something weird that we aren't expecting,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 * reject it.
1966 */
1967 default:
1968 if (!tmp) {
Finn Thain6a6ff4a2016-01-03 16:06:04 +11001969 shost_printk(KERN_ERR, instance, "rejecting message ");
Matthew Wilcox1abfd372005-12-15 16:22:01 -05001970 spi_print_msg(extended_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 printk("\n");
1972 } else if (tmp != EXTENDED_MESSAGE)
Jeff Garzik017560f2005-10-24 18:04:36 -04001973 scmd_printk(KERN_INFO, cmd,
Finn Thain0d2cf862016-01-03 16:06:11 +11001974 "rejecting unknown message %02x\n",
1975 tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 else
Jeff Garzik017560f2005-10-24 18:04:36 -04001977 scmd_printk(KERN_INFO, cmd,
Finn Thain0d2cf862016-01-03 16:06:11 +11001978 "rejecting unknown extended message code %02x, length %d\n",
1979 extended_msg[1], extended_msg[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
1981 msgout = MESSAGE_REJECT;
1982 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
1983 break;
Finn Thain0d2cf862016-01-03 16:06:11 +11001984 } /* switch (tmp) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 break;
1986 case PHASE_MSGOUT:
1987 len = 1;
1988 data = &msgout;
1989 hostdata->last_message = msgout;
1990 NCR5380_transfer_pio(instance, &phase, &len, &data);
1991 if (msgout == ABORT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 hostdata->connected = NULL;
1993 cmd->result = DID_ERROR << 16;
Finn Thain677e0192016-01-03 16:05:59 +11001994 complete_cmd(instance, cmd);
Finn Thain52d3e562016-03-23 21:10:20 +11001995 maybe_release_dma_irq(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
1997 return;
1998 }
1999 msgout = NOP;
2000 break;
2001 case PHASE_CMDOUT:
2002 len = cmd->cmd_len;
2003 data = cmd->cmnd;
Finn Thainaff0cf92016-01-03 16:06:09 +11002004 /*
2005 * XXX for performance reasons, on machines with a
2006 * PSEUDO-DMA architecture we should probably
2007 * use the dma transfer function.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 */
2009 NCR5380_transfer_pio(instance, &phase, &len, &data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 break;
2011 case PHASE_STATIN:
2012 len = 1;
2013 data = &tmp;
2014 NCR5380_transfer_pio(instance, &phase, &len, &data);
2015 cmd->SCp.Status = tmp;
2016 break;
2017 default:
Finn Thain6a6ff4a2016-01-03 16:06:04 +11002018 shost_printk(KERN_ERR, instance, "unknown phase\n");
Finn Thain4dde8f72014-03-18 11:42:17 +11002019 NCR5380_dprint(NDEBUG_ANY, instance);
Finn Thain0d2cf862016-01-03 16:06:11 +11002020 } /* switch(phase) */
Finn Thain686f3992016-01-03 16:05:26 +11002021 } else {
Finn Thain11d2f632016-01-03 16:05:51 +11002022 spin_unlock_irq(&hostdata->lock);
Finn Thain686f3992016-01-03 16:05:26 +11002023 NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
Finn Thain11d2f632016-01-03 16:05:51 +11002024 spin_lock_irq(&hostdata->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 }
Finn Thain11d2f632016-01-03 16:05:51 +11002026 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027}
2028
2029/*
2030 * Function : void NCR5380_reselect (struct Scsi_Host *instance)
2031 *
Finn Thainaff0cf92016-01-03 16:06:09 +11002032 * Purpose : does reselection, initializing the instance->connected
Finn Thain594d4ba2016-01-03 16:06:10 +11002033 * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
2034 * nexus has been reestablished,
Finn Thainaff0cf92016-01-03 16:06:09 +11002035 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 * Inputs : instance - this instance of the NCR5380.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 */
2038
Finn Thain0d2cf862016-01-03 16:06:11 +11002039static void NCR5380_reselect(struct Scsi_Host *instance)
2040{
Finn Thaine8a60142016-01-03 16:05:54 +11002041 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 unsigned char target_mask;
2043 unsigned char lun, phase;
2044 int len;
2045 unsigned char msg[3];
2046 unsigned char *data;
Finn Thain32b26a12016-01-03 16:05:58 +11002047 struct NCR5380_cmd *ncmd;
2048 struct scsi_cmnd *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
2050 /*
2051 * Disable arbitration, etc. since the host adapter obviously
2052 * lost, and tell an interrupted NCR5380_select() to restart.
2053 */
2054
2055 NCR5380_write(MODE_REG, MR_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
2057 target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
Finn Thainb7465452016-01-03 16:06:05 +11002058
2059 dsprintk(NDEBUG_RESELECTION, instance, "reselect\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
Finn Thainaff0cf92016-01-03 16:06:09 +11002061 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 * At this point, we have detected that our SCSI ID is on the bus,
2063 * SEL is true and BSY was false for at least one bus settle delay
2064 * (400 ns).
2065 *
2066 * We must assert BSY ourselves, until the target drops the SEL
2067 * signal.
2068 */
2069
2070 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
Finn Thain72064a72016-01-03 16:05:44 +11002071 if (NCR5380_poll_politely(instance,
2072 STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) {
2073 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
2074 return;
2075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
2077
2078 /*
2079 * Wait for target to go into MSGIN.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 */
2081
Finn Thain1cc160e2016-01-03 16:05:32 +11002082 if (NCR5380_poll_politely(instance,
Finn Thain72064a72016-01-03 16:05:44 +11002083 STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) {
2084 do_abort(instance);
2085 return;
2086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087
2088 len = 1;
2089 data = msg;
2090 phase = PHASE_MSGIN;
2091 NCR5380_transfer_pio(instance, &phase, &len, &data);
2092
Finn Thain72064a72016-01-03 16:05:44 +11002093 if (len) {
2094 do_abort(instance);
2095 return;
2096 }
2097
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 if (!(msg[0] & 0x80)) {
Finn Thain72064a72016-01-03 16:05:44 +11002099 shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got ");
Matthew Wilcox1abfd372005-12-15 16:22:01 -05002100 spi_print_msg(msg);
Finn Thain72064a72016-01-03 16:05:44 +11002101 printk("\n");
2102 do_abort(instance);
2103 return;
2104 }
2105 lun = msg[0] & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Finn Thain72064a72016-01-03 16:05:44 +11002107 /*
2108 * We need to add code for SCSI-II to track which devices have
2109 * I_T_L_Q nexuses established, and which have simple I_T_L
2110 * nexuses so we can chose to do additional data transfer.
2111 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Finn Thain72064a72016-01-03 16:05:44 +11002113 /*
2114 * Find the command corresponding to the I_T_L or I_T_L_Q nexus we
2115 * just reestablished, and remove it from the disconnected queue.
2116 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Finn Thain32b26a12016-01-03 16:05:58 +11002118 tmp = NULL;
2119 list_for_each_entry(ncmd, &hostdata->disconnected, list) {
2120 struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
2121
2122 if (target_mask == (1 << scmd_id(cmd)) &&
2123 lun == (u8)cmd->device->lun) {
2124 list_del(&ncmd->list);
2125 tmp = cmd;
Finn Thain72064a72016-01-03 16:05:44 +11002126 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
2128 }
Finn Thain0d3d9a42016-01-03 16:05:55 +11002129
2130 if (tmp) {
2131 dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance,
2132 "reselect: removed %p from disconnected queue\n", tmp);
2133 } else {
Finn Thain72064a72016-01-03 16:05:44 +11002134 shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n",
2135 target_mask, lun);
2136 /*
Finn Thain0d2cf862016-01-03 16:06:11 +11002137 * Since we have an established nexus that we can't do anything
2138 * with, we must abort it.
Finn Thain72064a72016-01-03 16:05:44 +11002139 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 do_abort(instance);
Finn Thain72064a72016-01-03 16:05:44 +11002141 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 }
Finn Thain72064a72016-01-03 16:05:44 +11002143
2144 /* Accept message by clearing ACK */
2145 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
2146
2147 hostdata->connected = tmp;
Finn Thainb7465452016-01-03 16:06:05 +11002148 dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n",
2149 scmd_id(tmp), tmp->device->lun, tmp->tag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150}
2151
Finn Thain8b00c3d2016-01-03 16:06:01 +11002152/**
2153 * list_find_cmd - test for presence of a command in a linked list
2154 * @haystack: list of commands
2155 * @needle: command to search for
2156 */
2157
2158static bool list_find_cmd(struct list_head *haystack,
2159 struct scsi_cmnd *needle)
2160{
2161 struct NCR5380_cmd *ncmd;
2162
2163 list_for_each_entry(ncmd, haystack, list)
2164 if (NCR5380_to_scmd(ncmd) == needle)
2165 return true;
2166 return false;
2167}
2168
2169/**
2170 * list_remove_cmd - remove a command from linked list
2171 * @haystack: list of commands
2172 * @needle: command to remove
2173 */
2174
2175static bool list_del_cmd(struct list_head *haystack,
2176 struct scsi_cmnd *needle)
2177{
2178 if (list_find_cmd(haystack, needle)) {
2179 struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle);
2180
2181 list_del(&ncmd->list);
2182 return true;
2183 }
2184 return false;
2185}
2186
2187/**
2188 * NCR5380_abort - scsi host eh_abort_handler() method
2189 * @cmd: the command to be aborted
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 *
Finn Thain8b00c3d2016-01-03 16:06:01 +11002191 * Try to abort a given command by removing it from queues and/or sending
2192 * the target an abort message. This may not succeed in causing a target
2193 * to abort the command. Nonetheless, the low-level driver must forget about
2194 * the command because the mid-layer reclaims it and it may be re-issued.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 *
Finn Thain8b00c3d2016-01-03 16:06:01 +11002196 * The normal path taken by a command is as follows. For EH we trace this
2197 * same path to locate and abort the command.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 *
Finn Thain8b00c3d2016-01-03 16:06:01 +11002199 * unissued -> selecting -> [unissued -> selecting ->]... connected ->
2200 * [disconnected -> connected ->]...
2201 * [autosense -> connected ->] done
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 *
Finn Thain8b00c3d2016-01-03 16:06:01 +11002203 * If cmd was not found at all then presumably it has already been completed,
2204 * in which case return SUCCESS to try to avoid further EH measures.
Finn Thaindc183962016-02-23 10:07:07 +11002205 *
Finn Thain8b00c3d2016-01-03 16:06:01 +11002206 * If the command has not completed yet, we must not fail to find it.
Finn Thaindc183962016-02-23 10:07:07 +11002207 * We have no option but to forget the aborted command (even if it still
2208 * lacks sense data). The mid-layer may re-issue a command that is in error
2209 * recovery (see scsi_send_eh_cmnd), but the logic and data structures in
2210 * this driver are such that a command can appear on one queue only.
Finn Thain71a00592016-02-23 10:07:06 +11002211 *
2212 * The lock protects driver data structures, but EH handlers also use it
2213 * to serialize their own execution and prevent their own re-entry.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 */
2215
Finn Thain710ddd02014-11-12 16:12:02 +11002216static int NCR5380_abort(struct scsi_cmnd *cmd)
2217{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 struct Scsi_Host *instance = cmd->device->host;
Finn Thaine8a60142016-01-03 16:05:54 +11002219 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Finn Thain11d2f632016-01-03 16:05:51 +11002220 unsigned long flags;
Finn Thain8b00c3d2016-01-03 16:06:01 +11002221 int result = SUCCESS;
Hannes Reinecke1fa6b5f2014-10-24 14:26:58 +02002222
Finn Thain11d2f632016-01-03 16:05:51 +11002223 spin_lock_irqsave(&hostdata->lock, flags);
2224
Finn Thain32b26a12016-01-03 16:05:58 +11002225#if (NDEBUG & NDEBUG_ANY)
Finn Thain8b00c3d2016-01-03 16:06:01 +11002226 scmd_printk(KERN_INFO, cmd, __func__);
Finn Thain32b26a12016-01-03 16:05:58 +11002227#endif
Finn Thaine5c3fdd2016-01-03 16:05:52 +11002228 NCR5380_dprint(NDEBUG_ANY, instance);
2229 NCR5380_dprint_phase(NDEBUG_ANY, instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
Finn Thain8b00c3d2016-01-03 16:06:01 +11002231 if (list_del_cmd(&hostdata->unissued, cmd)) {
2232 dsprintk(NDEBUG_ABORT, instance,
2233 "abort: removed %p from issue queue\n", cmd);
2234 cmd->result = DID_ABORT << 16;
2235 cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
Finn Thaindc183962016-02-23 10:07:07 +11002236 goto out;
Finn Thain8b00c3d2016-01-03 16:06:01 +11002237 }
2238
Finn Thain707d62b2016-01-03 16:06:02 +11002239 if (hostdata->selecting == cmd) {
2240 dsprintk(NDEBUG_ABORT, instance,
2241 "abort: cmd %p == selecting\n", cmd);
2242 hostdata->selecting = NULL;
2243 cmd->result = DID_ABORT << 16;
2244 complete_cmd(instance, cmd);
2245 goto out;
2246 }
2247
Finn Thain8b00c3d2016-01-03 16:06:01 +11002248 if (list_del_cmd(&hostdata->disconnected, cmd)) {
2249 dsprintk(NDEBUG_ABORT, instance,
2250 "abort: removed %p from disconnected list\n", cmd);
Finn Thain71a00592016-02-23 10:07:06 +11002251 /* Can't call NCR5380_select() and send ABORT because that
2252 * means releasing the lock. Need a bus reset.
2253 */
Finn Thaindc183962016-02-23 10:07:07 +11002254 set_host_byte(cmd, DID_ERROR);
2255 complete_cmd(instance, cmd);
Finn Thain71a00592016-02-23 10:07:06 +11002256 result = FAILED;
2257 goto out;
Finn Thain8b00c3d2016-01-03 16:06:01 +11002258 }
2259
2260 if (hostdata->connected == cmd) {
2261 dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
2262 hostdata->connected = NULL;
Finn Thaindc183962016-02-23 10:07:07 +11002263 hostdata->dma_len = 0;
Finn Thain8b00c3d2016-01-03 16:06:01 +11002264 if (do_abort(instance)) {
2265 set_host_byte(cmd, DID_ERROR);
2266 complete_cmd(instance, cmd);
2267 result = FAILED;
2268 goto out;
2269 }
2270 set_host_byte(cmd, DID_ABORT);
Finn Thaindc183962016-02-23 10:07:07 +11002271 complete_cmd(instance, cmd);
2272 goto out;
Finn Thain8b00c3d2016-01-03 16:06:01 +11002273 }
2274
Finn Thaindc183962016-02-23 10:07:07 +11002275 if (list_del_cmd(&hostdata->autosense, cmd)) {
Finn Thain8b00c3d2016-01-03 16:06:01 +11002276 dsprintk(NDEBUG_ABORT, instance,
Finn Thaindc183962016-02-23 10:07:07 +11002277 "abort: removed %p from sense queue\n", cmd);
2278 set_host_byte(cmd, DID_ERROR);
Finn Thain8b00c3d2016-01-03 16:06:01 +11002279 complete_cmd(instance, cmd);
2280 }
2281
2282out:
2283 if (result == FAILED)
2284 dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd);
2285 else
2286 dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd);
2287
2288 queue_work(hostdata->work_q, &hostdata->main_task);
Finn Thain52d3e562016-03-23 21:10:20 +11002289 maybe_release_dma_irq(instance);
Finn Thain11d2f632016-01-03 16:05:51 +11002290 spin_unlock_irqrestore(&hostdata->lock, flags);
Finn Thain32b26a12016-01-03 16:05:58 +11002291
Finn Thain8b00c3d2016-01-03 16:06:01 +11002292 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293}
2294
2295
Finn Thain3be1b3e2016-01-03 16:05:12 +11002296/**
2297 * NCR5380_bus_reset - reset the SCSI bus
2298 * @cmd: SCSI command undergoing EH
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 *
Finn Thain3be1b3e2016-01-03 16:05:12 +11002300 * Returns SUCCESS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 */
2302
Finn Thain710ddd02014-11-12 16:12:02 +11002303static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04002304{
2305 struct Scsi_Host *instance = cmd->device->host;
Finn Thain11d2f632016-01-03 16:05:51 +11002306 struct NCR5380_hostdata *hostdata = shost_priv(instance);
Finn Thain62717f52016-01-03 16:06:03 +11002307 int i;
Finn Thain11d2f632016-01-03 16:05:51 +11002308 unsigned long flags;
Finn Thain62717f52016-01-03 16:06:03 +11002309 struct NCR5380_cmd *ncmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Finn Thain11d2f632016-01-03 16:05:51 +11002311 spin_lock_irqsave(&hostdata->lock, flags);
Finn Thain3be1b3e2016-01-03 16:05:12 +11002312
2313#if (NDEBUG & NDEBUG_ANY)
Finn Thain62717f52016-01-03 16:06:03 +11002314 scmd_printk(KERN_INFO, cmd, __func__);
Finn Thain3be1b3e2016-01-03 16:05:12 +11002315#endif
Finn Thaine5c3fdd2016-01-03 16:05:52 +11002316 NCR5380_dprint(NDEBUG_ANY, instance);
2317 NCR5380_dprint_phase(NDEBUG_ANY, instance);
Finn Thain3be1b3e2016-01-03 16:05:12 +11002318
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04002319 do_reset(instance);
Finn Thain3be1b3e2016-01-03 16:05:12 +11002320
Finn Thain62717f52016-01-03 16:06:03 +11002321 /* reset NCR registers */
2322 NCR5380_write(MODE_REG, MR_BASE);
2323 NCR5380_write(TARGET_COMMAND_REG, 0);
2324 NCR5380_write(SELECT_ENABLE_REG, 0);
2325
2326 /* After the reset, there are no more connected or disconnected commands
2327 * and no busy units; so clear the low-level status here to avoid
2328 * conflicts when the mid-level code tries to wake up the affected
2329 * commands!
2330 */
2331
Finn Thain1884c282016-02-23 10:07:04 +11002332 if (list_del_cmd(&hostdata->unissued, cmd)) {
2333 cmd->result = DID_RESET << 16;
2334 cmd->scsi_done(cmd);
2335 }
2336
2337 if (hostdata->selecting) {
2338 hostdata->selecting->result = DID_RESET << 16;
2339 complete_cmd(instance, hostdata->selecting);
2340 hostdata->selecting = NULL;
2341 }
Finn Thain62717f52016-01-03 16:06:03 +11002342
2343 list_for_each_entry(ncmd, &hostdata->disconnected, list) {
2344 struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
2345
2346 set_host_byte(cmd, DID_RESET);
2347 cmd->scsi_done(cmd);
2348 }
Finn Thain1884c282016-02-23 10:07:04 +11002349 INIT_LIST_HEAD(&hostdata->disconnected);
Finn Thain62717f52016-01-03 16:06:03 +11002350
2351 list_for_each_entry(ncmd, &hostdata->autosense, list) {
2352 struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
2353
2354 set_host_byte(cmd, DID_RESET);
2355 cmd->scsi_done(cmd);
2356 }
Finn Thain1884c282016-02-23 10:07:04 +11002357 INIT_LIST_HEAD(&hostdata->autosense);
Finn Thain62717f52016-01-03 16:06:03 +11002358
2359 if (hostdata->connected) {
2360 set_host_byte(hostdata->connected, DID_RESET);
2361 complete_cmd(instance, hostdata->connected);
2362 hostdata->connected = NULL;
2363 }
2364
Finn Thain62717f52016-01-03 16:06:03 +11002365 for (i = 0; i < 8; ++i)
2366 hostdata->busy[i] = 0;
Finn Thain62717f52016-01-03 16:06:03 +11002367 hostdata->dma_len = 0;
Finn Thain62717f52016-01-03 16:06:03 +11002368
2369 queue_work(hostdata->work_q, &hostdata->main_task);
Finn Thain52d3e562016-03-23 21:10:20 +11002370 maybe_release_dma_irq(instance);
Finn Thain11d2f632016-01-03 16:05:51 +11002371 spin_unlock_irqrestore(&hostdata->lock, flags);
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04002372
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 return SUCCESS;
2374}