blob: 7b066984ebbf1304eb3d0963c6370d5e7e40b9de [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
Ondrej Zaryf71429a2015-02-06 23:11:41 +010056#define MAXBOARDS 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Ondrej Zaryf71429a2015-02-06 23:11:41 +010058static bool isapnp = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059module_param(isapnp, bool, 0);
Ondrej Zaryf71429a2015-02-06 23:11:41 +010060MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
61
62static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
63module_param_array(io, int, NULL, 0);
64MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
65
66/* time AHA spends on the AT-bus during data transfer */
67static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
68module_param_array(bus_on, int, NULL, 0);
69MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
70
71/* time AHA spends off the bus (not to monopolize it) during data transfer */
72static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
73module_param_array(bus_off, int, NULL, 0);
74MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
75
76/* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
77static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
78module_param_array(dma_speed, int, NULL, 0);
79MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define BIOS_TRANSLATION_6432 1 /* Default case these days */
82#define BIOS_TRANSLATION_25563 2 /* Big disk case */
83
84struct aha1542_hostdata {
85 /* This will effectively start both of them at the first mailbox */
86 int bios_translation; /* Mapping bios uses - for compatibility */
87 int aha1542_last_mbi_used;
88 int aha1542_last_mbo_used;
Ondrej Zary55b28f92015-02-06 23:11:44 +010089 struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 struct mailbox mb[2 * AHA1542_MAILBOXES];
91 struct ccb ccb[AHA1542_MAILBOXES];
92};
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094static DEFINE_SPINLOCK(aha1542_lock);
95
Ondrej Zaryf1bbef62015-02-06 23:11:26 +010096static inline void aha1542_intr_reset(u16 base)
97{
98 outb(IRST, CONTROL(base));
99}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100101static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
102{
103 bool delayed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100105 if (timeout == 0) {
106 timeout = 3000000;
107 delayed = false;
108 }
109
110 while (1) {
111 u8 bits = inb(port) & mask;
112 if ((bits & allof) == allof && ((bits & noneof) == 0))
113 break;
114 if (delayed)
115 mdelay(1);
116 if (--timeout == 0)
117 return false;
118 }
119
120 return true;
121}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123/* This is a bit complicated, but we need to make sure that an interrupt
124 routine does not send something out while we are in the middle of this.
125 Fortunately, it is only at boot time that multi-byte messages
126 are ever sent. */
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100127static int aha1542_outb(unsigned int base, u8 val)
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100128{
129 unsigned long flags;
130
131 while (1) {
132 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) {
133 printk(KERN_ERR "aha1542_outb failed");
134 return 1;
135 }
136 spin_lock_irqsave(&aha1542_lock, flags);
137 if (inb(STATUS(base)) & CDF) {
138 spin_unlock_irqrestore(&aha1542_lock, flags);
139 continue;
140 }
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100141 outb(val, DATA(base));
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100142 spin_unlock_irqrestore(&aha1542_lock, flags);
143 return 0;
144 }
145}
146
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100147static int aha1542_out(unsigned int base, u8 *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100149 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100151 spin_lock_irqsave(&aha1542_lock, flags);
152 while (len--) {
153 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 spin_unlock_irqrestore(&aha1542_lock, flags);
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100155 printk(KERN_ERR "aha1542_out failed(%d): ", len + 1);
156 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 }
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100158 outb(*buf++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 }
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100160 spin_unlock_irqrestore(&aha1542_lock, flags);
Ondrej Zary23e69402015-02-06 23:11:39 +0100161 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
162 return 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
167/* Only used at boot time, so we do not need to worry about latency as much
168 here */
169
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100170static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171{
172 unsigned long flags;
173
174 spin_lock_irqsave(&aha1542_lock, flags);
175 while (len--) {
Ondrej Zarya13b3722015-02-06 23:11:34 +0100176 if (!wait_mask(STATUS(base), DF, DF, 0, timeout)) {
177 spin_unlock_irqrestore(&aha1542_lock, flags);
178 if (timeout == 0)
179 printk(KERN_ERR "aha1542_in failed(%d): ", len + 1);
180 return 1;
181 }
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100182 *buf++ = inb(DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 }
184 spin_unlock_irqrestore(&aha1542_lock, flags);
185 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
188static int makecode(unsigned hosterr, unsigned scsierr)
189{
190 switch (hosterr) {
191 case 0x0:
192 case 0xa: /* Linked command complete without error and linked normally */
193 case 0xb: /* Linked command complete without error, interrupt generated */
194 hosterr = 0;
195 break;
196
197 case 0x11: /* Selection time out-The initiator selection or target
198 reselection was not complete within the SCSI Time out period */
199 hosterr = DID_TIME_OUT;
200 break;
201
202 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
203 than was allocated by the Data Length field or the sum of the
204 Scatter / Gather Data Length fields. */
205
206 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
207
208 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
209 invalid. This usually indicates a software failure. */
210
211 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
212 This usually indicates a software failure. */
213
214 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
215 of linked CCB's does not specify the same logical unit number as
216 the first. */
217 case 0x18: /* Invalid Target Direction received from Host-The direction of a
218 Target Mode CCB was invalid. */
219
220 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
221 received to service data transfer between the same target LUN
222 and initiator SCSI ID in the same direction. */
223
224 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
225 length segment or invalid segment list boundaries was received.
226 A CCB parameter was invalid. */
227 DEB(printk("Aha1542: %x %x\n", hosterr, scsierr));
228 hosterr = DID_ERROR; /* Couldn't find any better */
229 break;
230
231 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
232 phase sequence was requested by the target. The host adapter
233 will generate a SCSI Reset Condition, notifying the host with
234 a SCRD interrupt */
235 hosterr = DID_RESET;
236 break;
237 default:
238 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
239 break;
240 }
241 return scsierr | (hosterr << 16);
242}
243
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100244static int aha1542_test_port(int bse, struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100246 u8 inquiry_result[4];
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100247 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 /* Quick and dirty test for presence of the card. */
250 if (inb(STATUS(bse)) == 0xff)
251 return 0;
252
253 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 /* In case some other card was probing here, reset interrupts */
256 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
257
258 outb(SRST | IRST /*|SCRST */ , CONTROL(bse));
259
260 mdelay(20); /* Wait a little bit for things to settle down. */
261
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100263 if (!wait_mask(STATUS(bse), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100264 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 /* Shouldn't have generated any interrupts during reset */
267 if (inb(INTRFLAGS(bse)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100268 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 /* Perform a host adapter inquiry instead so we do not need to set
271 up the mailboxes ahead of time */
272
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100273 aha1542_outb(bse, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100275 for (i = 0; i < 4; i++) {
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100276 if (!wait_mask(STATUS(bse), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100277 return 0;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100278 inquiry_result[i] = inb(DATA(bse));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 /* Reading port should reset DF */
282 if (inb(STATUS(bse)) & DF)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100283 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 /* When HACC, command is completed, and we're though testing */
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100286 if (!wait_mask(INTRFLAGS(bse), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100287 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 /* Clear interrupts */
290 outb(IRST, CONTROL(bse));
291
Ondrej Zarybdebe222015-02-06 23:11:35 +0100292 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293}
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295/* A "high" level interrupt handler */
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100296static void aha1542_intr_handle(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100298 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100299 void (*my_done)(struct scsi_cmnd *) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 int errstatus, mbi, mbo, mbistatus;
301 int number_serviced;
302 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100303 struct scsi_cmnd *tmp_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100305 struct mailbox *mb = aha1542->mb;
306 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308#ifdef DEBUG
309 {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100310 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 printk(KERN_DEBUG "aha1542_intr_handle: ");
312 if (!(flag & ANYINTR))
313 printk("no interrupt?");
314 if (flag & MBIF)
315 printk("MBIF ");
316 if (flag & MBOA)
317 printk("MBOF ");
318 if (flag & HACC)
319 printk("HACC ");
320 if (flag & SCRD)
321 printk("SCRD ");
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100322 printk("status %02x\n", inb(STATUS(sh->io_port)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 };
324#endif
325 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 while (1 == 1) {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100328 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 /* Check for unusual interrupts. If any of these happen, we should
331 probably do something special, but for now just printing a message
332 is sufficient. A SCSI reset detected is something that we really
333 need to deal with in some way. */
334 if (flag & ~MBIF) {
335 if (flag & MBOA)
336 printk("MBOF ");
337 if (flag & HACC)
338 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100339 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100342 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100345 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 if (mbi >= 2 * AHA1542_MAILBOXES)
347 mbi = AHA1542_MAILBOXES;
348
349 do {
350 if (mb[mbi].status != 0)
351 break;
352 mbi++;
353 if (mbi >= 2 * AHA1542_MAILBOXES)
354 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100355 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 if (mb[mbi].status == 0) {
358 spin_unlock_irqrestore(&aha1542_lock, flags);
359 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100360 if (!number_serviced)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 printk(KERN_WARNING "aha1542.c: interrupt received, but no mail.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 return;
363 };
364
Ondrej Zary10be6252015-02-06 23:11:24 +0100365 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 mbistatus = mb[mbi].status;
367 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100368 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 spin_unlock_irqrestore(&aha1542_lock, flags);
370
371#ifdef DEBUG
372 {
373 if (ccb[mbo].tarstat | ccb[mbo].hastat)
374 printk(KERN_DEBUG "aha1542_command: returning %x (status %d)\n",
375 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
376 };
377#endif
378
379 if (mbistatus == 3)
380 continue; /* Aborted command not found */
381
382#ifdef DEBUG
383 printk(KERN_DEBUG "...done %d %d\n", mbo, mbi);
384#endif
385
Ondrej Zary55b28f92015-02-06 23:11:44 +0100386 tmp_cmd = aha1542->int_cmds[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Ondrej Zary55b28f92015-02-06 23:11:44 +0100388 if (!tmp_cmd || !tmp_cmd->scsi_done) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 printk(KERN_WARNING "aha1542_intr_handle: Unexpected interrupt\n");
390 printk(KERN_WARNING "tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat,
391 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
392 return;
393 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100394 my_done = tmp_cmd->scsi_done;
395 kfree(tmp_cmd->host_scribble);
396 tmp_cmd->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 /* Fetch the sense data, and tuck it away, in the required slot. The
398 Adaptec automatically fetches it, and there is no guarantee that
399 we will still have it in the cdb when we come back */
400 if (ccb[mbo].tarstat == 2)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100401 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900402 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404
405 /* is there mail :-) */
406
407 /* more error checking left out here */
408 if (mbistatus != 1)
409 /* This is surely wrong, but I don't know what's right */
410 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
411 else
412 errstatus = 0;
413
414#ifdef DEBUG
415 if (errstatus)
416 printk(KERN_DEBUG "(aha1542 error:%x %x %x) ", errstatus,
417 ccb[mbo].hastat, ccb[mbo].tarstat);
418#endif
419
420 if (ccb[mbo].tarstat == 2) {
421#ifdef DEBUG
422 int i;
423#endif
424 DEB(printk("aha1542_intr_handle: sense:"));
425#ifdef DEBUG
426 for (i = 0; i < 12; i++)
427 printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen + i]);
428 printk("\n");
429#endif
430 /*
431 DEB(printk("aha1542_intr_handle: buf:"));
432 for (i = 0; i < bufflen; i++)
433 printk("%02x ", ((unchar *)buff)[i]);
434 printk("\n");
435 */
436 }
437 DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
Ondrej Zary55b28f92015-02-06 23:11:44 +0100438 tmp_cmd->result = errstatus;
439 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
Ondrej Zarye98878f2015-02-06 23:11:25 +0100440 far as queuecommand is concerned */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100441 my_done(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 number_serviced++;
443 };
444}
445
Ondrej Zary09a44832015-02-06 23:11:28 +0100446/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
447static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
448{
449 unsigned long flags;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100450 struct Scsi_Host *sh = dev_id;
Ondrej Zary09a44832015-02-06 23:11:28 +0100451
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100452 spin_lock_irqsave(sh->host_lock, flags);
453 aha1542_intr_handle(sh);
454 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zary09a44832015-02-06 23:11:28 +0100455 return IRQ_HANDLED;
456}
457
Ondrej Zary55b28f92015-02-06 23:11:44 +0100458static int aha1542_queuecommand_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100460 struct aha1542_hostdata *aha1542 = shost_priv(cmd->device->host);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100461 u8 direction;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100462 u8 target = cmd->device->id;
463 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100465 int bufflen = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100467 struct mailbox *mb = aha1542->mb;
468 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 DEB(int i);
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 DEB(if (target > 1) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100473 cmd->result = DID_TIME_OUT << 16;
474 done(cmd); return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
476 );
477
Ondrej Zary55b28f92015-02-06 23:11:44 +0100478 if (*cmd->cmnd == REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 /* Don't do the command - we have the sense data already */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100480 cmd->result = 0;
481 done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 return 0;
483 }
484#ifdef DEBUG
Ondrej Zary55b28f92015-02-06 23:11:44 +0100485 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
486 i = xscsi2int(cmd->cmnd + 2);
487 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
488 i = scsi2int(cmd->cmnd + 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 else
490 i = -1;
491 if (done)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100492 printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd->cmnd, i, bufflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 else
Ondrej Zary55b28f92015-02-06 23:11:44 +0100494 printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd->cmnd, i, bufflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:");
Ondrej Zary55b28f92015-02-06 23:11:44 +0100496 for (i = 0; i < cmd->cmd_len; i++)
497 printk("%02x ", cmd->cmnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 printk("\n");
Ondrej Zary55b28f92015-02-06 23:11:44 +0100499 if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 return 0; /* we are still testing, so *don't* write */
501#endif
502 /* Use the outgoing mailboxes in a round-robin fashion, because this
503 is how the host adapter will scan for them */
504
505 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100506 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 if (mbo >= AHA1542_MAILBOXES)
508 mbo = 0;
509
510 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100511 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 break;
513 mbo++;
514 if (mbo >= AHA1542_MAILBOXES)
515 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100516 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Ondrej Zary55b28f92015-02-06 23:11:44 +0100518 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 panic("Unable to find empty mailbox for aha1542.\n");
520
Ondrej Zary55b28f92015-02-06 23:11:44 +0100521 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
Ondrej Zarye98878f2015-02-06 23:11:25 +0100522 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Ondrej Zarye98878f2015-02-06 23:11:25 +0100524 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 spin_unlock_irqrestore(&aha1542_lock, flags);
526
527#ifdef DEBUG
528 printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);
529#endif
530
Ondrej Zary10be6252015-02-06 23:11:24 +0100531 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 memset(&ccb[mbo], 0, sizeof(struct ccb));
534
Ondrej Zary55b28f92015-02-06 23:11:44 +0100535 ccb[mbo].cdblen = cmd->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 direction = 0;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100538 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 direction = 8;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100540 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 direction = 16;
542
Ondrej Zary55b28f92015-02-06 23:11:44 +0100543 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300545 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200546 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 struct chain *cptr;
548#ifdef DEBUG
549 unsigned char *ptr;
550#endif
Ondrej Zary55b28f92015-02-06 23:11:44 +0100551 int i, sg_count = scsi_sg_count(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100553 cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300554 GFP_KERNEL | GFP_DMA);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100555 cptr = (struct chain *) cmd->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 if (cptr == NULL) {
557 /* free the claimed mailbox slot */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100558 aha1542->int_cmds[mbo] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 return SCSI_MLQUEUE_HOST_BUSY;
560 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100561 scsi_for_each_sg(cmd, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100562 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
563 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200564 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300566 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100567 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568#ifdef DEBUG
569 printk("cptr %x: ", cptr);
570 ptr = (unsigned char *) cptr;
571 for (i = 0; i < 18; i++)
572 printk("%02x ", ptr[i]);
573#endif
574 } else {
575 ccb[mbo].op = 0; /* SCSI Initiator Command */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100576 cmd->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300577 any2scsi(ccb[mbo].datalen, 0);
578 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 };
580 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
581 ccb[mbo].rsalen = 16;
582 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
583 ccb[mbo].commlinkid = 0;
584
585#ifdef DEBUG
586 {
587 int i;
588 printk(KERN_DEBUG "aha1542_command: sending.. ");
589 for (i = 0; i < sizeof(ccb[mbo]) - 10; i++)
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100590 printk("%02x ", ((u8 *) &ccb[mbo])[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 };
592#endif
593
594 if (done) {
Ondrej Zaryf232d532015-02-06 23:11:29 +0100595 DEB(printk("aha1542_queuecommand: now waiting for interrupt "));
Ondrej Zary55b28f92015-02-06 23:11:44 +0100596 cmd->scsi_done = done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 mb[mbo].status = 1;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100598 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 } else
600 printk("aha1542_queuecommand: done can't be NULL\n");
601
602 return 0;
603}
604
Jeff Garzikf2812332010-11-16 02:10:29 -0500605static DEF_SCSI_QCMD(aha1542_queuecommand)
606
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607/* Initialize mailboxes */
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100608static void setup_mailboxes(int bse, struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100610 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100612 struct mailbox *mb = aha1542->mb;
613 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100615 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 for (i = 0; i < AHA1542_MAILBOXES; i++) {
618 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100619 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 };
621 aha1542_intr_reset(bse); /* reset interrupts, so they don't block */
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100622 any2scsi((mb_cmd + 2), isa_virt_to_bus(mb));
623 if (aha1542_out(bse, mb_cmd, 5))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 aha1542_intr_reset(bse);
626}
627
Ondrej Zary3a70c002015-02-06 23:11:40 +0100628static int aha1542_getconfig(int base_io, unsigned int *irq_level, unsigned char *dma_chan, unsigned int *scsi_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100630 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 int i;
632 i = inb(STATUS(base_io));
633 if (i & DF) {
634 i = inb(DATA(base_io));
635 };
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100636 aha1542_outb(base_io, CMD_RETCONF);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100637 aha1542_in(base_io, inquiry_result, 3, 0);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100638 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 printk(KERN_ERR "aha1542_detect: query board settings\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 aha1542_intr_reset(base_io);
641 switch (inquiry_result[0]) {
642 case 0x80:
643 *dma_chan = 7;
644 break;
645 case 0x40:
646 *dma_chan = 6;
647 break;
648 case 0x20:
649 *dma_chan = 5;
650 break;
651 case 0x01:
652 *dma_chan = 0;
653 break;
654 case 0:
655 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
656 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
657 *dma_chan = 0xFF;
658 break;
659 default:
660 printk(KERN_ERR "Unable to determine Adaptec DMA priority. Disabling board\n");
661 return -1;
662 };
663 switch (inquiry_result[1]) {
664 case 0x40:
665 *irq_level = 15;
666 break;
667 case 0x20:
668 *irq_level = 14;
669 break;
670 case 0x8:
671 *irq_level = 12;
672 break;
673 case 0x4:
674 *irq_level = 11;
675 break;
676 case 0x2:
677 *irq_level = 10;
678 break;
679 case 0x1:
680 *irq_level = 9;
681 break;
682 default:
683 printk(KERN_ERR "Unable to determine Adaptec IRQ level. Disabling board\n");
684 return -1;
685 };
686 *scsi_id = inquiry_result[2] & 7;
687 return 0;
688}
689
690/* This function should only be called for 1542C boards - we can detect
691 the special firmware settings and unlock the board */
692
Ondrej Zary643a7c42015-02-06 23:11:22 +0100693static int aha1542_mbenable(int base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100695 static u8 mbenable_cmd[3];
696 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 int retval;
698
699 retval = BIOS_TRANSLATION_6432;
700
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100701 aha1542_outb(base, CMD_EXTBIOS);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100702 if (aha1542_in(base, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 return retval;
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100704 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 100))
705 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 aha1542_intr_reset(base);
707
708 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
709 mbenable_cmd[0] = CMD_MBENABLE;
710 mbenable_cmd[1] = 0;
711 mbenable_cmd[2] = mbenable_result[1];
712
713 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
714 retval = BIOS_TRANSLATION_25563;
715
Ondrej Zary23e69402015-02-06 23:11:39 +0100716 if (aha1542_out(base, mbenable_cmd, 3))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100717 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 };
719 while (0) {
720fail:
721 printk(KERN_ERR "aha1542_mbenable: Mailbox init failed\n");
722 }
723 aha1542_intr_reset(base);
724 return retval;
725}
726
727/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100728static int aha1542_query(int base_io, int *transl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100730 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 int i;
732 i = inb(STATUS(base_io));
733 if (i & DF) {
734 i = inb(DATA(base_io));
735 };
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100736 aha1542_outb(base_io, CMD_INQUIRY);
Ondrej Zaryf8846be2015-02-06 23:11:32 +0100737 aha1542_in(base_io, inquiry_result, 4, 0);
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100738 if (!wait_mask(INTRFLAGS(base_io), INTRMASK, HACC, 0, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 printk(KERN_ERR "aha1542_detect: query card type\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 aha1542_intr_reset(base_io);
741
742 *transl = BIOS_TRANSLATION_6432; /* Default case */
743
744 /* For an AHA1740 series board, we ignore the board since there is a
745 hardware bug which can lead to wrong blocks being returned if the board
746 is operating in the 1542 emulation mode. Since there is an extended mode
747 driver, we simply ignore the board and let the 1740 driver pick it up.
748 */
749
750 if (inquiry_result[0] == 0x43) {
751 printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
752 return 1;
753 };
754
755 /* Always call this - boards that do not support extended bios translation
756 will ignore the command, and we will set the proper default */
757
758 *transl = aha1542_mbenable(base_io);
759
760 return 0;
761}
762
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100763static u8 dma_speed_hw(int dma_speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100765 switch (dma_speed) {
766 case 5:
767 return 0x00;
768 case 6:
769 return 0x04;
770 case 7:
771 return 0x01;
772 case 8:
773 return 0x02;
774 case 10:
775 return 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100778 return 0xff; /* invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100781/* Set the Bus on/off-times as not to ruin floppy performance */
782static void aha1542_set_bus_times(int indx)
783{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100784 unsigned int base_io = io[indx];
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100785
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100786 if (bus_on[indx] > 0) {
787 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on[indx], 2, 15) };
788
789 aha1542_intr_reset(base_io);
790 if (aha1542_out(base_io, oncmd, 2))
791 goto fail;
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100792 }
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100793
794 if (bus_off[indx] > 0) {
795 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off[indx], 1, 64) };
796
797 aha1542_intr_reset(base_io);
798 if (aha1542_out(base_io, offcmd, 2))
799 goto fail;
800 }
801
802 if (dma_speed_hw(dma_speed[indx]) != 0xff) {
803 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed[indx]) };
804
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100805 aha1542_intr_reset(base_io);
Ondrej Zary23e69402015-02-06 23:11:39 +0100806 if (aha1542_out(base_io, dmacmd, 2))
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100807 goto fail;
808 }
809 aha1542_intr_reset(base_io);
810 return;
811fail:
812 printk(KERN_ERR "setting bus on/off-time failed\n");
813 aha1542_intr_reset(base_io);
814}
815
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100817static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100819 unsigned int base_io = io[indx];
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100820 struct Scsi_Host *sh;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100821 struct aha1542_hostdata *aha1542;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
Ondrej Zary3a70c002015-02-06 23:11:40 +0100823 if (base_io == 0)
824 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Ondrej Zary3a70c002015-02-06 23:11:40 +0100826 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
827 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100829 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
830 if (!sh)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100831 goto release;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100832 aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100834 if (!aha1542_test_port(base_io, sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100835 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Ondrej Zary3a70c002015-02-06 23:11:40 +0100837 aha1542_set_bus_times(indx);
838 if (aha1542_query(base_io, &aha1542->bios_translation))
839 goto unregister;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100840 if (aha1542_getconfig(base_io, &sh->irq, &sh->dma_channel, &sh->this_id) == -1)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100841 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100843 printk(KERN_INFO "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d", sh->this_id, base_io, sh->irq);
844 if (sh->dma_channel != 0xFF)
845 printk(", DMA %d", sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100846 printk("\n");
847 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
848 printk(KERN_INFO "aha1542.c: Using extended bios translation\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100850 setup_mailboxes(base_io, sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100852 if (request_irq(sh->irq, do_aha1542_intr_handle, 0,
853 "aha1542", sh)) {
Ondrej Zary3a70c002015-02-06 23:11:40 +0100854 printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
855 goto unregister;
856 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100857 if (sh->dma_channel != 0xFF) {
858 if (request_dma(sh->dma_channel, "aha1542")) {
Ondrej Zary3a70c002015-02-06 23:11:40 +0100859 printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
860 goto free_irq;
861 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100862 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
863 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
864 enable_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100865 }
866 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400867
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100868 sh->unique_id = base_io;
869 sh->io_port = base_io;
870 sh->n_io_port = AHA1542_REGION_SIZE;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100871 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
872 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100874 if (scsi_add_host(sh, pdev))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100875 goto free_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100877 scsi_scan_host(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100879 return sh;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100880free_dma:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100881 if (sh->dma_channel != 0xff)
882 free_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100883free_irq:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100884 free_irq(sh->irq, sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885unregister:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100886 scsi_host_put(sh);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100887release:
888 release_region(base_io, AHA1542_REGION_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Ondrej Zary643a7c42015-02-06 23:11:22 +0100890 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891}
892
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100893static int aha1542_release(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100895 scsi_remove_host(sh);
896 if (sh->dma_channel != 0xff)
897 free_dma(sh->dma_channel);
898 if (sh->irq)
899 free_irq(sh->irq, sh);
900 if (sh->io_port && sh->n_io_port)
901 release_region(sh->io_port, sh->n_io_port);
902 scsi_host_put(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return 0;
904}
905
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907/*
908 * This is a device reset. This is handled by sending a special command
909 * to the device.
910 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100911static int aha1542_dev_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100913 struct aha1542_hostdata *aha1542 = shost_priv(cmd->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100915 struct mailbox *mb = aha1542->mb;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100916 u8 target = cmd->device->id;
917 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100919 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 spin_lock_irqsave(&aha1542_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100922 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 if (mbo >= AHA1542_MAILBOXES)
924 mbo = 0;
925
926 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100927 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 break;
929 mbo++;
930 if (mbo >= AHA1542_MAILBOXES)
931 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100932 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Ondrej Zary55b28f92015-02-06 23:11:44 +0100934 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 panic("Unable to find empty mailbox for aha1542.\n");
936
Ondrej Zary55b28f92015-02-06 23:11:44 +0100937 aha1542->int_cmds[mbo] = cmd; /* This will effectively
Ondrej Zarye98878f2015-02-06 23:11:25 +0100938 prevent someone else from
939 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Ondrej Zarye98878f2015-02-06 23:11:25 +0100941 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 spin_unlock_irqrestore(&aha1542_lock, flags);
943
Ondrej Zary10be6252015-02-06 23:11:24 +0100944 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 memset(&ccb[mbo], 0, sizeof(struct ccb));
947
948 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
949
950 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
951
952 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
953 ccb[mbo].commlinkid = 0;
954
955 /*
956 * Now tell the 1542 to flush all pending commands for this
957 * target
958 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100959 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Ondrej Zary55b28f92015-02-06 23:11:44 +0100961 scmd_printk(KERN_WARNING, cmd,
Jeff Garzik017560f2005-10-24 18:04:36 -0400962 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
964 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
Ondrej Zary55b28f92015-02-06 23:11:44 +0100967static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100969 struct aha1542_hostdata *aha1542 = shost_priv(cmd->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 int i;
971
972 /*
973 * This does a scsi reset for all devices on the bus.
974 * In principle, we could also reset the 1542 - should
975 * we do this? Try this first, and we can add that later
976 * if it turns out to be useful.
977 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100978 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 /*
981 * Wait for the thing to settle down a bit. Unfortunately
982 * this is going to basically lock up the machine while we
983 * wait for this to complete. To be 100% correct, we need to
984 * check for timeout, and if we are doing something like this
985 * we are pretty desperate anyways.
986 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 ssleep(4);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100988 spin_lock_irq(cmd->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
Ondrej Zary55b28f92015-02-06 23:11:44 +0100990 if (!wait_mask(STATUS(cmd->device->host->io_port),
Ondrej Zarya13b3722015-02-06 23:11:34 +0100991 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100992 spin_unlock_irq(cmd->device->host->host_lock);
Ondrej Zarya13b3722015-02-06 23:11:34 +0100993 return FAILED;
994 }
Ondrej Zary8537cba2015-02-06 23:11:37 +0100995 /*
996 * We need to do this too before the 1542 can interact with
997 * us again after host reset.
998 */
999 if (reset_cmd & HRST)
Ondrej Zary55b28f92015-02-06 23:11:44 +01001000 setup_mailboxes(cmd->device->host->io_port, cmd->device->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 /*
1002 * Now try to pick up the pieces. For all pending commands,
1003 * free any internal data structures, and basically clear things
1004 * out. We do not try and restart any commands or anything -
1005 * the strategy handler takes care of that crap.
1006 */
Ondrej Zary55b28f92015-02-06 23:11:44 +01001007 printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", cmd->device->host->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
1009 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zary55b28f92015-02-06 23:11:44 +01001010 if (aha1542->int_cmds[i] != NULL) {
1011 struct scsi_cmnd *tmp_cmd;
1012 tmp_cmd = aha1542->int_cmds[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Ondrej Zary55b28f92015-02-06 23:11:44 +01001014 if (tmp_cmd->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 /*
1016 * If this device implements the soft reset option,
1017 * then it is still holding onto the command, and
1018 * may yet complete it. In this case, we don't
1019 * flush the data.
1020 */
1021 continue;
1022 }
Ondrej Zary55b28f92015-02-06 23:11:44 +01001023 kfree(tmp_cmd->host_scribble);
1024 tmp_cmd->host_scribble = NULL;
1025 aha1542->int_cmds[i] = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +01001026 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 }
1028 }
1029
Ondrej Zary55b28f92015-02-06 23:11:44 +01001030 spin_unlock_irq(cmd->device->host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032}
1033
Ondrej Zary55b28f92015-02-06 23:11:44 +01001034static int aha1542_bus_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
Ondrej Zary55b28f92015-02-06 23:11:44 +01001036 return aha1542_reset(cmd, SCRST);
Ondrej Zary8537cba2015-02-06 23:11:37 +01001037}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Ondrej Zary55b28f92015-02-06 23:11:44 +01001039static int aha1542_host_reset(struct scsi_cmnd *cmd)
Ondrej Zary8537cba2015-02-06 23:11:37 +01001040{
Ondrej Zary55b28f92015-02-06 23:11:44 +01001041 return aha1542_reset(cmd, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044static int aha1542_biosparam(struct scsi_device *sdev,
Ondrej Zary17787a02015-02-06 23:11:42 +01001045 struct block_device *bdev, sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
Ondrej Zarye98878f2015-02-06 23:11:25 +01001047 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
Ondrej Zary17787a02015-02-06 23:11:42 +01001049 if (capacity >= 0x200000 &&
1050 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 /* Please verify that this is the same as what DOS returns */
Ondrej Zary17787a02015-02-06 23:11:42 +01001052 geom[0] = 255; /* heads */
1053 geom[1] = 63; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 } else {
Ondrej Zary17787a02015-02-06 23:11:42 +01001055 geom[0] = 64; /* heads */
1056 geom[1] = 32; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
Ondrej Zary17787a02015-02-06 23:11:42 +01001058 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060 return 0;
1061}
1062MODULE_LICENSE("GPL");
1063
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001064static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001065 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 .proc_name = "aha1542",
1067 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 .eh_device_reset_handler= aha1542_dev_reset,
1070 .eh_bus_reset_handler = aha1542_bus_reset,
1071 .eh_host_reset_handler = aha1542_host_reset,
1072 .bios_param = aha1542_biosparam,
1073 .can_queue = AHA1542_MAILBOXES,
1074 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001075 .sg_tablesize = 16,
1076 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 .unchecked_isa_dma = 1,
1078 .use_clustering = ENABLE_CLUSTERING,
1079};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001080
1081static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1082{
1083 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1084
1085 if (!sh)
1086 return 0;
1087
1088 dev_set_drvdata(pdev, sh);
1089 return 1;
1090}
1091
1092static int aha1542_isa_remove(struct device *pdev,
1093 unsigned int ndev)
1094{
1095 aha1542_release(dev_get_drvdata(pdev));
1096 dev_set_drvdata(pdev, NULL);
1097 return 0;
1098}
1099
1100static struct isa_driver aha1542_isa_driver = {
1101 .match = aha1542_isa_match,
1102 .remove = aha1542_isa_remove,
1103 .driver = {
1104 .name = "aha1542"
1105 },
1106};
1107static int isa_registered;
1108
1109#ifdef CONFIG_PNP
1110static struct pnp_device_id aha1542_pnp_ids[] = {
1111 { .id = "ADP1542" },
1112 { .id = "" }
1113};
1114MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1115
1116static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1117{
1118 int indx;
1119 struct Scsi_Host *sh;
1120
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001121 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1122 if (io[indx])
Ondrej Zary643a7c42015-02-06 23:11:22 +01001123 continue;
1124
1125 if (pnp_activate_dev(pdev) < 0)
1126 continue;
1127
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001128 io[indx] = pnp_port_start(pdev, 0);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001129
1130 /* The card can be queried for its DMA, we have
1131 the DMA set up that is enough */
1132
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001133 printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", io[indx]);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001134 }
1135
1136 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1137 if (!sh)
1138 return -ENODEV;
1139
1140 pnp_set_drvdata(pdev, sh);
1141 return 0;
1142}
1143
1144static void aha1542_pnp_remove(struct pnp_dev *pdev)
1145{
1146 aha1542_release(pnp_get_drvdata(pdev));
1147 pnp_set_drvdata(pdev, NULL);
1148}
1149
1150static struct pnp_driver aha1542_pnp_driver = {
1151 .name = "aha1542",
1152 .id_table = aha1542_pnp_ids,
1153 .probe = aha1542_pnp_probe,
1154 .remove = aha1542_pnp_remove,
1155};
1156static int pnp_registered;
1157#endif /* CONFIG_PNP */
1158
1159static int __init aha1542_init(void)
1160{
1161 int ret = 0;
Ondrej Zary643a7c42015-02-06 23:11:22 +01001162
1163#ifdef CONFIG_PNP
1164 if (isapnp) {
1165 ret = pnp_register_driver(&aha1542_pnp_driver);
1166 if (!ret)
1167 pnp_registered = 1;
1168 }
1169#endif
1170 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1171 if (!ret)
1172 isa_registered = 1;
1173
1174#ifdef CONFIG_PNP
1175 if (pnp_registered)
1176 ret = 0;
1177#endif
1178 if (isa_registered)
1179 ret = 0;
1180
1181 return ret;
1182}
1183
1184static void __exit aha1542_exit(void)
1185{
1186#ifdef CONFIG_PNP
1187 if (pnp_registered)
1188 pnp_unregister_driver(&aha1542_pnp_driver);
1189#endif
1190 if (isa_registered)
1191 isa_unregister_driver(&aha1542_isa_driver);
1192}
1193
1194module_init(aha1542_init);
1195module_exit(aha1542_exit);