blob: af1e8fa414133a500e1040c62c7c51bf9bc6c052 [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
Ondrej Zaryf1bbef62015-02-06 23:11:26 +0100127static inline void aha1542_intr_reset(u16 base)
128{
129 outb(IRST, CONTROL(base));
130}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132#define WAIT(port, mask, allof, noneof) \
133 { register int WAITbits; \
134 register int WAITtimeout = WAITnexttimeout; \
135 while (1) { \
136 WAITbits = inb(port) & (mask); \
137 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
138 break; \
139 if (--WAITtimeout == 0) goto fail; \
140 } \
141 }
142
143/* Similar to WAIT, except we use the udelay call to regulate the
144 amount of time we wait. */
145#define WAITd(port, mask, allof, noneof, timeout) \
146 { register int WAITbits; \
147 register int WAITtimeout = timeout; \
148 while (1) { \
149 WAITbits = inb(port) & (mask); \
150 if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
151 break; \
152 mdelay(1); \
153 if (--WAITtimeout == 0) goto fail; \
154 } \
155 }
156
157static void aha1542_stat(void)
158{
159/* int s = inb(STATUS), i = inb(INTRFLAGS);
160 printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
161}
162
163/* This is a bit complicated, but we need to make sure that an interrupt
164 routine does not send something out while we are in the middle of this.
165 Fortunately, it is only at boot time that multi-byte messages
166 are ever sent. */
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100167static int aha1542_out(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
169 unsigned long flags = 0;
170 int got_lock;
171
172 if (len == 1) {
173 got_lock = 0;
174 while (1 == 1) {
175 WAIT(STATUS(base), CDF, 0, CDF);
176 spin_lock_irqsave(&aha1542_lock, flags);
177 if (inb(STATUS(base)) & CDF) {
178 spin_unlock_irqrestore(&aha1542_lock, flags);
179 continue;
180 }
181 outb(*cmdp, DATA(base));
182 spin_unlock_irqrestore(&aha1542_lock, flags);
183 return 0;
184 }
185 } else {
186 spin_lock_irqsave(&aha1542_lock, flags);
187 got_lock = 1;
188 while (len--) {
189 WAIT(STATUS(base), CDF, 0, CDF);
190 outb(*cmdp++, DATA(base));
191 }
192 spin_unlock_irqrestore(&aha1542_lock, flags);
193 }
194 return 0;
195fail:
196 if (got_lock)
197 spin_unlock_irqrestore(&aha1542_lock, flags);
198 printk(KERN_ERR "aha1542_out failed(%d): ", len + 1);
199 aha1542_stat();
200 return 1;
201}
202
203/* Only used at boot time, so we do not need to worry about latency as much
204 here */
205
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100206static int aha1542_in(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207{
208 unsigned long flags;
209
210 spin_lock_irqsave(&aha1542_lock, flags);
211 while (len--) {
212 WAIT(STATUS(base), DF, DF, 0);
213 *cmdp++ = inb(DATA(base));
214 }
215 spin_unlock_irqrestore(&aha1542_lock, flags);
216 return 0;
217fail:
218 spin_unlock_irqrestore(&aha1542_lock, flags);
219 printk(KERN_ERR "aha1542_in failed(%d): ", len + 1);
220 aha1542_stat();
221 return 1;
222}
223
224/* Similar to aha1542_in, except that we wait a very short period of time.
225 We use this if we know the board is alive and awake, but we are not sure
226 if the board will respond to the command we are about to send or not */
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100227static int aha1542_in1(unsigned int base, u8 *cmdp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228{
229 unsigned long flags;
230
231 spin_lock_irqsave(&aha1542_lock, flags);
232 while (len--) {
233 WAITd(STATUS(base), DF, DF, 0, 100);
234 *cmdp++ = inb(DATA(base));
235 }
236 spin_unlock_irqrestore(&aha1542_lock, flags);
237 return 0;
238fail:
239 spin_unlock_irqrestore(&aha1542_lock, flags);
240 return 1;
241}
242
243static int makecode(unsigned hosterr, unsigned scsierr)
244{
245 switch (hosterr) {
246 case 0x0:
247 case 0xa: /* Linked command complete without error and linked normally */
248 case 0xb: /* Linked command complete without error, interrupt generated */
249 hosterr = 0;
250 break;
251
252 case 0x11: /* Selection time out-The initiator selection or target
253 reselection was not complete within the SCSI Time out period */
254 hosterr = DID_TIME_OUT;
255 break;
256
257 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
258 than was allocated by the Data Length field or the sum of the
259 Scatter / Gather Data Length fields. */
260
261 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
262
263 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
264 invalid. This usually indicates a software failure. */
265
266 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
267 This usually indicates a software failure. */
268
269 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
270 of linked CCB's does not specify the same logical unit number as
271 the first. */
272 case 0x18: /* Invalid Target Direction received from Host-The direction of a
273 Target Mode CCB was invalid. */
274
275 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
276 received to service data transfer between the same target LUN
277 and initiator SCSI ID in the same direction. */
278
279 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
280 length segment or invalid segment list boundaries was received.
281 A CCB parameter was invalid. */
282 DEB(printk("Aha1542: %x %x\n", hosterr, scsierr));
283 hosterr = DID_ERROR; /* Couldn't find any better */
284 break;
285
286 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
287 phase sequence was requested by the target. The host adapter
288 will generate a SCSI Reset Condition, notifying the host with
289 a SCRD interrupt */
290 hosterr = DID_RESET;
291 break;
292 default:
293 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
294 break;
295 }
296 return scsierr | (hosterr << 16);
297}
298
Ondrej Zary643a7c42015-02-06 23:11:22 +0100299static int aha1542_test_port(int bse, struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100301 u8 inquiry_cmd[] = {CMD_INQUIRY};
302 u8 inquiry_result[4];
303 u8 *cmdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 int len;
305 volatile int debug = 0;
306
307 /* Quick and dirty test for presence of the card. */
308 if (inb(STATUS(bse)) == 0xff)
309 return 0;
310
311 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
312
313 /* DEB(printk("aha1542_test_port called \n")); */
314
315 /* In case some other card was probing here, reset interrupts */
316 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
317
318 outb(SRST | IRST /*|SCRST */ , CONTROL(bse));
319
320 mdelay(20); /* Wait a little bit for things to settle down. */
321
322 debug = 1;
323 /* Expect INIT and IDLE, any of the others are bad */
324 WAIT(STATUS(bse), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
325
326 debug = 2;
327 /* Shouldn't have generated any interrupts during reset */
328 if (inb(INTRFLAGS(bse)) & INTRMASK)
329 goto fail;
330
331
332 /* Perform a host adapter inquiry instead so we do not need to set
333 up the mailboxes ahead of time */
334
335 aha1542_out(bse, inquiry_cmd, 1);
336
337 debug = 3;
338 len = 4;
339 cmdp = &inquiry_result[0];
340
341 while (len--) {
342 WAIT(STATUS(bse), DF, DF, 0);
343 *cmdp++ = inb(DATA(bse));
344 }
345
346 debug = 8;
347 /* Reading port should reset DF */
348 if (inb(STATUS(bse)) & DF)
349 goto fail;
350
351 debug = 9;
352 /* When HACC, command is completed, and we're though testing */
353 WAIT(INTRFLAGS(bse), HACC, HACC, 0);
354 /* now initialize adapter */
355
356 debug = 10;
357 /* Clear interrupts */
358 outb(IRST, CONTROL(bse));
359
360 debug = 11;
361
362 return debug; /* 1 = ok */
363fail:
364 return 0; /* 0 = not ok */
365}
366
Ondrej Zary09a44832015-02-06 23:11:28 +0100367static int aha1542_restart(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Ondrej Zary09a44832015-02-06 23:11:28 +0100369 struct aha1542_hostdata *aha1542 = shost_priv(shost);
370 int i;
371 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Ondrej Zary09a44832015-02-06 23:11:28 +0100373 for (i = 0; i < AHA1542_MAILBOXES; i++)
374 if (aha1542->SCint[i] &&
375 !(aha1542->SCint[i]->device->soft_reset)) {
376 count++;
377 }
378 printk(KERN_DEBUG "Potential to restart %d stalled commands...\n", count);
379
380 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
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
Ondrej Zary09a44832015-02-06 23:11:28 +0100542/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
543static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
544{
545 unsigned long flags;
546 struct Scsi_Host *shost = dev_id;
547
548 spin_lock_irqsave(shost->host_lock, flags);
549 aha1542_intr_handle(shost);
550 spin_unlock_irqrestore(shost->host_lock, flags);
551 return IRQ_HANDLED;
552}
553
Jeff Garzikf2812332010-11-16 02:10:29 -0500554static int aha1542_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100556 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100557 u8 ahacmd = CMD_START_SCSI;
558 u8 direction;
559 u8 *cmd = (u8 *) SCpnt->cmnd;
560 u8 target = SCpnt->device->id;
561 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 unsigned long flags;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300563 int bufflen = scsi_bufflen(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100565 struct mailbox *mb = aha1542->mb;
566 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 DEB(int i);
569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 DEB(if (target > 1) {
571 SCpnt->result = DID_TIME_OUT << 16;
572 done(SCpnt); return 0;
573 }
574 );
575
576 if (*cmd == REQUEST_SENSE) {
577 /* Don't do the command - we have the sense data already */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 SCpnt->result = 0;
579 done(SCpnt);
580 return 0;
581 }
582#ifdef DEBUG
583 if (*cmd == READ_10 || *cmd == WRITE_10)
584 i = xscsi2int(cmd + 2);
585 else if (*cmd == READ_6 || *cmd == WRITE_6)
586 i = scsi2int(cmd + 2);
587 else
588 i = -1;
589 if (done)
590 printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
591 else
592 printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
593 aha1542_stat();
594 printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:");
595 for (i = 0; i < SCpnt->cmd_len; i++)
596 printk("%02x ", cmd[i]);
597 printk("\n");
598 if (*cmd == WRITE_10 || *cmd == WRITE_6)
599 return 0; /* we are still testing, so *don't* write */
600#endif
601 /* Use the outgoing mailboxes in a round-robin fashion, because this
602 is how the host adapter will scan for them */
603
604 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100605 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (mbo >= AHA1542_MAILBOXES)
607 mbo = 0;
608
609 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +0100610 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 break;
612 mbo++;
613 if (mbo >= AHA1542_MAILBOXES)
614 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100615 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Ondrej Zarye98878f2015-02-06 23:11:25 +0100617 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 panic("Unable to find empty mailbox for aha1542.\n");
619
Ondrej Zarye98878f2015-02-06 23:11:25 +0100620 aha1542->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from
621 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Ondrej Zarye98878f2015-02-06 23:11:25 +0100623 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 spin_unlock_irqrestore(&aha1542_lock, flags);
625
626#ifdef DEBUG
627 printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
628#endif
629
Ondrej Zary10be6252015-02-06 23:11:24 +0100630 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
632 memset(&ccb[mbo], 0, sizeof(struct ccb));
633
634 ccb[mbo].cdblen = SCpnt->cmd_len;
635
636 direction = 0;
637 if (*cmd == READ_10 || *cmd == READ_6)
638 direction = 8;
639 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
640 direction = 16;
641
642 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
643
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300644 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200645 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 struct chain *cptr;
647#ifdef DEBUG
648 unsigned char *ptr;
649#endif
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300650 int i, sg_count = scsi_sg_count(SCpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300652 SCpnt->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
653 GFP_KERNEL | GFP_DMA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 cptr = (struct chain *) SCpnt->host_scribble;
655 if (cptr == NULL) {
656 /* free the claimed mailbox slot */
Ondrej Zarye98878f2015-02-06 23:11:25 +0100657 aha1542->SCint[mbo] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return SCSI_MLQUEUE_HOST_BUSY;
659 }
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300660 scsi_for_each_sg(SCpnt, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100661 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
662 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200663 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300665 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100666 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667#ifdef DEBUG
668 printk("cptr %x: ", cptr);
669 ptr = (unsigned char *) cptr;
670 for (i = 0; i < 18; i++)
671 printk("%02x ", ptr[i]);
672#endif
673 } else {
674 ccb[mbo].op = 0; /* SCSI Initiator Command */
675 SCpnt->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300676 any2scsi(ccb[mbo].datalen, 0);
677 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 };
679 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
680 ccb[mbo].rsalen = 16;
681 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
682 ccb[mbo].commlinkid = 0;
683
684#ifdef DEBUG
685 {
686 int i;
687 printk(KERN_DEBUG "aha1542_command: sending.. ");
688 for (i = 0; i < sizeof(ccb[mbo]) - 10; i++)
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100689 printk("%02x ", ((u8 *) &ccb[mbo])[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 };
691#endif
692
693 if (done) {
694 DEB(printk("aha1542_queuecommand: now waiting for interrupt ");
695 aha1542_stat());
696 SCpnt->scsi_done = done;
697 mb[mbo].status = 1;
698 aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); /* start scsi command */
699 DEB(aha1542_stat());
700 } else
701 printk("aha1542_queuecommand: done can't be NULL\n");
702
703 return 0;
704}
705
Jeff Garzikf2812332010-11-16 02:10:29 -0500706static DEF_SCSI_QCMD(aha1542_queuecommand)
707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708/* Initialize mailboxes */
709static void setup_mailboxes(int bse, struct Scsi_Host *shpnt)
710{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100711 struct aha1542_hostdata *aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100713 struct mailbox *mb = aha1542->mb;
714 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100716 u8 cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 for (i = 0; i < AHA1542_MAILBOXES; i++) {
719 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100720 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 };
722 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
Ondrej Zary10be6252015-02-06 23:11:24 +0100723 any2scsi((cmd + 2), isa_virt_to_bus(mb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 aha1542_out(bse, cmd, 5);
725 WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0);
726 while (0) {
727fail:
728 printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n");
729 }
730 aha1542_intr_reset(bse);
731}
732
Ondrej Zary643a7c42015-02-06 23:11:22 +0100733static 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 -0700734{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100735 u8 inquiry_cmd[] = {CMD_RETCONF};
736 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 int i;
738 i = inb(STATUS(base_io));
739 if (i & DF) {
740 i = inb(DATA(base_io));
741 };
742 aha1542_out(base_io, inquiry_cmd, 1);
743 aha1542_in(base_io, inquiry_result, 3);
744 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
745 while (0) {
746fail:
747 printk(KERN_ERR "aha1542_detect: query board settings\n");
748 }
749 aha1542_intr_reset(base_io);
750 switch (inquiry_result[0]) {
751 case 0x80:
752 *dma_chan = 7;
753 break;
754 case 0x40:
755 *dma_chan = 6;
756 break;
757 case 0x20:
758 *dma_chan = 5;
759 break;
760 case 0x01:
761 *dma_chan = 0;
762 break;
763 case 0:
764 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
765 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
766 *dma_chan = 0xFF;
767 break;
768 default:
769 printk(KERN_ERR "Unable to determine Adaptec DMA priority. Disabling board\n");
770 return -1;
771 };
772 switch (inquiry_result[1]) {
773 case 0x40:
774 *irq_level = 15;
775 break;
776 case 0x20:
777 *irq_level = 14;
778 break;
779 case 0x8:
780 *irq_level = 12;
781 break;
782 case 0x4:
783 *irq_level = 11;
784 break;
785 case 0x2:
786 *irq_level = 10;
787 break;
788 case 0x1:
789 *irq_level = 9;
790 break;
791 default:
792 printk(KERN_ERR "Unable to determine Adaptec IRQ level. Disabling board\n");
793 return -1;
794 };
795 *scsi_id = inquiry_result[2] & 7;
796 return 0;
797}
798
799/* This function should only be called for 1542C boards - we can detect
800 the special firmware settings and unlock the board */
801
Ondrej Zary643a7c42015-02-06 23:11:22 +0100802static int aha1542_mbenable(int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100804 static u8 mbenable_cmd[3];
805 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 int retval;
807
808 retval = BIOS_TRANSLATION_6432;
809
810 mbenable_cmd[0] = CMD_EXTBIOS;
811 aha1542_out(base, mbenable_cmd, 1);
812 if (aha1542_in1(base, mbenable_result, 2))
813 return retval;
814 WAITd(INTRFLAGS(base), INTRMASK, HACC, 0, 100);
815 aha1542_intr_reset(base);
816
817 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
818 mbenable_cmd[0] = CMD_MBENABLE;
819 mbenable_cmd[1] = 0;
820 mbenable_cmd[2] = mbenable_result[1];
821
822 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
823 retval = BIOS_TRANSLATION_25563;
824
825 aha1542_out(base, mbenable_cmd, 3);
826 WAIT(INTRFLAGS(base), INTRMASK, HACC, 0);
827 };
828 while (0) {
829fail:
830 printk(KERN_ERR "aha1542_mbenable: Mailbox init failed\n");
831 }
832 aha1542_intr_reset(base);
833 return retval;
834}
835
836/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100837static int aha1542_query(int base_io, int *transl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100839 u8 inquiry_cmd[] = {CMD_INQUIRY};
840 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 int i;
842 i = inb(STATUS(base_io));
843 if (i & DF) {
844 i = inb(DATA(base_io));
845 };
846 aha1542_out(base_io, inquiry_cmd, 1);
847 aha1542_in(base_io, inquiry_result, 4);
848 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
849 while (0) {
850fail:
851 printk(KERN_ERR "aha1542_detect: query card type\n");
852 }
853 aha1542_intr_reset(base_io);
854
855 *transl = BIOS_TRANSLATION_6432; /* Default case */
856
857 /* For an AHA1740 series board, we ignore the board since there is a
858 hardware bug which can lead to wrong blocks being returned if the board
859 is operating in the 1542 emulation mode. Since there is an extended mode
860 driver, we simply ignore the board and let the 1740 driver pick it up.
861 */
862
863 if (inquiry_result[0] == 0x43) {
864 printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
865 return 1;
866 };
867
868 /* Always call this - boards that do not support extended bios translation
869 will ignore the command, and we will set the proper default */
870
871 *transl = aha1542_mbenable(base_io);
872
873 return 0;
874}
875
876#ifndef MODULE
877static char *setup_str[MAXBOARDS] __initdata;
878static int setup_idx = 0;
879
880static void __init aha1542_setup(char *str, int *ints)
881{
882 const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
883 int setup_portbase;
884
885 if (setup_idx >= MAXBOARDS) {
886 printk(KERN_ERR "aha1542: aha1542_setup called too many times! Bad LILO params ?\n");
887 printk(KERN_ERR " Entryline 1: %s\n", setup_str[0]);
888 printk(KERN_ERR " Entryline 2: %s\n", setup_str[1]);
889 printk(KERN_ERR " This line: %s\n", str);
890 return;
891 }
892 if (ints[0] < 1 || ints[0] > 4) {
893 printk(KERN_ERR "aha1542: %s\n", str);
894 printk(ahausage);
895 printk(KERN_ERR "aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n");
896 }
897 setup_called[setup_idx] = ints[0];
898 setup_str[setup_idx] = str;
899
900 setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */
901 setup_buson[setup_idx] = ints[0] >= 2 ? ints[2] : 7;
902 setup_busoff[setup_idx] = ints[0] >= 3 ? ints[3] : 5;
903 if (ints[0] >= 4)
904 {
905 int atbt = -1;
906 switch (ints[4]) {
907 case 5:
908 atbt = 0x00;
909 break;
910 case 6:
911 atbt = 0x04;
912 break;
913 case 7:
914 atbt = 0x01;
915 break;
916 case 8:
917 atbt = 0x02;
918 break;
919 case 10:
920 atbt = 0x03;
921 break;
922 default:
923 printk(KERN_ERR "aha1542: %s\n", str);
924 printk(ahausage);
925 printk(KERN_ERR "aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n");
926 break;
927 }
928 setup_dmaspeed[setup_idx] = atbt;
929 }
930 if (setup_portbase != 0)
931 bases[setup_idx] = setup_portbase;
932
933 ++setup_idx;
934}
935
936static int __init do_setup(char *str)
937{
938 int ints[5];
939
940 int count=setup_idx;
941
Tobias Klauser6391a112006-06-08 22:23:48 -0700942 get_options(str, ARRAY_SIZE(ints), ints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 aha1542_setup(str,ints);
944
945 return count<setup_idx;
946}
947
948__setup("aha1542=",do_setup);
949#endif
950
951/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100952static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953{
954 unsigned char dma_chan;
955 unsigned char irq_level;
956 unsigned char scsi_id;
957 unsigned long flags;
958 unsigned int base_io;
959 int trans;
960 struct Scsi_Host *shpnt = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100961 struct aha1542_hostdata *aha1542;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
963 DEB(printk("aha1542_detect: \n"));
964
965 tpnt->proc_name = "aha1542";
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) {
Ondrej Zary643a7c42015-02-06 23:11:22 +0100968 shpnt = scsi_host_alloc(tpnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 sizeof(struct aha1542_hostdata));
970
971 if(shpnt==NULL) {
972 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +0100973 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 }
Ondrej Zarye98878f2015-02-06 23:11:25 +0100975 aha1542 = shost_priv(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 if (!aha1542_test_port(bases[indx], shpnt))
977 goto unregister;
978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 base_io = bases[indx];
980
981 /* Set the Bus on/off-times as not to ruin floppy performance */
982 {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100983 u8 oncmd[] = {CMD_BUSON_TIME, 7};
984 u8 offcmd[] = {CMD_BUSOFF_TIME, 5};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 if (setup_called[indx]) {
987 oncmd[1] = setup_buson[indx];
988 offcmd[1] = setup_busoff[indx];
989 }
990 aha1542_intr_reset(base_io);
991 aha1542_out(base_io, oncmd, 2);
992 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
993 aha1542_intr_reset(base_io);
994 aha1542_out(base_io, offcmd, 2);
995 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
996 if (setup_dmaspeed[indx] >= 0) {
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100997 u8 dmacmd[] = {CMD_DMASPEED, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 dmacmd[1] = setup_dmaspeed[indx];
999 aha1542_intr_reset(base_io);
1000 aha1542_out(base_io, dmacmd, 2);
1001 WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
1002 }
1003 while (0) {
1004fail:
1005 printk(KERN_ERR "aha1542_detect: setting bus on/off-time failed\n");
1006 }
1007 aha1542_intr_reset(base_io);
1008 }
1009 if (aha1542_query(base_io, &trans))
1010 goto unregister;
1011
1012 if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1)
1013 goto unregister;
1014
1015 printk(KERN_INFO "Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level);
1016 if (dma_chan != 0xFF)
1017 printk(", DMA priority %d", dma_chan);
1018 printk("\n");
1019
1020 DEB(aha1542_stat());
1021 setup_mailboxes(base_io, shpnt);
1022
1023 DEB(aha1542_stat());
1024
1025 DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
1026 spin_lock_irqsave(&aha1542_lock, flags);
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001027 if (request_irq(irq_level, do_aha1542_intr_handle, 0,
1028 "aha1542", shpnt)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
1030 spin_unlock_irqrestore(&aha1542_lock, flags);
1031 goto unregister;
1032 }
1033 if (dma_chan != 0xFF) {
1034 if (request_dma(dma_chan, "aha1542")) {
1035 printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001036 free_irq(irq_level, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 spin_unlock_irqrestore(&aha1542_lock, flags);
1038 goto unregister;
1039 }
1040 if (dma_chan == 0 || dma_chan >= 5) {
1041 set_dma_mode(dma_chan, DMA_MODE_CASCADE);
1042 enable_dma(dma_chan);
1043 }
1044 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001045
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 shpnt->this_id = scsi_id;
1047 shpnt->unique_id = base_io;
1048 shpnt->io_port = base_io;
1049 shpnt->n_io_port = 4; /* Number of bytes of I/O space used */
1050 shpnt->dma_channel = dma_chan;
1051 shpnt->irq = irq_level;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001052 aha1542->bios_translation = trans;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 if (trans == BIOS_TRANSLATION_25563)
1054 printk(KERN_INFO "aha1542.c: Using extended bios translation\n");
Ondrej Zarye98878f2015-02-06 23:11:25 +01001055 aha1542->aha1542_last_mbi_used = (2 * AHA1542_MAILBOXES - 1);
1056 aha1542->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
1057 memset(aha1542->SCint, 0, sizeof(aha1542->SCint));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 spin_unlock_irqrestore(&aha1542_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Ondrej Zary643a7c42015-02-06 23:11:22 +01001060 if (scsi_add_host(shpnt, pdev)) {
1061 if (shpnt->dma_channel != 0xff)
1062 free_dma(shpnt->dma_channel);
1063 free_irq(irq_level, shpnt);
1064 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 }
1066
Ondrej Zary643a7c42015-02-06 23:11:22 +01001067 scsi_scan_host(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Ondrej Zary643a7c42015-02-06 23:11:22 +01001069 return shpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070unregister:
1071 release_region(bases[indx], 4);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001072 scsi_host_put(shpnt);
1073 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 };
1076
Ondrej Zary643a7c42015-02-06 23:11:22 +01001077 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078}
1079
1080static int aha1542_release(struct Scsi_Host *shost)
1081{
Ondrej Zary643a7c42015-02-06 23:11:22 +01001082 scsi_remove_host(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 if (shost->irq)
Jeff Garzik87c4d7b2008-04-24 19:45:32 -04001084 free_irq(shost->irq, shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 if (shost->dma_channel != 0xff)
1086 free_dma(shost->dma_channel);
1087 if (shost->io_port && shost->n_io_port)
1088 release_region(shost->io_port, shost->n_io_port);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001089 scsi_host_put(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 return 0;
1091}
1092
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094/*
1095 * This is a device reset. This is handled by sending a special command
1096 * to the device.
1097 */
1098static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
1099{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001100 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001102 struct mailbox *mb = aha1542->mb;
Ondrej Zarycb5b5702015-02-06 23:11:27 +01001103 u8 target = SCpnt->device->id;
1104 u8 lun = SCpnt->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001106 struct ccb *ccb = aha1542->ccb;
Ondrej Zarycb5b5702015-02-06 23:11:27 +01001107 u8 ahacmd = CMD_START_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +01001110 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 if (mbo >= AHA1542_MAILBOXES)
1112 mbo = 0;
1113
1114 do {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001115 if (mb[mbo].status == 0 && aha1542->SCint[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 break;
1117 mbo++;
1118 if (mbo >= AHA1542_MAILBOXES)
1119 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001120 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Ondrej Zarye98878f2015-02-06 23:11:25 +01001122 if (mb[mbo].status || aha1542->SCint[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 panic("Unable to find empty mailbox for aha1542.\n");
1124
Ondrej Zarye98878f2015-02-06 23:11:25 +01001125 aha1542->SCint[mbo] = SCpnt; /* This will effectively
1126 prevent someone else from
1127 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Ondrej Zarye98878f2015-02-06 23:11:25 +01001129 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 spin_unlock_irqrestore(&aha1542_lock, flags);
1131
Ondrej Zary10be6252015-02-06 23:11:24 +01001132 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 memset(&ccb[mbo], 0, sizeof(struct ccb));
1135
1136 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
1137
1138 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
1139
1140 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
1141 ccb[mbo].commlinkid = 0;
1142
1143 /*
1144 * Now tell the 1542 to flush all pending commands for this
1145 * target
1146 */
1147 aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1);
1148
Jeff Garzik017560f2005-10-24 18:04:36 -04001149 scmd_printk(KERN_WARNING, SCpnt,
1150 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153}
1154
1155static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
1156{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001157 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 int i;
1159
1160 /*
1161 * This does a scsi reset for all devices on the bus.
1162 * In principle, we could also reset the 1542 - should
1163 * we do this? Try this first, and we can add that later
1164 * if it turns out to be useful.
1165 */
1166 outb(SCRST, CONTROL(SCpnt->device->host->io_port));
1167
1168 /*
1169 * Wait for the thing to settle down a bit. Unfortunately
1170 * this is going to basically lock up the machine while we
1171 * wait for this to complete. To be 100% correct, we need to
1172 * check for timeout, and if we are doing something like this
1173 * we are pretty desperate anyways.
1174 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 ssleep(4);
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001176
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 spin_lock_irq(SCpnt->device->host->host_lock);
1178
1179 WAIT(STATUS(SCpnt->device->host->io_port),
1180 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
1181
1182 /*
1183 * Now try to pick up the pieces. For all pending commands,
1184 * free any internal data structures, and basically clear things
1185 * out. We do not try and restart any commands or anything -
1186 * the strategy handler takes care of that crap.
1187 */
1188 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
1189
1190 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001191 if (aha1542->SCint[i] != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 Scsi_Cmnd *SCtmp;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001193 SCtmp = aha1542->SCint[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
1195
1196 if (SCtmp->device->soft_reset) {
1197 /*
1198 * If this device implements the soft reset option,
1199 * then it is still holding onto the command, and
1200 * may yet complete it. In this case, we don't
1201 * flush the data.
1202 */
1203 continue;
1204 }
Jesper Juhlc9475cb2005-11-07 01:01:26 -08001205 kfree(SCtmp->host_scribble);
1206 SCtmp->host_scribble = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001207 aha1542->SCint[i] = NULL;
1208 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 }
1210 }
1211
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001212 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 return SUCCESS;
1214
1215fail:
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001216 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 return FAILED;
1218}
1219
1220static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
1221{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001222 struct aha1542_hostdata *aha1542 = shost_priv(SCpnt->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 int i;
1224
1225 /*
1226 * This does a scsi reset for all devices on the bus.
1227 * In principle, we could also reset the 1542 - should
1228 * we do this? Try this first, and we can add that later
1229 * if it turns out to be useful.
1230 */
1231 outb(HRST | SCRST, CONTROL(SCpnt->device->host->io_port));
1232
1233 /*
1234 * Wait for the thing to settle down a bit. Unfortunately
1235 * this is going to basically lock up the machine while we
1236 * wait for this to complete. To be 100% correct, we need to
1237 * check for timeout, and if we are doing something like this
1238 * we are pretty desperate anyways.
1239 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 ssleep(4);
1241 spin_lock_irq(SCpnt->device->host->host_lock);
1242
1243 WAIT(STATUS(SCpnt->device->host->io_port),
1244 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
1245
1246 /*
1247 * We need to do this too before the 1542 can interact with
1248 * us again.
1249 */
1250 setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host);
1251
1252 /*
1253 * Now try to pick up the pieces. For all pending commands,
1254 * free any internal data structures, and basically clear things
1255 * out. We do not try and restart any commands or anything -
1256 * the strategy handler takes care of that crap.
1257 */
1258 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
1259
1260 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zarye98878f2015-02-06 23:11:25 +01001261 if (aha1542->SCint[i] != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 Scsi_Cmnd *SCtmp;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001263 SCtmp = aha1542->SCint[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 if (SCtmp->device->soft_reset) {
1266 /*
1267 * If this device implements the soft reset option,
1268 * then it is still holding onto the command, and
1269 * may yet complete it. In this case, we don't
1270 * flush the data.
1271 */
1272 continue;
1273 }
Jesper Juhlc9475cb2005-11-07 01:01:26 -08001274 kfree(SCtmp->host_scribble);
1275 SCtmp->host_scribble = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001276 aha1542->SCint[i] = NULL;
1277 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
1279 }
1280
Jeff Garzik df0ae242005-05-28 07:57:14 -04001281 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return SUCCESS;
1283
1284fail:
Jeff Garzik df0ae242005-05-28 07:57:14 -04001285 spin_unlock_irq(SCpnt->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 return FAILED;
1287}
1288
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289static int aha1542_biosparam(struct scsi_device *sdev,
1290 struct block_device *bdev, sector_t capacity, int *ip)
1291{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001292 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 int translation_algorithm;
1294 int size = capacity;
1295
Ondrej Zarye98878f2015-02-06 23:11:25 +01001296 translation_algorithm = aha1542->bios_translation;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
1298 if ((size >> 11) > 1024 && translation_algorithm == BIOS_TRANSLATION_25563) {
1299 /* Please verify that this is the same as what DOS returns */
1300 ip[0] = 255;
1301 ip[1] = 63;
1302 ip[2] = size / 255 / 63;
1303 } else {
1304 ip[0] = 64;
1305 ip[1] = 32;
1306 ip[2] = size >> 11;
1307 }
1308
1309 return 0;
1310}
1311MODULE_LICENSE("GPL");
1312
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001313static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001314 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 .proc_name = "aha1542",
1316 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 .eh_device_reset_handler= aha1542_dev_reset,
1319 .eh_bus_reset_handler = aha1542_bus_reset,
1320 .eh_host_reset_handler = aha1542_host_reset,
1321 .bios_param = aha1542_biosparam,
1322 .can_queue = AHA1542_MAILBOXES,
1323 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001324 .sg_tablesize = 16,
1325 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 .unchecked_isa_dma = 1,
1327 .use_clustering = ENABLE_CLUSTERING,
1328};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001329
1330static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1331{
1332 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1333
1334 if (!sh)
1335 return 0;
1336
1337 dev_set_drvdata(pdev, sh);
1338 return 1;
1339}
1340
1341static int aha1542_isa_remove(struct device *pdev,
1342 unsigned int ndev)
1343{
1344 aha1542_release(dev_get_drvdata(pdev));
1345 dev_set_drvdata(pdev, NULL);
1346 return 0;
1347}
1348
1349static struct isa_driver aha1542_isa_driver = {
1350 .match = aha1542_isa_match,
1351 .remove = aha1542_isa_remove,
1352 .driver = {
1353 .name = "aha1542"
1354 },
1355};
1356static int isa_registered;
1357
1358#ifdef CONFIG_PNP
1359static struct pnp_device_id aha1542_pnp_ids[] = {
1360 { .id = "ADP1542" },
1361 { .id = "" }
1362};
1363MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1364
1365static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1366{
1367 int indx;
1368 struct Scsi_Host *sh;
1369
1370 for (indx = 0; indx < ARRAY_SIZE(bases); indx++) {
1371 if (bases[indx])
1372 continue;
1373
1374 if (pnp_activate_dev(pdev) < 0)
1375 continue;
1376
1377 bases[indx] = pnp_port_start(pdev, 0);
1378
1379 /* The card can be queried for its DMA, we have
1380 the DMA set up that is enough */
1381
1382 printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]);
1383 }
1384
1385 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1386 if (!sh)
1387 return -ENODEV;
1388
1389 pnp_set_drvdata(pdev, sh);
1390 return 0;
1391}
1392
1393static void aha1542_pnp_remove(struct pnp_dev *pdev)
1394{
1395 aha1542_release(pnp_get_drvdata(pdev));
1396 pnp_set_drvdata(pdev, NULL);
1397}
1398
1399static struct pnp_driver aha1542_pnp_driver = {
1400 .name = "aha1542",
1401 .id_table = aha1542_pnp_ids,
1402 .probe = aha1542_pnp_probe,
1403 .remove = aha1542_pnp_remove,
1404};
1405static int pnp_registered;
1406#endif /* CONFIG_PNP */
1407
1408static int __init aha1542_init(void)
1409{
1410 int ret = 0;
1411#ifdef MODULE
1412 int atbt = -1;
1413
1414 bases[0] = aha1542[0];
1415 setup_buson[0] = aha1542[1];
1416 setup_busoff[0] = aha1542[2];
1417
1418 switch (aha1542[3]) {
1419 case 5:
1420 atbt = 0x00;
1421 break;
1422 case 6:
1423 atbt = 0x04;
1424 break;
1425 case 7:
1426 atbt = 0x01;
1427 break;
1428 case 8:
1429 atbt = 0x02;
1430 break;
1431 case 10:
1432 atbt = 0x03;
1433 break;
1434 };
1435 setup_dmaspeed[0] = atbt;
1436#endif
1437
1438#ifdef CONFIG_PNP
1439 if (isapnp) {
1440 ret = pnp_register_driver(&aha1542_pnp_driver);
1441 if (!ret)
1442 pnp_registered = 1;
1443 }
1444#endif
1445 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1446 if (!ret)
1447 isa_registered = 1;
1448
1449#ifdef CONFIG_PNP
1450 if (pnp_registered)
1451 ret = 0;
1452#endif
1453 if (isa_registered)
1454 ret = 0;
1455
1456 return ret;
1457}
1458
1459static void __exit aha1542_exit(void)
1460{
1461#ifdef CONFIG_PNP
1462 if (pnp_registered)
1463 pnp_unregister_driver(&aha1542_pnp_driver);
1464#endif
1465 if (isa_registered)
1466 isa_unregister_driver(&aha1542_isa_driver);
1467}
1468
1469module_init(aha1542_init);
1470module_exit(aha1542_exit);