blob: 4bfba454a0329bf6c785692713e7e92d49de8077 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $
2 * linux/kernel/aha1542.c
3 *
4 * Copyright (C) 1992 Tommy Thorn
5 * Copyright (C) 1993, 1994, 1995 Eric Youngdale
6 *
7 * Modified by Eric Youngdale
8 * Use request_irq and request_dma to help prevent unexpected conflicts
9 * Set up on-board DMA controller, such that we do not have to
10 * have the bios enabled to use the aha1542.
11 * Modified by David Gentzel
12 * Don't call request_dma if dma mask is 0 (for BusLogic BT-445S VL-Bus
13 * controller).
14 * Modified by Matti Aarnio
15 * Accept parameters from LILO cmd-line. -- 1-Oct-94
16 * Modified by Mike McLagan <mike.mclagan@linux.org>
17 * Recognise extended mode on AHA1542CP, different bit than 1542CF
18 * 1-Jan-97
19 * Modified by Bjorn L. Thordarson and Einar Thor Einarsson
20 * Recognize that DMA0 is valid DMA channel -- 13-Jul-98
21 * Modified by Chris Faulhaber <jedgar@fxp.org>
22 * Added module command-line options
23 * 19-Jul-99
Joe Perches726a6452008-02-03 16:36:24 +020024 * Modified by Adam Fritzler
Paul Gortmakera88dc062012-05-16 20:33:52 -040025 * Added proper detection of the AHA-1640 (MCA, now deleted)
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29#include <linux/interrupt.h>
30#include <linux/kernel.h>
31#include <linux/types.h>
32#include <linux/string.h>
33#include <linux/ioport.h>
34#include <linux/delay.h>
35#include <linux/proc_fs.h>
36#include <linux/init.h>
37#include <linux/spinlock.h>
Ondrej Zary643a7c42015-02-06 23:11:22 +010038#include <linux/isa.h>
39#include <linux/pnp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/blkdev.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090041#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#include <asm/dma.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <asm/io.h>
45
46#include "scsi.h"
47#include <scsi/scsi_host.h>
48#include "aha1542.h"
Paul Bolle6ac7d112012-06-06 14:17:46 +020049#include <linux/stat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#ifdef DEBUG
52#define DEB(x) x
53#else
54#define DEB(x)
55#endif
56
57/*
58 static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
59 */
60
61/* The adaptec can be configured for quite a number of addresses, but
62 I generally do not want the card poking around at random. We allow
63 two addresses - this allows people to use the Adaptec with a Midi
64 card, which also used 0x330 -- can be overridden with LILO! */
65
66#define MAXBOARDS 4 /* Increase this and the sizes of the
67 arrays below, if you need more.. */
68
Paul Gortmakera88dc062012-05-16 20:33:52 -040069/* Boards 3,4 slots are reserved for ISAPnP scans */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Ondrej Zary643a7c42015-02-06 23:11:22 +010071static unsigned int bases[MAXBOARDS] = {0x330, 0x334, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73/* set by aha1542_setup according to the command line; they also may
74 be marked __initdata, but require zero initializers then */
75
76static int setup_called[MAXBOARDS];
77static int setup_buson[MAXBOARDS];
78static int setup_busoff[MAXBOARDS];
Ondrej Zary643a7c42015-02-06 23:11:22 +010079static int setup_dmaspeed[MAXBOARDS] = { -1, -1, -1, -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
81/*
82 * LILO/Module params: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]
83 *
84 * Where: <PORTBASE> is any of the valid AHA addresses:
85 * 0x130, 0x134, 0x230, 0x234, 0x330, 0x334
86 * <BUSON> is the time (in microsecs) that AHA spends on the AT-bus
87 * when transferring data. 1542A power-on default is 11us,
88 * valid values are in range: 2..15 (decimal)
89 * <BUSOFF> is the time that AHA spends OFF THE BUS after while
90 * it is transferring data (not to monopolize the bus).
91 * Power-on default is 4us, valid range: 1..64 microseconds.
92 * <DMASPEED> Default is jumper selected (1542A: on the J1),
93 * but experimenter can alter it with this.
94 * Valid values: 5, 6, 7, 8, 10 (MB/s)
95 * Factory default is 5 MB/s.
96 */
97
98#if defined(MODULE)
Rusty Russell90ab5ee2012-01-13 09:32:20 +103099static bool isapnp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100static int aha1542[] = {0x330, 11, 4, -1};
101module_param_array(aha1542, int, NULL, 0);
102module_param(isapnp, bool, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103#else
104static int isapnp = 1;
105#endif
106
107#define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */
108#define BIOS_TRANSLATION_6432 1 /* Default case these days */
109#define BIOS_TRANSLATION_25563 2 /* Big disk case */
110
111struct aha1542_hostdata {
112 /* This will effectively start both of them at the first mailbox */
113 int bios_translation; /* Mapping bios uses - for compatibility */
114 int aha1542_last_mbi_used;
115 int aha1542_last_mbo_used;
116 Scsi_Cmnd *SCint[AHA1542_MAILBOXES];
117 struct mailbox mb[2 * AHA1542_MAILBOXES];
118 struct ccb ccb[AHA1542_MAILBOXES];
119};
120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121static DEFINE_SPINLOCK(aha1542_lock);
122
Ondrej Zaryf1bbef62015-02-06 23:11:26 +0100123static inline void aha1542_intr_reset(u16 base)
124{
125 outb(IRST, CONTROL(base));
126}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100128static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
129{
130 bool delayed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100132 if (timeout == 0) {
133 timeout = 3000000;
134 delayed = false;
135 }
136
137 while (1) {
138 u8 bits = inb(port) & mask;
139 if ((bits & allof) == allof && ((bits & noneof) == 0))
140 break;
141 if (delayed)
142 mdelay(1);
143 if (--timeout == 0)
144 return false;
145 }
146
147 return true;
148}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150/* This is a bit complicated, but we need to make sure that an interrupt
151 routine does not send something out while we are in the middle of this.
152 Fortunately, it is only at boot time that multi-byte messages
153 are ever sent. */
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100154static int aha1542_outb(unsigned int base, u8 cmd)
155{
156 unsigned long flags;
157
158 while (1) {
159 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) {
160 printk(KERN_ERR "aha1542_outb failed");
161 return 1;
162 }
163 spin_lock_irqsave(&aha1542_lock, flags);
164 if (inb(STATUS(base)) & CDF) {
165 spin_unlock_irqrestore(&aha1542_lock, flags);
166 continue;
167 }
168 outb(cmd, DATA(base));
169 spin_unlock_irqrestore(&aha1542_lock, flags);
170 return 0;
171 }
172}
173
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100174static int aha1542_out(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100176 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100178 spin_lock_irqsave(&aha1542_lock, flags);
179 while (len--) {
180 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 spin_unlock_irqrestore(&aha1542_lock, flags);
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100182 printk(KERN_ERR "aha1542_out failed(%d): ", len + 1);
183 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 }
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100185 outb(*cmdp++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 }
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100187 spin_unlock_irqrestore(&aha1542_lock, flags);
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190}
191
192/* Only used at boot time, so we do not need to worry about latency as much
193 here */
194
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100195static int aha1542_in(unsigned int base, u8 *cmdp, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196{
197 unsigned long flags;
198
199 spin_lock_irqsave(&aha1542_lock, flags);
200 while (len--) {
Ondrej Zarya13b3722015-02-06 23:11:34 +0100201 if (!wait_mask(STATUS(base), DF, DF, 0, timeout)) {
202 spin_unlock_irqrestore(&aha1542_lock, flags);
203 if (timeout == 0)
204 printk(KERN_ERR "aha1542_in failed(%d): ", len + 1);
205 return 1;
206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 *cmdp++ = inb(DATA(base));
208 }
209 spin_unlock_irqrestore(&aha1542_lock, flags);
210 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211}
212
213static int makecode(unsigned hosterr, unsigned scsierr)
214{
215 switch (hosterr) {
216 case 0x0:
217 case 0xa: /* Linked command complete without error and linked normally */
218 case 0xb: /* Linked command complete without error, interrupt generated */
219 hosterr = 0;
220 break;
221
222 case 0x11: /* Selection time out-The initiator selection or target
223 reselection was not complete within the SCSI Time out period */
224 hosterr = DID_TIME_OUT;
225 break;
226
227 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
228 than was allocated by the Data Length field or the sum of the
229 Scatter / Gather Data Length fields. */
230
231 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
232
233 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
234 invalid. This usually indicates a software failure. */
235
236 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
237 This usually indicates a software failure. */
238
239 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
240 of linked CCB's does not specify the same logical unit number as
241 the first. */
242 case 0x18: /* Invalid Target Direction received from Host-The direction of a
243 Target Mode CCB was invalid. */
244
245 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
246 received to service data transfer between the same target LUN
247 and initiator SCSI ID in the same direction. */
248
249 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
250 length segment or invalid segment list boundaries was received.
251 A CCB parameter was invalid. */
252 DEB(printk("Aha1542: %x %x\n", hosterr, scsierr));
253 hosterr = DID_ERROR; /* Couldn't find any better */
254 break;
255
256 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
257 phase sequence was requested by the target. The host adapter
258 will generate a SCSI Reset Condition, notifying the host with
259 a SCRD interrupt */
260 hosterr = DID_RESET;
261 break;
262 default:
263 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
264 break;
265 }
266 return scsierr | (hosterr << 16);
267}
268
Ondrej Zary643a7c42015-02-06 23:11:22 +0100269static int aha1542_test_port(int bse, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100271 u8 inquiry_result[4];
272 u8 *cmdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 /* Quick and dirty test for presence of the card. */
276 if (inb(STATUS(bse)) == 0xff)
277 return 0;
278
279 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 /* In case some other card was probing here, reset interrupts */
282 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
283
284 outb(SRST | IRST /*|SCRST */ , CONTROL(bse));
285
286 mdelay(20); /* Wait a little bit for things to settle down. */
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100289 if (!wait_mask(STATUS(bse), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100290 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 /* Shouldn't have generated any interrupts during reset */
293 if (inb(INTRFLAGS(bse)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100294 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 /* Perform a host adapter inquiry instead so we do not need to set
297 up the mailboxes ahead of time */
298
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100299 aha1542_outb(bse, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 len = 4;
302 cmdp = &inquiry_result[0];
303
304 while (len--) {
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100305 if (!wait_mask(STATUS(bse), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100306 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 *cmdp++ = inb(DATA(bse));
308 }
309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 /* Reading port should reset DF */
311 if (inb(STATUS(bse)) & DF)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100312 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 /* When HACC, command is completed, and we're though testing */
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100315 if (!wait_mask(INTRFLAGS(bse), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100316 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 /* Clear interrupts */
319 outb(IRST, CONTROL(bse));
320
Ondrej Zarybdebe222015-02-06 23:11:35 +0100321 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324/* A "high" level interrupt handler */
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400325static void aha1542_intr_handle(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100327 struct aha1542_hostdata *aha1542 = shost_priv(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 void (*my_done) (Scsi_Cmnd *) = NULL;
329 int errstatus, mbi, mbo, mbistatus;
330 int number_serviced;
331 unsigned long flags;
332 Scsi_Cmnd *SCtmp;
333 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100334 struct mailbox *mb = aha1542->mb;
335 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337#ifdef DEBUG
338 {
339 flag = inb(INTRFLAGS(shost->io_port));
340 printk(KERN_DEBUG "aha1542_intr_handle: ");
341 if (!(flag & ANYINTR))
342 printk("no interrupt?");
343 if (flag & MBIF)
344 printk("MBIF ");
345 if (flag & MBOA)
346 printk("MBOF ");
347 if (flag & HACC)
348 printk("HACC ");
349 if (flag & SCRD)
350 printk("SCRD ");
351 printk("status %02x\n", inb(STATUS(shost->io_port)));
352 };
353#endif
354 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356 while (1 == 1) {
357 flag = inb(INTRFLAGS(shost->io_port));
358
359 /* Check for unusual interrupts. If any of these happen, we should
360 probably do something special, but for now just printing a message
361 is sufficient. A SCSI reset detected is something that we really
362 need to deal with in some way. */
363 if (flag & ~MBIF) {
364 if (flag & MBOA)
365 printk("MBOF ");
366 if (flag & HACC)
367 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100368 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 }
371 aha1542_intr_reset(shost->io_port);
372
373 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100374 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 if (mbi >= 2 * AHA1542_MAILBOXES)
376 mbi = AHA1542_MAILBOXES;
377
378 do {
379 if (mb[mbi].status != 0)
380 break;
381 mbi++;
382 if (mbi >= 2 * AHA1542_MAILBOXES)
383 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100384 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386 if (mb[mbi].status == 0) {
387 spin_unlock_irqrestore(&aha1542_lock, flags);
388 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100389 if (!number_serviced)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 printk(KERN_WARNING "aha1542.c: interrupt received, but no mail.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return;
392 };
393
Ondrej Zary10be6252015-02-06 23:11:24 +0100394 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 mbistatus = mb[mbi].status;
396 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100397 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 spin_unlock_irqrestore(&aha1542_lock, flags);
399
400#ifdef DEBUG
401 {
402 if (ccb[mbo].tarstat | ccb[mbo].hastat)
403 printk(KERN_DEBUG "aha1542_command: returning %x (status %d)\n",
404 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
405 };
406#endif
407
408 if (mbistatus == 3)
409 continue; /* Aborted command not found */
410
411#ifdef DEBUG
412 printk(KERN_DEBUG "...done %d %d\n", mbo, mbi);
413#endif
414
Ondrej Zarye98878f2015-02-06 23:11:25 +0100415 SCtmp = aha1542->SCint[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417 if (!SCtmp || !SCtmp->scsi_done) {
418 printk(KERN_WARNING "aha1542_intr_handle: Unexpected interrupt\n");
419 printk(KERN_WARNING "tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat,
420 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
421 return;
422 }
423 my_done = SCtmp->scsi_done;
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800424 kfree(SCtmp->host_scribble);
425 SCtmp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* Fetch the sense data, and tuck it away, in the required slot. The
427 Adaptec automatically fetches it, and there is no guarantee that
428 we will still have it in the cdb when we come back */
429 if (ccb[mbo].tarstat == 2)
430 memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900431 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
433
434 /* is there mail :-) */
435
436 /* more error checking left out here */
437 if (mbistatus != 1)
438 /* This is surely wrong, but I don't know what's right */
439 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
440 else
441 errstatus = 0;
442
443#ifdef DEBUG
444 if (errstatus)
445 printk(KERN_DEBUG "(aha1542 error:%x %x %x) ", errstatus,
446 ccb[mbo].hastat, ccb[mbo].tarstat);
447#endif
448
449 if (ccb[mbo].tarstat == 2) {
450#ifdef DEBUG
451 int i;
452#endif
453 DEB(printk("aha1542_intr_handle: sense:"));
454#ifdef DEBUG
455 for (i = 0; i < 12; i++)
456 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen + i]);
457 printk("\n");
458#endif
459 /*
460 DEB(printk("aha1542_intr_handle: buf:"));
461 for (i = 0; i < bufflen; i++)
462 printk("%02x ", ((unchar *)buff)[i]);
463 printk("\n");
464 */
465 }
466 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
467 SCtmp->result = errstatus;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100468 aha1542->SCint[mbo] = NULL; /* This effectively frees up the mailbox slot, as
469 far as queuecommand is concerned */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 my_done(SCtmp);
471 number_serviced++;
472 };
473}
474
Ondrej Zary09a44832015-02-06 23:11:28 +0100475/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
476static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
477{
478 unsigned long flags;
479 struct Scsi_Host *shost = dev_id;
480
481 spin_lock_irqsave(shost->host_lock, flags);
482 aha1542_intr_handle(shost);
483 spin_unlock_irqrestore(shost->host_lock, flags);
484 return IRQ_HANDLED;
485}
486
Jeff Garzikf2812332010-11-16 02:10:29 -0500487static int aha1542_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100489 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100490 u8 direction;
491 u8 *cmd = (u8 *) SCpnt->cmnd;
492 u8 target = SCpnt->device->id;
493 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 unsigned long flags;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300495 int bufflen = scsi_bufflen(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100497 struct mailbox *mb = aha1542->mb;
498 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
500 DEB(int i);
501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 DEB(if (target > 1) {
503 SCpnt->result = DID_TIME_OUT << 16;
504 done(SCpnt); return 0;
505 }
506 );
507
508 if (*cmd == REQUEST_SENSE) {
509 /* Don't do the command - we have the sense data already */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 SCpnt->result = 0;
511 done(SCpnt);
512 return 0;
513 }
514#ifdef DEBUG
515 if (*cmd == READ_10 || *cmd == WRITE_10)
516 i = xscsi2int(cmd + 2);
517 else if (*cmd == READ_6 || *cmd == WRITE_6)
518 i = scsi2int(cmd + 2);
519 else
520 i = -1;
521 if (done)
522 printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
523 else
524 printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:");
526 for (i = 0; i < SCpnt->cmd_len; i++)
527 printk("%02x ", cmd[i]);
528 printk("\n");
529 if (*cmd == WRITE_10 || *cmd == WRITE_6)
530 return 0; /* we are still testing, so *don't* write */
531#endif
532 /* Use the outgoing mailboxes in a round-robin fashion, because this
533 is how the host adapter will scan for them */
534
535 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100536 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 if (mbo >= AHA1542_MAILBOXES)
538 mbo = 0;
539
540 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +0100541 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 break;
543 mbo++;
544 if (mbo >= AHA1542_MAILBOXES)
545 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100546 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Ondrej Zarye98878f2015-02-06 23:11:25 +0100548 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 panic("Unable to find empty mailbox for aha1542.\n");
550
Ondrej Zarye98878f2015-02-06 23:11:25 +0100551 aha1542->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from
552 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Ondrej Zarye98878f2015-02-06 23:11:25 +0100554 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 spin_unlock_irqrestore(&aha1542_lock, flags);
556
557#ifdef DEBUG
558 printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
559#endif
560
Ondrej Zary10be6252015-02-06 23:11:24 +0100561 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
563 memset(&ccb[mbo], 0, sizeof(struct ccb));
564
565 ccb[mbo].cdblen = SCpnt->cmd_len;
566
567 direction = 0;
568 if (*cmd == READ_10 || *cmd == READ_6)
569 direction = 8;
570 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
571 direction = 16;
572
573 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
574
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300575 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200576 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 struct chain *cptr;
578#ifdef DEBUG
579 unsigned char *ptr;
580#endif
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300581 int i, sg_count = scsi_sg_count(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300583 SCpnt->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
584 GFP_KERNEL | GFP_DMA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 cptr = (struct chain *) SCpnt->host_scribble;
586 if (cptr == NULL) {
587 /* free the claimed mailbox slot */
Ondrej Zarye98878f2015-02-06 23:11:25 +0100588 aha1542->SCint[mbo] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 return SCSI_MLQUEUE_HOST_BUSY;
590 }
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300591 scsi_for_each_sg(SCpnt, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100592 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
593 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200594 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300596 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100597 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598#ifdef DEBUG
599 printk("cptr %x: ", cptr);
600 ptr = (unsigned char *) cptr;
601 for (i = 0; i < 18; i++)
602 printk("%02x ", ptr[i]);
603#endif
604 } else {
605 ccb[mbo].op = 0; /* SCSI Initiator Command */
606 SCpnt->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300607 any2scsi(ccb[mbo].datalen, 0);
608 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 };
610 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
611 ccb[mbo].rsalen = 16;
612 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
613 ccb[mbo].commlinkid = 0;
614
615#ifdef DEBUG
616 {
617 int i;
618 printk(KERN_DEBUG "aha1542_command: sending.. ");
619 for (i = 0; i < sizeof(ccb[mbo]) - 10; i++)
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100620 printk("%02x ", ((u8 *) &ccb[mbo])[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 };
622#endif
623
624 if (done) {
Ondrej Zaryf232d532015-02-06 23:11:29 +0100625 DEB(printk("aha1542_queuecommand: now waiting for interrupt "));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 SCpnt->scsi_done = done;
627 mb[mbo].status = 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100628 aha1542_outb(SCpnt->device->host->io_port, CMD_START_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 } else
630 printk("aha1542_queuecommand: done can't be NULL\n");
631
632 return 0;
633}
634
Jeff Garzikf2812332010-11-16 02:10:29 -0500635static DEF_SCSI_QCMD(aha1542_queuecommand)
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637/* Initialize mailboxes */
638static void setup_mailboxes(int bse, struct Scsi_Host *shpnt)
639{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100640 struct aha1542_hostdata *aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100642 struct mailbox *mb = aha1542->mb;
643 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100645 u8 cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 for (i = 0; i < AHA1542_MAILBOXES; i++) {
648 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100649 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 };
651 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
Ondrej Zary10be6252015-02-06 23:11:24 +0100652 any2scsi((cmd + 2), isa_virt_to_bus(mb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 aha1542_out(bse, cmd, 5);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100654 if (!wait_mask(INTRFLAGS(bse), INTRMASK, HACC, 0, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 aha1542_intr_reset(bse);
657}
658
Ondrej Zary643a7c42015-02-06 23:11:22 +0100659static int aha1542_getconfig(int base_io, unsigned char *irq_level, unsigned char *dma_chan, unsigned char *scsi_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100661 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 int i;
663 i = inb(STATUS(base_io));
664 if (i & DF) {
665 i = inb(DATA(base_io));
666 };
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100667 aha1542_outb(base_io, CMD_RETCONF);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100668 aha1542_in(base_io, inquiry_result, 3, 0);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100669 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 printk(KERN_ERR "aha1542_detect: query board settings\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 aha1542_intr_reset(base_io);
672 switch (inquiry_result[0]) {
673 case 0x80:
674 *dma_chan = 7;
675 break;
676 case 0x40:
677 *dma_chan = 6;
678 break;
679 case 0x20:
680 *dma_chan = 5;
681 break;
682 case 0x01:
683 *dma_chan = 0;
684 break;
685 case 0:
686 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
687 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
688 *dma_chan = 0xFF;
689 break;
690 default:
691 printk(KERN_ERR "Unable to determine Adaptec DMA priority. Disabling board\n");
692 return -1;
693 };
694 switch (inquiry_result[1]) {
695 case 0x40:
696 *irq_level = 15;
697 break;
698 case 0x20:
699 *irq_level = 14;
700 break;
701 case 0x8:
702 *irq_level = 12;
703 break;
704 case 0x4:
705 *irq_level = 11;
706 break;
707 case 0x2:
708 *irq_level = 10;
709 break;
710 case 0x1:
711 *irq_level = 9;
712 break;
713 default:
714 printk(KERN_ERR "Unable to determine Adaptec IRQ level. Disabling board\n");
715 return -1;
716 };
717 *scsi_id = inquiry_result[2] & 7;
718 return 0;
719}
720
721/* This function should only be called for 1542C boards - we can detect
722 the special firmware settings and unlock the board */
723
Ondrej Zary643a7c42015-02-06 23:11:22 +0100724static int aha1542_mbenable(int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100726 static u8 mbenable_cmd[3];
727 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 int retval;
729
730 retval = BIOS_TRANSLATION_6432;
731
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100732 aha1542_outb(base, CMD_EXTBIOS);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100733 if (aha1542_in(base, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return retval;
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100735 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 100))
736 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 aha1542_intr_reset(base);
738
739 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
740 mbenable_cmd[0] = CMD_MBENABLE;
741 mbenable_cmd[1] = 0;
742 mbenable_cmd[2] = mbenable_result[1];
743
744 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
745 retval = BIOS_TRANSLATION_25563;
746
747 aha1542_out(base, mbenable_cmd, 3);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100748 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
749 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 };
751 while (0) {
752fail:
753 printk(KERN_ERR "aha1542_mbenable: Mailbox init failed\n");
754 }
755 aha1542_intr_reset(base);
756 return retval;
757}
758
759/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100760static int aha1542_query(int base_io, int *transl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100762 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 int i;
764 i = inb(STATUS(base_io));
765 if (i & DF) {
766 i = inb(DATA(base_io));
767 };
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100768 aha1542_outb(base_io, CMD_INQUIRY);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100769 aha1542_in(base_io, inquiry_result, 4, 0);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100770 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 printk(KERN_ERR "aha1542_detect: query card type\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 aha1542_intr_reset(base_io);
773
774 *transl = BIOS_TRANSLATION_6432; /* Default case */
775
776 /* For an AHA1740 series board, we ignore the board since there is a
777 hardware bug which can lead to wrong blocks being returned if the board
778 is operating in the 1542 emulation mode. Since there is an extended mode
779 driver, we simply ignore the board and let the 1740 driver pick it up.
780 */
781
782 if (inquiry_result[0] == 0x43) {
783 printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
784 return 1;
785 };
786
787 /* Always call this - boards that do not support extended bios translation
788 will ignore the command, and we will set the proper default */
789
790 *transl = aha1542_mbenable(base_io);
791
792 return 0;
793}
794
795#ifndef MODULE
796static char *setup_str[MAXBOARDS] __initdata;
797static int setup_idx = 0;
798
799static void __init aha1542_setup(char *str, int *ints)
800{
801 const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
802 int setup_portbase;
803
804 if (setup_idx >= MAXBOARDS) {
805 printk(KERN_ERR "aha1542: aha1542_setup called too many times! Bad LILO params ?\n");
806 printk(KERN_ERR " Entryline 1: %s\n", setup_str[0]);
807 printk(KERN_ERR " Entryline 2: %s\n", setup_str[1]);
808 printk(KERN_ERR " This line: %s\n", str);
809 return;
810 }
811 if (ints[0] < 1 || ints[0] > 4) {
812 printk(KERN_ERR "aha1542: %s\n", str);
813 printk(ahausage);
814 printk(KERN_ERR "aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n");
815 }
816 setup_called[setup_idx] = ints[0];
817 setup_str[setup_idx] = str;
818
819 setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */
820 setup_buson[setup_idx] = ints[0] >= 2 ? ints[2] : 7;
821 setup_busoff[setup_idx] = ints[0] >= 3 ? ints[3] : 5;
822 if (ints[0] >= 4)
823 {
824 int atbt = -1;
825 switch (ints[4]) {
826 case 5:
827 atbt = 0x00;
828 break;
829 case 6:
830 atbt = 0x04;
831 break;
832 case 7:
833 atbt = 0x01;
834 break;
835 case 8:
836 atbt = 0x02;
837 break;
838 case 10:
839 atbt = 0x03;
840 break;
841 default:
842 printk(KERN_ERR "aha1542: %s\n", str);
843 printk(ahausage);
844 printk(KERN_ERR "aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n");
845 break;
846 }
847 setup_dmaspeed[setup_idx] = atbt;
848 }
849 if (setup_portbase != 0)
850 bases[setup_idx] = setup_portbase;
851
852 ++setup_idx;
853}
854
855static int __init do_setup(char *str)
856{
857 int ints[5];
858
859 int count=setup_idx;
860
Tobias Klauser6391a112006-06-08 22:23:48 -0700861 get_options(str, ARRAY_SIZE(ints), ints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 aha1542_setup(str,ints);
863
864 return count<setup_idx;
865}
866
867__setup("aha1542=",do_setup);
868#endif
869
870/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100871static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
873 unsigned char dma_chan;
874 unsigned char irq_level;
875 unsigned char scsi_id;
876 unsigned long flags;
877 unsigned int base_io;
878 int trans;
879 struct Scsi_Host *shpnt = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100880 struct aha1542_hostdata *aha1542;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
882 DEB(printk("aha1542_detect: \n"));
883
884 tpnt->proc_name = "aha1542";
885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) {
Ondrej Zary643a7c42015-02-06 23:11:22 +0100887 shpnt = scsi_host_alloc(tpnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 sizeof(struct aha1542_hostdata));
889
890 if(shpnt==NULL) {
891 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +0100892 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 }
Ondrej Zarye98878f2015-02-06 23:11:25 +0100894 aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 if (!aha1542_test_port(bases[indx], shpnt))
896 goto unregister;
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 base_io = bases[indx];
899
900 /* Set the Bus on/off-times as not to ruin floppy performance */
901 {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100902 u8 oncmd[] = {CMD_BUSON_TIME, 7};
903 u8 offcmd[] = {CMD_BUSOFF_TIME, 5};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 if (setup_called[indx]) {
906 oncmd[1] = setup_buson[indx];
907 offcmd[1] = setup_busoff[indx];
908 }
909 aha1542_intr_reset(base_io);
910 aha1542_out(base_io, oncmd, 2);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100911 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
912 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 aha1542_intr_reset(base_io);
914 aha1542_out(base_io, offcmd, 2);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100915 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
916 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 if (setup_dmaspeed[indx] >= 0) {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100918 u8 dmacmd[] = {CMD_DMASPEED, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 dmacmd[1] = setup_dmaspeed[indx];
920 aha1542_intr_reset(base_io);
921 aha1542_out(base_io, dmacmd, 2);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100922 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
923 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 }
925 while (0) {
926fail:
927 printk(KERN_ERR "aha1542_detect: setting bus on/off-time failed\n");
928 }
929 aha1542_intr_reset(base_io);
930 }
931 if (aha1542_query(base_io, &trans))
932 goto unregister;
933
934 if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1)
935 goto unregister;
936
937 printk(KERN_INFO "Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level);
938 if (dma_chan != 0xFF)
939 printk(", DMA priority %d", dma_chan);
940 printk("\n");
941
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 setup_mailboxes(base_io, shpnt);
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
945 spin_lock_irqsave(&aha1542_lock, flags);
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400946 if (request_irq(irq_level, do_aha1542_intr_handle, 0,
947 "aha1542", shpnt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
949 spin_unlock_irqrestore(&aha1542_lock, flags);
950 goto unregister;
951 }
952 if (dma_chan != 0xFF) {
953 if (request_dma(dma_chan, "aha1542")) {
954 printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400955 free_irq(irq_level, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 spin_unlock_irqrestore(&aha1542_lock, flags);
957 goto unregister;
958 }
959 if (dma_chan == 0 || dma_chan >= 5) {
960 set_dma_mode(dma_chan, DMA_MODE_CASCADE);
961 enable_dma(dma_chan);
962 }
963 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 shpnt->this_id = scsi_id;
966 shpnt->unique_id = base_io;
967 shpnt->io_port = base_io;
968 shpnt->n_io_port = 4; /* Number of bytes of I/O space used */
969 shpnt->dma_channel = dma_chan;
970 shpnt->irq = irq_level;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100971 aha1542->bios_translation = trans;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 if (trans == BIOS_TRANSLATION_25563)
973 printk(KERN_INFO "aha1542.c: Using extended bios translation\n");
Ondrej Zarye98878f2015-02-06 23:11:25 +0100974 aha1542->aha1542_last_mbi_used = (2 * AHA1542_MAILBOXES - 1);
975 aha1542->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
976 memset(aha1542->SCint, 0, sizeof(aha1542->SCint));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 spin_unlock_irqrestore(&aha1542_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Ondrej Zary643a7c42015-02-06 23:11:22 +0100979 if (scsi_add_host(shpnt, pdev)) {
980 if (shpnt->dma_channel != 0xff)
981 free_dma(shpnt->dma_channel);
982 free_irq(irq_level, shpnt);
983 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 }
985
Ondrej Zary643a7c42015-02-06 23:11:22 +0100986 scsi_scan_host(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Ondrej Zary643a7c42015-02-06 23:11:22 +0100988 return shpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989unregister:
990 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +0100991 scsi_host_put(shpnt);
992 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 };
995
Ondrej Zary643a7c42015-02-06 23:11:22 +0100996 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997}
998
999static int aha1542_release(struct Scsi_Host *shost)
1000{
Ondrej Zary643a7c42015-02-06 23:11:22 +01001001 scsi_remove_host(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 if (shost->irq)
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001003 free_irq(shost->irq, shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (shost->dma_channel != 0xff)
1005 free_dma(shost->dma_channel);
1006 if (shost->io_port && shost->n_io_port)
1007 release_region(shost->io_port, shost->n_io_port);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001008 scsi_host_put(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 return 0;
1010}
1011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013/*
1014 * This is a device reset. This is handled by sending a special command
1015 * to the device.
1016 */
1017static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
1018{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001019 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001021 struct mailbox *mb = aha1542->mb;
Ondrej Zarycb5b5702015-02-06 23:11:27 +01001022 u8 target = SCpnt->device->id;
1023 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001025 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +01001028 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 if (mbo >= AHA1542_MAILBOXES)
1030 mbo = 0;
1031
1032 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001033 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 break;
1035 mbo++;
1036 if (mbo >= AHA1542_MAILBOXES)
1037 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001038 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Ondrej Zarye98878f2015-02-06 23:11:25 +01001040 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 panic("Unable to find empty mailbox for aha1542.\n");
1042
Ondrej Zarye98878f2015-02-06 23:11:25 +01001043 aha1542->SCint[mbo] = SCpnt; /* This will effectively
1044 prevent someone else from
1045 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Ondrej Zarye98878f2015-02-06 23:11:25 +01001047 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 spin_unlock_irqrestore(&aha1542_lock, flags);
1049
Ondrej Zary10be6252015-02-06 23:11:24 +01001050 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
1052 memset(&ccb[mbo], 0, sizeof(struct ccb));
1053
1054 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
1055
1056 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
1057
1058 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
1059 ccb[mbo].commlinkid = 0;
1060
1061 /*
1062 * Now tell the 1542 to flush all pending commands for this
1063 * target
1064 */
Ondrej Zary0c2b6482015-02-06 23:11:33 +01001065 aha1542_outb(SCpnt->device->host->io_port, CMD_START_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Jeff Garzik017560f2005-10-24 18:04:36 -04001067 scmd_printk(KERN_WARNING, SCpnt,
1068 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071}
1072
Ondrej Zary8537cba2015-02-06 23:11:37 +01001073static int aha1542_reset(Scsi_Cmnd *SCpnt, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001075 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 int i;
1077
1078 /*
1079 * This does a scsi reset for all devices on the bus.
1080 * In principle, we could also reset the 1542 - should
1081 * we do this? Try this first, and we can add that later
1082 * if it turns out to be useful.
1083 */
Ondrej Zary8537cba2015-02-06 23:11:37 +01001084 outb(reset_cmd, CONTROL(SCpnt->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086 /*
1087 * Wait for the thing to settle down a bit. Unfortunately
1088 * this is going to basically lock up the machine while we
1089 * wait for this to complete. To be 100% correct, we need to
1090 * check for timeout, and if we are doing something like this
1091 * we are pretty desperate anyways.
1092 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 ssleep(4);
1094 spin_lock_irq(SCpnt->device->host->host_lock);
1095
Ondrej Zary2093bfa2015-02-06 23:11:31 +01001096 if (!wait_mask(STATUS(SCpnt->device->host->io_port),
Ondrej Zarya13b3722015-02-06 23:11:34 +01001097 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
1098 spin_unlock_irq(SCpnt->device->host->host_lock);
1099 return FAILED;
1100 }
Ondrej Zary8537cba2015-02-06 23:11:37 +01001101 /*
1102 * We need to do this too before the 1542 can interact with
1103 * us again after host reset.
1104 */
1105 if (reset_cmd & HRST)
1106 setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 /*
1108 * Now try to pick up the pieces. For all pending commands,
1109 * free any internal data structures, and basically clear things
1110 * out. We do not try and restart any commands or anything -
1111 * the strategy handler takes care of that crap.
1112 */
1113 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
1114
1115 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001116 if (aha1542->SCint[i] != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 Scsi_Cmnd *SCtmp;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001118 SCtmp = aha1542->SCint[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (SCtmp->device->soft_reset) {
1121 /*
1122 * If this device implements the soft reset option,
1123 * then it is still holding onto the command, and
1124 * may yet complete it. In this case, we don't
1125 * flush the data.
1126 */
1127 continue;
1128 }
Jesper Juhlc9475cb2005-11-07 01:01:26 -08001129 kfree(SCtmp->host_scribble);
1130 SCtmp->host_scribble = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001131 aha1542->SCint[i] = NULL;
1132 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 }
1134 }
1135
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001136 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138}
1139
Ondrej Zary8537cba2015-02-06 23:11:37 +01001140static int aha1542_bus_reset(Scsi_Cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
Ondrej Zary8537cba2015-02-06 23:11:37 +01001142 return aha1542_reset(SCpnt, SCRST);
1143}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Ondrej Zary8537cba2015-02-06 23:11:37 +01001145static int aha1542_host_reset(Scsi_Cmnd *SCpnt)
1146{
1147 return aha1542_reset(SCpnt, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148}
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150static int aha1542_biosparam(struct scsi_device *sdev,
1151 struct block_device *bdev, sector_t capacity, int *ip)
1152{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001153 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 int translation_algorithm;
1155 int size = capacity;
1156
Ondrej Zarye98878f2015-02-06 23:11:25 +01001157 translation_algorithm = aha1542->bios_translation;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
1159 if ((size >> 11) > 1024 && translation_algorithm == BIOS_TRANSLATION_25563) {
1160 /* Please verify that this is the same as what DOS returns */
1161 ip[0] = 255;
1162 ip[1] = 63;
1163 ip[2] = size / 255 / 63;
1164 } else {
1165 ip[0] = 64;
1166 ip[1] = 32;
1167 ip[2] = size >> 11;
1168 }
1169
1170 return 0;
1171}
1172MODULE_LICENSE("GPL");
1173
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001174static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001175 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 .proc_name = "aha1542",
1177 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 .eh_device_reset_handler= aha1542_dev_reset,
1180 .eh_bus_reset_handler = aha1542_bus_reset,
1181 .eh_host_reset_handler = aha1542_host_reset,
1182 .bios_param = aha1542_biosparam,
1183 .can_queue = AHA1542_MAILBOXES,
1184 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001185 .sg_tablesize = 16,
1186 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 .unchecked_isa_dma = 1,
1188 .use_clustering = ENABLE_CLUSTERING,
1189};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001190
1191static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1192{
1193 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1194
1195 if (!sh)
1196 return 0;
1197
1198 dev_set_drvdata(pdev, sh);
1199 return 1;
1200}
1201
1202static int aha1542_isa_remove(struct device *pdev,
1203 unsigned int ndev)
1204{
1205 aha1542_release(dev_get_drvdata(pdev));
1206 dev_set_drvdata(pdev, NULL);
1207 return 0;
1208}
1209
1210static struct isa_driver aha1542_isa_driver = {
1211 .match = aha1542_isa_match,
1212 .remove = aha1542_isa_remove,
1213 .driver = {
1214 .name = "aha1542"
1215 },
1216};
1217static int isa_registered;
1218
1219#ifdef CONFIG_PNP
1220static struct pnp_device_id aha1542_pnp_ids[] = {
1221 { .id = "ADP1542" },
1222 { .id = "" }
1223};
1224MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1225
1226static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1227{
1228 int indx;
1229 struct Scsi_Host *sh;
1230
1231 for (indx = 0; indx < ARRAY_SIZE(bases); indx++) {
1232 if (bases[indx])
1233 continue;
1234
1235 if (pnp_activate_dev(pdev) < 0)
1236 continue;
1237
1238 bases[indx] = pnp_port_start(pdev, 0);
1239
1240 /* The card can be queried for its DMA, we have
1241 the DMA set up that is enough */
1242
1243 printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]);
1244 }
1245
1246 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1247 if (!sh)
1248 return -ENODEV;
1249
1250 pnp_set_drvdata(pdev, sh);
1251 return 0;
1252}
1253
1254static void aha1542_pnp_remove(struct pnp_dev *pdev)
1255{
1256 aha1542_release(pnp_get_drvdata(pdev));
1257 pnp_set_drvdata(pdev, NULL);
1258}
1259
1260static struct pnp_driver aha1542_pnp_driver = {
1261 .name = "aha1542",
1262 .id_table = aha1542_pnp_ids,
1263 .probe = aha1542_pnp_probe,
1264 .remove = aha1542_pnp_remove,
1265};
1266static int pnp_registered;
1267#endif /* CONFIG_PNP */
1268
1269static int __init aha1542_init(void)
1270{
1271 int ret = 0;
1272#ifdef MODULE
1273 int atbt = -1;
1274
1275 bases[0] = aha1542[0];
1276 setup_buson[0] = aha1542[1];
1277 setup_busoff[0] = aha1542[2];
1278
1279 switch (aha1542[3]) {
1280 case 5:
1281 atbt = 0x00;
1282 break;
1283 case 6:
1284 atbt = 0x04;
1285 break;
1286 case 7:
1287 atbt = 0x01;
1288 break;
1289 case 8:
1290 atbt = 0x02;
1291 break;
1292 case 10:
1293 atbt = 0x03;
1294 break;
1295 };
1296 setup_dmaspeed[0] = atbt;
1297#endif
1298
1299#ifdef CONFIG_PNP
1300 if (isapnp) {
1301 ret = pnp_register_driver(&aha1542_pnp_driver);
1302 if (!ret)
1303 pnp_registered = 1;
1304 }
1305#endif
1306 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1307 if (!ret)
1308 isa_registered = 1;
1309
1310#ifdef CONFIG_PNP
1311 if (pnp_registered)
1312 ret = 0;
1313#endif
1314 if (isa_registered)
1315 ret = 0;
1316
1317 return ret;
1318}
1319
1320static void __exit aha1542_exit(void)
1321{
1322#ifdef CONFIG_PNP
1323 if (pnp_registered)
1324 pnp_unregister_driver(&aha1542_pnp_driver);
1325#endif
1326 if (isa_registered)
1327 isa_unregister_driver(&aha1542_isa_driver);
1328}
1329
1330module_init(aha1542_init);
1331module_exit(aha1542_exit);