blob: 8851719d8d0eb7e7c90af568f016adb406ef1f9e [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
123
124
125#define WAITnexttimeout 3000000
126
127static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
128static int aha1542_restart(struct Scsi_Host *shost);
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400129static void aha1542_intr_handle(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Ondrej Zaryf1bbef62015-02-06 23:11:26 +0100131static inline void aha1542_intr_reset(u16 base)
132{
133 outb(IRST, CONTROL(base));
134}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136#define WAIT(port, mask, allof, noneof) \
137 { register int WAITbits; \
138 register int WAITtimeout = WAITnexttimeout; \
139 while (1) { \
140 WAITbits = inb(port) & (mask); \
141 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
142 break; \
143 if (--WAITtimeout == 0) goto fail; \
144 } \
145 }
146
147/* Similar to WAIT, except we use the udelay call to regulate the
148 amount of time we wait. */
149#define WAITd(port, mask, allof, noneof, timeout) \
150 { register int WAITbits; \
151 register int WAITtimeout = timeout; \
152 while (1) { \
153 WAITbits = inb(port) & (mask); \
154 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
155 break; \
156 mdelay(1); \
157 if (--WAITtimeout == 0) goto fail; \
158 } \
159 }
160
161static void aha1542_stat(void)
162{
163/* int s = inb(STATUS), i = inb(INTRFLAGS);
164 printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
165}
166
167/* This is a bit complicated, but we need to make sure that an interrupt
168 routine does not send something out while we are in the middle of this.
169 Fortunately, it is only at boot time that multi-byte messages
170 are ever sent. */
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100171static int aha1542_out(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
173 unsigned long flags = 0;
174 int got_lock;
175
176 if (len == 1) {
177 got_lock = 0;
178 while (1 == 1) {
179 WAIT(STATUS(base), CDF, 0, CDF);
180 spin_lock_irqsave(&aha1542_lock, flags);
181 if (inb(STATUS(base)) & CDF) {
182 spin_unlock_irqrestore(&aha1542_lock, flags);
183 continue;
184 }
185 outb(*cmdp, DATA(base));
186 spin_unlock_irqrestore(&aha1542_lock, flags);
187 return 0;
188 }
189 } else {
190 spin_lock_irqsave(&aha1542_lock, flags);
191 got_lock = 1;
192 while (len--) {
193 WAIT(STATUS(base), CDF, 0, CDF);
194 outb(*cmdp++, DATA(base));
195 }
196 spin_unlock_irqrestore(&aha1542_lock, flags);
197 }
198 return 0;
199fail:
200 if (got_lock)
201 spin_unlock_irqrestore(&aha1542_lock, flags);
202 printk(KERN_ERR "aha1542_out failed(%d): ", len + 1);
203 aha1542_stat();
204 return 1;
205}
206
207/* Only used at boot time, so we do not need to worry about latency as much
208 here */
209
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100210static int aha1542_in(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211{
212 unsigned long flags;
213
214 spin_lock_irqsave(&aha1542_lock, flags);
215 while (len--) {
216 WAIT(STATUS(base), DF, DF, 0);
217 *cmdp++ = inb(DATA(base));
218 }
219 spin_unlock_irqrestore(&aha1542_lock, flags);
220 return 0;
221fail:
222 spin_unlock_irqrestore(&aha1542_lock, flags);
223 printk(KERN_ERR "aha1542_in failed(%d): ", len + 1);
224 aha1542_stat();
225 return 1;
226}
227
228/* Similar to aha1542_in, except that we wait a very short period of time.
229 We use this if we know the board is alive and awake, but we are not sure
230 if the board will respond to the command we are about to send or not */
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100231static int aha1542_in1(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
233 unsigned long flags;
234
235 spin_lock_irqsave(&aha1542_lock, flags);
236 while (len--) {
237 WAITd(STATUS(base), DF, DF, 0, 100);
238 *cmdp++ = inb(DATA(base));
239 }
240 spin_unlock_irqrestore(&aha1542_lock, flags);
241 return 0;
242fail:
243 spin_unlock_irqrestore(&aha1542_lock, flags);
244 return 1;
245}
246
247static int makecode(unsigned hosterr, unsigned scsierr)
248{
249 switch (hosterr) {
250 case 0x0:
251 case 0xa: /* Linked command complete without error and linked normally */
252 case 0xb: /* Linked command complete without error, interrupt generated */
253 hosterr = 0;
254 break;
255
256 case 0x11: /* Selection time out-The initiator selection or target
257 reselection was not complete within the SCSI Time out period */
258 hosterr = DID_TIME_OUT;
259 break;
260
261 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
262 than was allocated by the Data Length field or the sum of the
263 Scatter / Gather Data Length fields. */
264
265 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
266
267 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
268 invalid. This usually indicates a software failure. */
269
270 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
271 This usually indicates a software failure. */
272
273 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
274 of linked CCB's does not specify the same logical unit number as
275 the first. */
276 case 0x18: /* Invalid Target Direction received from Host-The direction of a
277 Target Mode CCB was invalid. */
278
279 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
280 received to service data transfer between the same target LUN
281 and initiator SCSI ID in the same direction. */
282
283 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
284 length segment or invalid segment list boundaries was received.
285 A CCB parameter was invalid. */
286 DEB(printk("Aha1542: %x %x\n", hosterr, scsierr));
287 hosterr = DID_ERROR; /* Couldn't find any better */
288 break;
289
290 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
291 phase sequence was requested by the target. The host adapter
292 will generate a SCSI Reset Condition, notifying the host with
293 a SCRD interrupt */
294 hosterr = DID_RESET;
295 break;
296 default:
297 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
298 break;
299 }
300 return scsierr | (hosterr << 16);
301}
302
Ondrej Zary643a7c42015-02-06 23:11:22 +0100303static int aha1542_test_port(int bse, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100305 u8 inquiry_cmd[] = {CMD_INQUIRY};
306 u8 inquiry_result[4];
307 u8 *cmdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 int len;
309 volatile int debug = 0;
310
311 /* Quick and dirty test for presence of the card. */
312 if (inb(STATUS(bse)) == 0xff)
313 return 0;
314
315 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
316
317 /* DEB(printk("aha1542_test_port called \n")); */
318
319 /* In case some other card was probing here, reset interrupts */
320 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
321
322 outb(SRST | IRST /*|SCRST */ , CONTROL(bse));
323
324 mdelay(20); /* Wait a little bit for things to settle down. */
325
326 debug = 1;
327 /* Expect INIT and IDLE, any of the others are bad */
328 WAIT(STATUS(bse), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
329
330 debug = 2;
331 /* Shouldn't have generated any interrupts during reset */
332 if (inb(INTRFLAGS(bse)) & INTRMASK)
333 goto fail;
334
335
336 /* Perform a host adapter inquiry instead so we do not need to set
337 up the mailboxes ahead of time */
338
339 aha1542_out(bse, inquiry_cmd, 1);
340
341 debug = 3;
342 len = 4;
343 cmdp = &inquiry_result[0];
344
345 while (len--) {
346 WAIT(STATUS(bse), DF, DF, 0);
347 *cmdp++ = inb(DATA(bse));
348 }
349
350 debug = 8;
351 /* Reading port should reset DF */
352 if (inb(STATUS(bse)) & DF)
353 goto fail;
354
355 debug = 9;
356 /* When HACC, command is completed, and we're though testing */
357 WAIT(INTRFLAGS(bse), HACC, HACC, 0);
358 /* now initialize adapter */
359
360 debug = 10;
361 /* Clear interrupts */
362 outb(IRST, CONTROL(bse));
363
364 debug = 11;
365
366 return debug; /* 1 = ok */
367fail:
368 return 0; /* 0 = not ok */
369}
370
371/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400372static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 unsigned long flags;
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400375 struct Scsi_Host *shost = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
377 spin_lock_irqsave(shost->host_lock, flags);
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400378 aha1542_intr_handle(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 spin_unlock_irqrestore(shost->host_lock, flags);
380 return IRQ_HANDLED;
381}
382
383/* A "high" level interrupt handler */
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400384static void aha1542_intr_handle(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100386 struct aha1542_hostdata *aha1542 = shost_priv(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 void (*my_done) (Scsi_Cmnd *) = NULL;
388 int errstatus, mbi, mbo, mbistatus;
389 int number_serviced;
390 unsigned long flags;
391 Scsi_Cmnd *SCtmp;
392 int flag;
393 int needs_restart;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100394 struct mailbox *mb = aha1542->mb;
395 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397#ifdef DEBUG
398 {
399 flag = inb(INTRFLAGS(shost->io_port));
400 printk(KERN_DEBUG "aha1542_intr_handle: ");
401 if (!(flag & ANYINTR))
402 printk("no interrupt?");
403 if (flag & MBIF)
404 printk("MBIF ");
405 if (flag & MBOA)
406 printk("MBOF ");
407 if (flag & HACC)
408 printk("HACC ");
409 if (flag & SCRD)
410 printk("SCRD ");
411 printk("status %02x\n", inb(STATUS(shost->io_port)));
412 };
413#endif
414 number_serviced = 0;
415 needs_restart = 0;
416
417 while (1 == 1) {
418 flag = inb(INTRFLAGS(shost->io_port));
419
420 /* Check for unusual interrupts. If any of these happen, we should
421 probably do something special, but for now just printing a message
422 is sufficient. A SCSI reset detected is something that we really
423 need to deal with in some way. */
424 if (flag & ~MBIF) {
425 if (flag & MBOA)
426 printk("MBOF ");
427 if (flag & HACC)
428 printk("HACC ");
429 if (flag & SCRD) {
430 needs_restart = 1;
431 printk("SCRD ");
432 }
433 }
434 aha1542_intr_reset(shost->io_port);
435
436 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100437 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 if (mbi >= 2 * AHA1542_MAILBOXES)
439 mbi = AHA1542_MAILBOXES;
440
441 do {
442 if (mb[mbi].status != 0)
443 break;
444 mbi++;
445 if (mbi >= 2 * AHA1542_MAILBOXES)
446 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100447 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449 if (mb[mbi].status == 0) {
450 spin_unlock_irqrestore(&aha1542_lock, flags);
451 /* Hmm, no mail. Must have read it the last time around */
452 if (!number_serviced && !needs_restart)
453 printk(KERN_WARNING "aha1542.c: interrupt received, but no mail.\n");
454 /* We detected a reset. Restart all pending commands for
455 devices that use the hard reset option */
456 if (needs_restart)
457 aha1542_restart(shost);
458 return;
459 };
460
Ondrej Zary10be6252015-02-06 23:11:24 +0100461 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 mbistatus = mb[mbi].status;
463 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100464 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 spin_unlock_irqrestore(&aha1542_lock, flags);
466
467#ifdef DEBUG
468 {
469 if (ccb[mbo].tarstat | ccb[mbo].hastat)
470 printk(KERN_DEBUG "aha1542_command: returning %x (status %d)\n",
471 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
472 };
473#endif
474
475 if (mbistatus == 3)
476 continue; /* Aborted command not found */
477
478#ifdef DEBUG
479 printk(KERN_DEBUG "...done %d %d\n", mbo, mbi);
480#endif
481
Ondrej Zarye98878f2015-02-06 23:11:25 +0100482 SCtmp = aha1542->SCint[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 if (!SCtmp || !SCtmp->scsi_done) {
485 printk(KERN_WARNING "aha1542_intr_handle: Unexpected interrupt\n");
486 printk(KERN_WARNING "tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat,
487 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
488 return;
489 }
490 my_done = SCtmp->scsi_done;
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800491 kfree(SCtmp->host_scribble);
492 SCtmp->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 /* Fetch the sense data, and tuck it away, in the required slot. The
494 Adaptec automatically fetches it, and there is no guarantee that
495 we will still have it in the cdb when we come back */
496 if (ccb[mbo].tarstat == 2)
497 memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900498 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
500
501 /* is there mail :-) */
502
503 /* more error checking left out here */
504 if (mbistatus != 1)
505 /* This is surely wrong, but I don't know what's right */
506 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
507 else
508 errstatus = 0;
509
510#ifdef DEBUG
511 if (errstatus)
512 printk(KERN_DEBUG "(aha1542 error:%x %x %x) ", errstatus,
513 ccb[mbo].hastat, ccb[mbo].tarstat);
514#endif
515
516 if (ccb[mbo].tarstat == 2) {
517#ifdef DEBUG
518 int i;
519#endif
520 DEB(printk("aha1542_intr_handle: sense:"));
521#ifdef DEBUG
522 for (i = 0; i < 12; i++)
523 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen + i]);
524 printk("\n");
525#endif
526 /*
527 DEB(printk("aha1542_intr_handle: buf:"));
528 for (i = 0; i < bufflen; i++)
529 printk("%02x ", ((unchar *)buff)[i]);
530 printk("\n");
531 */
532 }
533 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
534 SCtmp->result = errstatus;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100535 aha1542->SCint[mbo] = NULL; /* This effectively frees up the mailbox slot, as
536 far as queuecommand is concerned */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 my_done(SCtmp);
538 number_serviced++;
539 };
540}
541
Jeff Garzikf2812332010-11-16 02:10:29 -0500542static int aha1542_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100544 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100545 u8 ahacmd = CMD_START_SCSI;
546 u8 direction;
547 u8 *cmd = (u8 *) SCpnt->cmnd;
548 u8 target = SCpnt->device->id;
549 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 unsigned long flags;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300551 int bufflen = scsi_bufflen(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100553 struct mailbox *mb = aha1542->mb;
554 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
556 DEB(int i);
557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 DEB(if (target > 1) {
559 SCpnt->result = DID_TIME_OUT << 16;
560 done(SCpnt); return 0;
561 }
562 );
563
564 if (*cmd == REQUEST_SENSE) {
565 /* Don't do the command - we have the sense data already */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 SCpnt->result = 0;
567 done(SCpnt);
568 return 0;
569 }
570#ifdef DEBUG
571 if (*cmd == READ_10 || *cmd == WRITE_10)
572 i = xscsi2int(cmd + 2);
573 else if (*cmd == READ_6 || *cmd == WRITE_6)
574 i = scsi2int(cmd + 2);
575 else
576 i = -1;
577 if (done)
578 printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
579 else
580 printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
581 aha1542_stat();
582 printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:");
583 for (i = 0; i < SCpnt->cmd_len; i++)
584 printk("%02x ", cmd[i]);
585 printk("\n");
586 if (*cmd == WRITE_10 || *cmd == WRITE_6)
587 return 0; /* we are still testing, so *don't* write */
588#endif
589 /* Use the outgoing mailboxes in a round-robin fashion, because this
590 is how the host adapter will scan for them */
591
592 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100593 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 if (mbo >= AHA1542_MAILBOXES)
595 mbo = 0;
596
597 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +0100598 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 break;
600 mbo++;
601 if (mbo >= AHA1542_MAILBOXES)
602 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100603 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
Ondrej Zarye98878f2015-02-06 23:11:25 +0100605 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 panic("Unable to find empty mailbox for aha1542.\n");
607
Ondrej Zarye98878f2015-02-06 23:11:25 +0100608 aha1542->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from
609 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Ondrej Zarye98878f2015-02-06 23:11:25 +0100611 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 spin_unlock_irqrestore(&aha1542_lock, flags);
613
614#ifdef DEBUG
615 printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
616#endif
617
Ondrej Zary10be6252015-02-06 23:11:24 +0100618 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 memset(&ccb[mbo], 0, sizeof(struct ccb));
621
622 ccb[mbo].cdblen = SCpnt->cmd_len;
623
624 direction = 0;
625 if (*cmd == READ_10 || *cmd == READ_6)
626 direction = 8;
627 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
628 direction = 16;
629
630 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
631
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300632 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200633 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 struct chain *cptr;
635#ifdef DEBUG
636 unsigned char *ptr;
637#endif
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300638 int i, sg_count = scsi_sg_count(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300640 SCpnt->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
641 GFP_KERNEL | GFP_DMA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 cptr = (struct chain *) SCpnt->host_scribble;
643 if (cptr == NULL) {
644 /* free the claimed mailbox slot */
Ondrej Zarye98878f2015-02-06 23:11:25 +0100645 aha1542->SCint[mbo] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return SCSI_MLQUEUE_HOST_BUSY;
647 }
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300648 scsi_for_each_sg(SCpnt, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100649 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
650 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200651 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300653 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100654 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655#ifdef DEBUG
656 printk("cptr %x: ", cptr);
657 ptr = (unsigned char *) cptr;
658 for (i = 0; i < 18; i++)
659 printk("%02x ", ptr[i]);
660#endif
661 } else {
662 ccb[mbo].op = 0; /* SCSI Initiator Command */
663 SCpnt->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300664 any2scsi(ccb[mbo].datalen, 0);
665 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 };
667 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
668 ccb[mbo].rsalen = 16;
669 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
670 ccb[mbo].commlinkid = 0;
671
672#ifdef DEBUG
673 {
674 int i;
675 printk(KERN_DEBUG "aha1542_command: sending.. ");
676 for (i = 0; i < sizeof(ccb[mbo]) - 10; i++)
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100677 printk("%02x ", ((u8 *) &ccb[mbo])[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 };
679#endif
680
681 if (done) {
682 DEB(printk("aha1542_queuecommand: now waiting for interrupt ");
683 aha1542_stat());
684 SCpnt->scsi_done = done;
685 mb[mbo].status = 1;
686 aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); /* start scsi command */
687 DEB(aha1542_stat());
688 } else
689 printk("aha1542_queuecommand: done can't be NULL\n");
690
691 return 0;
692}
693
Jeff Garzikf2812332010-11-16 02:10:29 -0500694static DEF_SCSI_QCMD(aha1542_queuecommand)
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696/* Initialize mailboxes */
697static void setup_mailboxes(int bse, struct Scsi_Host *shpnt)
698{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100699 struct aha1542_hostdata *aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100701 struct mailbox *mb = aha1542->mb;
702 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100704 u8 cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 for (i = 0; i < AHA1542_MAILBOXES; i++) {
707 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100708 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 };
710 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
Ondrej Zary10be6252015-02-06 23:11:24 +0100711 any2scsi((cmd + 2), isa_virt_to_bus(mb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 aha1542_out(bse, cmd, 5);
713 WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0);
714 while (0) {
715fail:
716 printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n");
717 }
718 aha1542_intr_reset(bse);
719}
720
Ondrej Zary643a7c42015-02-06 23:11:22 +0100721static 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 -0700722{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100723 u8 inquiry_cmd[] = {CMD_RETCONF};
724 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 int i;
726 i = inb(STATUS(base_io));
727 if (i & DF) {
728 i = inb(DATA(base_io));
729 };
730 aha1542_out(base_io, inquiry_cmd, 1);
731 aha1542_in(base_io, inquiry_result, 3);
732 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
733 while (0) {
734fail:
735 printk(KERN_ERR "aha1542_detect: query board settings\n");
736 }
737 aha1542_intr_reset(base_io);
738 switch (inquiry_result[0]) {
739 case 0x80:
740 *dma_chan = 7;
741 break;
742 case 0x40:
743 *dma_chan = 6;
744 break;
745 case 0x20:
746 *dma_chan = 5;
747 break;
748 case 0x01:
749 *dma_chan = 0;
750 break;
751 case 0:
752 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
753 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
754 *dma_chan = 0xFF;
755 break;
756 default:
757 printk(KERN_ERR "Unable to determine Adaptec DMA priority. Disabling board\n");
758 return -1;
759 };
760 switch (inquiry_result[1]) {
761 case 0x40:
762 *irq_level = 15;
763 break;
764 case 0x20:
765 *irq_level = 14;
766 break;
767 case 0x8:
768 *irq_level = 12;
769 break;
770 case 0x4:
771 *irq_level = 11;
772 break;
773 case 0x2:
774 *irq_level = 10;
775 break;
776 case 0x1:
777 *irq_level = 9;
778 break;
779 default:
780 printk(KERN_ERR "Unable to determine Adaptec IRQ level. Disabling board\n");
781 return -1;
782 };
783 *scsi_id = inquiry_result[2] & 7;
784 return 0;
785}
786
787/* This function should only be called for 1542C boards - we can detect
788 the special firmware settings and unlock the board */
789
Ondrej Zary643a7c42015-02-06 23:11:22 +0100790static int aha1542_mbenable(int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100792 static u8 mbenable_cmd[3];
793 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 int retval;
795
796 retval = BIOS_TRANSLATION_6432;
797
798 mbenable_cmd[0] = CMD_EXTBIOS;
799 aha1542_out(base, mbenable_cmd, 1);
800 if (aha1542_in1(base, mbenable_result, 2))
801 return retval;
802 WAITd(INTRFLAGS(base), INTRMASK, HACC, 0, 100);
803 aha1542_intr_reset(base);
804
805 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
806 mbenable_cmd[0] = CMD_MBENABLE;
807 mbenable_cmd[1] = 0;
808 mbenable_cmd[2] = mbenable_result[1];
809
810 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
811 retval = BIOS_TRANSLATION_25563;
812
813 aha1542_out(base, mbenable_cmd, 3);
814 WAIT(INTRFLAGS(base), INTRMASK, HACC, 0);
815 };
816 while (0) {
817fail:
818 printk(KERN_ERR "aha1542_mbenable: Mailbox init failed\n");
819 }
820 aha1542_intr_reset(base);
821 return retval;
822}
823
824/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100825static int aha1542_query(int base_io, int *transl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100827 u8 inquiry_cmd[] = {CMD_INQUIRY};
828 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 int i;
830 i = inb(STATUS(base_io));
831 if (i & DF) {
832 i = inb(DATA(base_io));
833 };
834 aha1542_out(base_io, inquiry_cmd, 1);
835 aha1542_in(base_io, inquiry_result, 4);
836 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
837 while (0) {
838fail:
839 printk(KERN_ERR "aha1542_detect: query card type\n");
840 }
841 aha1542_intr_reset(base_io);
842
843 *transl = BIOS_TRANSLATION_6432; /* Default case */
844
845 /* For an AHA1740 series board, we ignore the board since there is a
846 hardware bug which can lead to wrong blocks being returned if the board
847 is operating in the 1542 emulation mode. Since there is an extended mode
848 driver, we simply ignore the board and let the 1740 driver pick it up.
849 */
850
851 if (inquiry_result[0] == 0x43) {
852 printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
853 return 1;
854 };
855
856 /* Always call this - boards that do not support extended bios translation
857 will ignore the command, and we will set the proper default */
858
859 *transl = aha1542_mbenable(base_io);
860
861 return 0;
862}
863
864#ifndef MODULE
865static char *setup_str[MAXBOARDS] __initdata;
866static int setup_idx = 0;
867
868static void __init aha1542_setup(char *str, int *ints)
869{
870 const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
871 int setup_portbase;
872
873 if (setup_idx >= MAXBOARDS) {
874 printk(KERN_ERR "aha1542: aha1542_setup called too many times! Bad LILO params ?\n");
875 printk(KERN_ERR " Entryline 1: %s\n", setup_str[0]);
876 printk(KERN_ERR " Entryline 2: %s\n", setup_str[1]);
877 printk(KERN_ERR " This line: %s\n", str);
878 return;
879 }
880 if (ints[0] < 1 || ints[0] > 4) {
881 printk(KERN_ERR "aha1542: %s\n", str);
882 printk(ahausage);
883 printk(KERN_ERR "aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n");
884 }
885 setup_called[setup_idx] = ints[0];
886 setup_str[setup_idx] = str;
887
888 setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */
889 setup_buson[setup_idx] = ints[0] >= 2 ? ints[2] : 7;
890 setup_busoff[setup_idx] = ints[0] >= 3 ? ints[3] : 5;
891 if (ints[0] >= 4)
892 {
893 int atbt = -1;
894 switch (ints[4]) {
895 case 5:
896 atbt = 0x00;
897 break;
898 case 6:
899 atbt = 0x04;
900 break;
901 case 7:
902 atbt = 0x01;
903 break;
904 case 8:
905 atbt = 0x02;
906 break;
907 case 10:
908 atbt = 0x03;
909 break;
910 default:
911 printk(KERN_ERR "aha1542: %s\n", str);
912 printk(ahausage);
913 printk(KERN_ERR "aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n");
914 break;
915 }
916 setup_dmaspeed[setup_idx] = atbt;
917 }
918 if (setup_portbase != 0)
919 bases[setup_idx] = setup_portbase;
920
921 ++setup_idx;
922}
923
924static int __init do_setup(char *str)
925{
926 int ints[5];
927
928 int count=setup_idx;
929
Tobias Klauser6391a112006-06-08 22:23:48 -0700930 get_options(str, ARRAY_SIZE(ints), ints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 aha1542_setup(str,ints);
932
933 return count<setup_idx;
934}
935
936__setup("aha1542=",do_setup);
937#endif
938
939/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100940static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
942 unsigned char dma_chan;
943 unsigned char irq_level;
944 unsigned char scsi_id;
945 unsigned long flags;
946 unsigned int base_io;
947 int trans;
948 struct Scsi_Host *shpnt = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100949 struct aha1542_hostdata *aha1542;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 DEB(printk("aha1542_detect: \n"));
952
953 tpnt->proc_name = "aha1542";
954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) {
Ondrej Zary643a7c42015-02-06 23:11:22 +0100956 shpnt = scsi_host_alloc(tpnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 sizeof(struct aha1542_hostdata));
958
959 if(shpnt==NULL) {
960 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +0100961 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 }
Ondrej Zarye98878f2015-02-06 23:11:25 +0100963 aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 if (!aha1542_test_port(bases[indx], shpnt))
965 goto unregister;
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 base_io = bases[indx];
968
969 /* Set the Bus on/off-times as not to ruin floppy performance */
970 {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100971 u8 oncmd[] = {CMD_BUSON_TIME, 7};
972 u8 offcmd[] = {CMD_BUSOFF_TIME, 5};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
974 if (setup_called[indx]) {
975 oncmd[1] = setup_buson[indx];
976 offcmd[1] = setup_busoff[indx];
977 }
978 aha1542_intr_reset(base_io);
979 aha1542_out(base_io, oncmd, 2);
980 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
981 aha1542_intr_reset(base_io);
982 aha1542_out(base_io, offcmd, 2);
983 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
984 if (setup_dmaspeed[indx] >= 0) {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100985 u8 dmacmd[] = {CMD_DMASPEED, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 dmacmd[1] = setup_dmaspeed[indx];
987 aha1542_intr_reset(base_io);
988 aha1542_out(base_io, dmacmd, 2);
989 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
990 }
991 while (0) {
992fail:
993 printk(KERN_ERR "aha1542_detect: setting bus on/off-time failed\n");
994 }
995 aha1542_intr_reset(base_io);
996 }
997 if (aha1542_query(base_io, &trans))
998 goto unregister;
999
1000 if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1)
1001 goto unregister;
1002
1003 printk(KERN_INFO "Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level);
1004 if (dma_chan != 0xFF)
1005 printk(", DMA priority %d", dma_chan);
1006 printk("\n");
1007
1008 DEB(aha1542_stat());
1009 setup_mailboxes(base_io, shpnt);
1010
1011 DEB(aha1542_stat());
1012
1013 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
1014 spin_lock_irqsave(&aha1542_lock, flags);
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001015 if (request_irq(irq_level, do_aha1542_intr_handle, 0,
1016 "aha1542", shpnt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
1018 spin_unlock_irqrestore(&aha1542_lock, flags);
1019 goto unregister;
1020 }
1021 if (dma_chan != 0xFF) {
1022 if (request_dma(dma_chan, "aha1542")) {
1023 printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001024 free_irq(irq_level, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 spin_unlock_irqrestore(&aha1542_lock, flags);
1026 goto unregister;
1027 }
1028 if (dma_chan == 0 || dma_chan >= 5) {
1029 set_dma_mode(dma_chan, DMA_MODE_CASCADE);
1030 enable_dma(dma_chan);
1031 }
1032 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 shpnt->this_id = scsi_id;
1035 shpnt->unique_id = base_io;
1036 shpnt->io_port = base_io;
1037 shpnt->n_io_port = 4; /* Number of bytes of I/O space used */
1038 shpnt->dma_channel = dma_chan;
1039 shpnt->irq = irq_level;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001040 aha1542->bios_translation = trans;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 if (trans == BIOS_TRANSLATION_25563)
1042 printk(KERN_INFO "aha1542.c: Using extended bios translation\n");
Ondrej Zarye98878f2015-02-06 23:11:25 +01001043 aha1542->aha1542_last_mbi_used = (2 * AHA1542_MAILBOXES - 1);
1044 aha1542->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
1045 memset(aha1542->SCint, 0, sizeof(aha1542->SCint));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 spin_unlock_irqrestore(&aha1542_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Ondrej Zary643a7c42015-02-06 23:11:22 +01001048 if (scsi_add_host(shpnt, pdev)) {
1049 if (shpnt->dma_channel != 0xff)
1050 free_dma(shpnt->dma_channel);
1051 free_irq(irq_level, shpnt);
1052 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054
Ondrej Zary643a7c42015-02-06 23:11:22 +01001055 scsi_scan_host(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
Ondrej Zary643a7c42015-02-06 23:11:22 +01001057 return shpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058unregister:
1059 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001060 scsi_host_put(shpnt);
1061 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 };
1064
Ondrej Zary643a7c42015-02-06 23:11:22 +01001065 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066}
1067
1068static int aha1542_release(struct Scsi_Host *shost)
1069{
Ondrej Zary643a7c42015-02-06 23:11:22 +01001070 scsi_remove_host(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 if (shost->irq)
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001072 free_irq(shost->irq, shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 if (shost->dma_channel != 0xff)
1074 free_dma(shost->dma_channel);
1075 if (shost->io_port && shost->n_io_port)
1076 release_region(shost->io_port, shost->n_io_port);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001077 scsi_host_put(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 return 0;
1079}
1080
1081static int aha1542_restart(struct Scsi_Host *shost)
1082{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001083 struct aha1542_hostdata *aha1542 = shost_priv(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 int i;
1085 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
1087 for (i = 0; i < AHA1542_MAILBOXES; i++)
Ondrej Zarye98878f2015-02-06 23:11:25 +01001088 if (aha1542->SCint[i] &&
1089 !(aha1542->SCint[i]->device->soft_reset)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 count++;
1091 }
1092 printk(KERN_DEBUG "Potential to restart %d stalled commands...\n", count);
Ondrej Zary6f82fbf2015-02-06 23:11:23 +01001093
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 return 0;
1095}
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097/*
1098 * This is a device reset. This is handled by sending a special command
1099 * to the device.
1100 */
1101static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
1102{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001103 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001105 struct mailbox *mb = aha1542->mb;
Ondrej Zarycb5b5702015-02-06 23:11:27 +01001106 u8 target = SCpnt->device->id;
1107 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001109 struct ccb *ccb = aha1542->ccb;
Ondrej Zarycb5b5702015-02-06 23:11:27 +01001110 u8 ahacmd = CMD_START_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +01001113 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (mbo >= AHA1542_MAILBOXES)
1115 mbo = 0;
1116
1117 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001118 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 break;
1120 mbo++;
1121 if (mbo >= AHA1542_MAILBOXES)
1122 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001123 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Ondrej Zarye98878f2015-02-06 23:11:25 +01001125 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 panic("Unable to find empty mailbox for aha1542.\n");
1127
Ondrej Zarye98878f2015-02-06 23:11:25 +01001128 aha1542->SCint[mbo] = SCpnt; /* This will effectively
1129 prevent someone else from
1130 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Ondrej Zarye98878f2015-02-06 23:11:25 +01001132 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 spin_unlock_irqrestore(&aha1542_lock, flags);
1134
Ondrej Zary10be6252015-02-06 23:11:24 +01001135 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137 memset(&ccb[mbo], 0, sizeof(struct ccb));
1138
1139 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
1140
1141 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
1142
1143 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
1144 ccb[mbo].commlinkid = 0;
1145
1146 /*
1147 * Now tell the 1542 to flush all pending commands for this
1148 * target
1149 */
1150 aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1);
1151
Jeff Garzik017560f2005-10-24 18:04:36 -04001152 scmd_printk(KERN_WARNING, SCpnt,
1153 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156}
1157
1158static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
1159{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001160 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 int i;
1162
1163 /*
1164 * This does a scsi reset for all devices on the bus.
1165 * In principle, we could also reset the 1542 - should
1166 * we do this? Try this first, and we can add that later
1167 * if it turns out to be useful.
1168 */
1169 outb(SCRST, CONTROL(SCpnt->device->host->io_port));
1170
1171 /*
1172 * Wait for the thing to settle down a bit. Unfortunately
1173 * this is going to basically lock up the machine while we
1174 * wait for this to complete. To be 100% correct, we need to
1175 * check for timeout, and if we are doing something like this
1176 * we are pretty desperate anyways.
1177 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 ssleep(4);
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 spin_lock_irq(SCpnt->device->host->host_lock);
1181
1182 WAIT(STATUS(SCpnt->device->host->io_port),
1183 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
1184
1185 /*
1186 * Now try to pick up the pieces. For all pending commands,
1187 * free any internal data structures, and basically clear things
1188 * out. We do not try and restart any commands or anything -
1189 * the strategy handler takes care of that crap.
1190 */
1191 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
1192
1193 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001194 if (aha1542->SCint[i] != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 Scsi_Cmnd *SCtmp;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001196 SCtmp = aha1542->SCint[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198
1199 if (SCtmp->device->soft_reset) {
1200 /*
1201 * If this device implements the soft reset option,
1202 * then it is still holding onto the command, and
1203 * may yet complete it. In this case, we don't
1204 * flush the data.
1205 */
1206 continue;
1207 }
Jesper Juhlc9475cb2005-11-07 01:01:26 -08001208 kfree(SCtmp->host_scribble);
1209 SCtmp->host_scribble = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001210 aha1542->SCint[i] = NULL;
1211 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 }
1213 }
1214
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001215 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 return SUCCESS;
1217
1218fail:
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001219 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 return FAILED;
1221}
1222
1223static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
1224{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001225 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 int i;
1227
1228 /*
1229 * This does a scsi reset for all devices on the bus.
1230 * In principle, we could also reset the 1542 - should
1231 * we do this? Try this first, and we can add that later
1232 * if it turns out to be useful.
1233 */
1234 outb(HRST | SCRST, CONTROL(SCpnt->device->host->io_port));
1235
1236 /*
1237 * Wait for the thing to settle down a bit. Unfortunately
1238 * this is going to basically lock up the machine while we
1239 * wait for this to complete. To be 100% correct, we need to
1240 * check for timeout, and if we are doing something like this
1241 * we are pretty desperate anyways.
1242 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 ssleep(4);
1244 spin_lock_irq(SCpnt->device->host->host_lock);
1245
1246 WAIT(STATUS(SCpnt->device->host->io_port),
1247 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
1248
1249 /*
1250 * We need to do this too before the 1542 can interact with
1251 * us again.
1252 */
1253 setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host);
1254
1255 /*
1256 * Now try to pick up the pieces. For all pending commands,
1257 * free any internal data structures, and basically clear things
1258 * out. We do not try and restart any commands or anything -
1259 * the strategy handler takes care of that crap.
1260 */
1261 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
1262
1263 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001264 if (aha1542->SCint[i] != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 Scsi_Cmnd *SCtmp;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001266 SCtmp = aha1542->SCint[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 if (SCtmp->device->soft_reset) {
1269 /*
1270 * If this device implements the soft reset option,
1271 * then it is still holding onto the command, and
1272 * may yet complete it. In this case, we don't
1273 * flush the data.
1274 */
1275 continue;
1276 }
Jesper Juhlc9475cb2005-11-07 01:01:26 -08001277 kfree(SCtmp->host_scribble);
1278 SCtmp->host_scribble = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001279 aha1542->SCint[i] = NULL;
1280 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 }
1282 }
1283
Jeff Garzik df0ae242005-05-28 07:57:14 -04001284 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return SUCCESS;
1286
1287fail:
Jeff Garzik df0ae242005-05-28 07:57:14 -04001288 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 return FAILED;
1290}
1291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292static int aha1542_biosparam(struct scsi_device *sdev,
1293 struct block_device *bdev, sector_t capacity, int *ip)
1294{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001295 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 int translation_algorithm;
1297 int size = capacity;
1298
Ondrej Zarye98878f2015-02-06 23:11:25 +01001299 translation_algorithm = aha1542->bios_translation;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
1301 if ((size >> 11) > 1024 && translation_algorithm == BIOS_TRANSLATION_25563) {
1302 /* Please verify that this is the same as what DOS returns */
1303 ip[0] = 255;
1304 ip[1] = 63;
1305 ip[2] = size / 255 / 63;
1306 } else {
1307 ip[0] = 64;
1308 ip[1] = 32;
1309 ip[2] = size >> 11;
1310 }
1311
1312 return 0;
1313}
1314MODULE_LICENSE("GPL");
1315
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001316static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001317 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 .proc_name = "aha1542",
1319 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 .eh_device_reset_handler= aha1542_dev_reset,
1322 .eh_bus_reset_handler = aha1542_bus_reset,
1323 .eh_host_reset_handler = aha1542_host_reset,
1324 .bios_param = aha1542_biosparam,
1325 .can_queue = AHA1542_MAILBOXES,
1326 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001327 .sg_tablesize = 16,
1328 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 .unchecked_isa_dma = 1,
1330 .use_clustering = ENABLE_CLUSTERING,
1331};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001332
1333static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1334{
1335 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1336
1337 if (!sh)
1338 return 0;
1339
1340 dev_set_drvdata(pdev, sh);
1341 return 1;
1342}
1343
1344static int aha1542_isa_remove(struct device *pdev,
1345 unsigned int ndev)
1346{
1347 aha1542_release(dev_get_drvdata(pdev));
1348 dev_set_drvdata(pdev, NULL);
1349 return 0;
1350}
1351
1352static struct isa_driver aha1542_isa_driver = {
1353 .match = aha1542_isa_match,
1354 .remove = aha1542_isa_remove,
1355 .driver = {
1356 .name = "aha1542"
1357 },
1358};
1359static int isa_registered;
1360
1361#ifdef CONFIG_PNP
1362static struct pnp_device_id aha1542_pnp_ids[] = {
1363 { .id = "ADP1542" },
1364 { .id = "" }
1365};
1366MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1367
1368static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1369{
1370 int indx;
1371 struct Scsi_Host *sh;
1372
1373 for (indx = 0; indx < ARRAY_SIZE(bases); indx++) {
1374 if (bases[indx])
1375 continue;
1376
1377 if (pnp_activate_dev(pdev) < 0)
1378 continue;
1379
1380 bases[indx] = pnp_port_start(pdev, 0);
1381
1382 /* The card can be queried for its DMA, we have
1383 the DMA set up that is enough */
1384
1385 printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]);
1386 }
1387
1388 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1389 if (!sh)
1390 return -ENODEV;
1391
1392 pnp_set_drvdata(pdev, sh);
1393 return 0;
1394}
1395
1396static void aha1542_pnp_remove(struct pnp_dev *pdev)
1397{
1398 aha1542_release(pnp_get_drvdata(pdev));
1399 pnp_set_drvdata(pdev, NULL);
1400}
1401
1402static struct pnp_driver aha1542_pnp_driver = {
1403 .name = "aha1542",
1404 .id_table = aha1542_pnp_ids,
1405 .probe = aha1542_pnp_probe,
1406 .remove = aha1542_pnp_remove,
1407};
1408static int pnp_registered;
1409#endif /* CONFIG_PNP */
1410
1411static int __init aha1542_init(void)
1412{
1413 int ret = 0;
1414#ifdef MODULE
1415 int atbt = -1;
1416
1417 bases[0] = aha1542[0];
1418 setup_buson[0] = aha1542[1];
1419 setup_busoff[0] = aha1542[2];
1420
1421 switch (aha1542[3]) {
1422 case 5:
1423 atbt = 0x00;
1424 break;
1425 case 6:
1426 atbt = 0x04;
1427 break;
1428 case 7:
1429 atbt = 0x01;
1430 break;
1431 case 8:
1432 atbt = 0x02;
1433 break;
1434 case 10:
1435 atbt = 0x03;
1436 break;
1437 };
1438 setup_dmaspeed[0] = atbt;
1439#endif
1440
1441#ifdef CONFIG_PNP
1442 if (isapnp) {
1443 ret = pnp_register_driver(&aha1542_pnp_driver);
1444 if (!ret)
1445 pnp_registered = 1;
1446 }
1447#endif
1448 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1449 if (!ret)
1450 isa_registered = 1;
1451
1452#ifdef CONFIG_PNP
1453 if (pnp_registered)
1454 ret = 0;
1455#endif
1456 if (isa_registered)
1457 ret = 0;
1458
1459 return ret;
1460}
1461
1462static void __exit aha1542_exit(void)
1463{
1464#ifdef CONFIG_PNP
1465 if (pnp_registered)
1466 pnp_unregister_driver(&aha1542_pnp_driver);
1467#endif
1468 if (isa_registered)
1469 isa_unregister_driver(&aha1542_isa_driver);
1470}
1471
1472module_init(aha1542_init);
1473module_exit(aha1542_exit);