blob: ec432763a29a3c3472a53952e017b1d831cd214e [file] [log] [blame]
Ondrej Zary1d084d22015-02-06 23:11:47 +01001/*
2 * Driver for Adaptec AHA-1542 SCSI host adapters
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1992 Tommy Thorn
5 * Copyright (C) 1993, 1994, 1995 Eric Youngdale
Ondrej Zary1d084d22015-02-06 23:11:47 +01006 * Copyright (C) 2015 Ondrej Zary
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/module.h>
10#include <linux/interrupt.h>
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/init.h>
16#include <linux/spinlock.h>
Ondrej Zary643a7c42015-02-06 23:11:22 +010017#include <linux/isa.h>
18#include <linux/pnp.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Ondrej Zary954a9fd2015-02-06 23:11:48 +010020#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <asm/dma.h>
Ondrej Zary954a9fd2015-02-06 23:11:48 +010022#include <scsi/scsi_cmnd.h>
23#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <scsi/scsi_host.h>
25#include "aha1542.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Ondrej Zaryf71429a2015-02-06 23:11:41 +010027#define MAXBOARDS 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Ondrej Zaryf71429a2015-02-06 23:11:41 +010029static bool isapnp = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070030module_param(isapnp, bool, 0);
Ondrej Zaryf71429a2015-02-06 23:11:41 +010031MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
32
33static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
34module_param_array(io, int, NULL, 0);
35MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
36
37/* time AHA spends on the AT-bus during data transfer */
38static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
39module_param_array(bus_on, int, NULL, 0);
40MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
41
42/* time AHA spends off the bus (not to monopolize it) during data transfer */
43static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
44module_param_array(bus_off, int, NULL, 0);
45MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
46
47/* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
48static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
49module_param_array(dma_speed, int, NULL, 0);
50MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#define BIOS_TRANSLATION_6432 1 /* Default case these days */
53#define BIOS_TRANSLATION_25563 2 /* Big disk case */
54
55struct aha1542_hostdata {
56 /* This will effectively start both of them at the first mailbox */
57 int bios_translation; /* Mapping bios uses - for compatibility */
58 int aha1542_last_mbi_used;
59 int aha1542_last_mbo_used;
Ondrej Zary55b28f92015-02-06 23:11:44 +010060 struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 struct mailbox mb[2 * AHA1542_MAILBOXES];
62 struct ccb ccb[AHA1542_MAILBOXES];
63};
64
Ondrej Zaryf1bbef62015-02-06 23:11:26 +010065static inline void aha1542_intr_reset(u16 base)
66{
67 outb(IRST, CONTROL(base));
68}
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Ondrej Zary2093bfa2015-02-06 23:11:31 +010070static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
71{
72 bool delayed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Ondrej Zary2093bfa2015-02-06 23:11:31 +010074 if (timeout == 0) {
75 timeout = 3000000;
76 delayed = false;
77 }
78
79 while (1) {
80 u8 bits = inb(port) & mask;
81 if ((bits & allof) == allof && ((bits & noneof) == 0))
82 break;
83 if (delayed)
84 mdelay(1);
85 if (--timeout == 0)
86 return false;
87 }
88
89 return true;
90}
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Ondrej Zarycad2fc72015-02-06 23:11:43 +010092static int aha1542_outb(unsigned int base, u8 val)
Ondrej Zary0c2b6482015-02-06 23:11:33 +010093{
Ondrej Zaryeef77802015-02-06 23:11:57 +010094 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
95 return 1;
96 outb(val, DATA(base));
97
98 return 0;
Ondrej Zary0c2b6482015-02-06 23:11:33 +010099}
100
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100101static int aha1542_out(unsigned int base, u8 *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100103 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100104 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100105 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100106 outb(*buf++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 }
Ondrej Zary23e69402015-02-06 23:11:39 +0100108 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
109 return 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112}
113
114/* Only used at boot time, so we do not need to worry about latency as much
115 here */
116
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100117static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100120 if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100121 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100122 *buf++ = inb(DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125}
126
127static int makecode(unsigned hosterr, unsigned scsierr)
128{
129 switch (hosterr) {
130 case 0x0:
131 case 0xa: /* Linked command complete without error and linked normally */
132 case 0xb: /* Linked command complete without error, interrupt generated */
133 hosterr = 0;
134 break;
135
136 case 0x11: /* Selection time out-The initiator selection or target
137 reselection was not complete within the SCSI Time out period */
138 hosterr = DID_TIME_OUT;
139 break;
140
141 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
142 than was allocated by the Data Length field or the sum of the
143 Scatter / Gather Data Length fields. */
144
145 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
146
147 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
148 invalid. This usually indicates a software failure. */
149
150 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
151 This usually indicates a software failure. */
152
153 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
154 of linked CCB's does not specify the same logical unit number as
155 the first. */
156 case 0x18: /* Invalid Target Direction received from Host-The direction of a
157 Target Mode CCB was invalid. */
158
159 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
160 received to service data transfer between the same target LUN
161 and initiator SCSI ID in the same direction. */
162
163 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
164 length segment or invalid segment list boundaries was received.
165 A CCB parameter was invalid. */
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100166#ifdef DEBUG
167 printk("Aha1542: %x %x\n", hosterr, scsierr);
168#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 hosterr = DID_ERROR; /* Couldn't find any better */
170 break;
171
172 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
173 phase sequence was requested by the target. The host adapter
174 will generate a SCSI Reset Condition, notifying the host with
175 a SCRD interrupt */
176 hosterr = DID_RESET;
177 break;
178 default:
179 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
180 break;
181 }
182 return scsierr | (hosterr << 16);
183}
184
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100185static int aha1542_test_port(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100187 u8 inquiry_result[4];
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100188 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* Quick and dirty test for presence of the card. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100191 if (inb(STATUS(sh->io_port)) == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 return 0;
193
194 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 /* In case some other card was probing here, reset interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100197 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100199 outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201 mdelay(20); /* Wait a little bit for things to settle down. */
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100204 if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100205 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 /* Shouldn't have generated any interrupts during reset */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100208 if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100209 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 /* Perform a host adapter inquiry instead so we do not need to set
212 up the mailboxes ahead of time */
213
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100214 aha1542_outb(sh->io_port, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100216 for (i = 0; i < 4; i++) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100217 if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100218 return 0;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100219 inquiry_result[i] = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 }
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 /* Reading port should reset DF */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100223 if (inb(STATUS(sh->io_port)) & DF)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100224 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 /* When HACC, command is completed, and we're though testing */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100227 if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100228 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 /* Clear interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100231 outb(IRST, CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Ondrej Zarybdebe222015-02-06 23:11:35 +0100233 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100236static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100238 struct Scsi_Host *sh = dev_id;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100239 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100240 void (*my_done)(struct scsi_cmnd *) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 int errstatus, mbi, mbo, mbistatus;
242 int number_serviced;
243 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100244 struct scsi_cmnd *tmp_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100246 struct mailbox *mb = aha1542->mb;
247 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249#ifdef DEBUG
250 {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100251 flag = inb(INTRFLAGS(sh->io_port));
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100252 shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 if (!(flag & ANYINTR))
254 printk("no interrupt?");
255 if (flag & MBIF)
256 printk("MBIF ");
257 if (flag & MBOA)
258 printk("MBOF ");
259 if (flag & HACC)
260 printk("HACC ");
261 if (flag & SCRD)
262 printk("SCRD ");
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100263 printk("status %02x\n", inb(STATUS(sh->io_port)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 };
265#endif
266 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100268 spin_lock_irqsave(sh->host_lock, flags);
269 while (1) {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100270 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 /* Check for unusual interrupts. If any of these happen, we should
273 probably do something special, but for now just printing a message
274 is sufficient. A SCSI reset detected is something that we really
275 need to deal with in some way. */
276 if (flag & ~MBIF) {
277 if (flag & MBOA)
278 printk("MBOF ");
279 if (flag & HACC)
280 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100281 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100284 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Ondrej Zarye98878f2015-02-06 23:11:25 +0100286 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (mbi >= 2 * AHA1542_MAILBOXES)
288 mbi = AHA1542_MAILBOXES;
289
290 do {
291 if (mb[mbi].status != 0)
292 break;
293 mbi++;
294 if (mbi >= 2 * AHA1542_MAILBOXES)
295 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100296 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
298 if (mb[mbi].status == 0) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100299 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100301 if (!number_serviced)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100302 shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100303 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 };
305
Ondrej Zary10be6252015-02-06 23:11:24 +0100306 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 mbistatus = mb[mbi].status;
308 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100309 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311#ifdef DEBUG
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100312 if (ccb[mbo].tarstat | ccb[mbo].hastat)
313 shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
314 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315#endif
316
317 if (mbistatus == 3)
318 continue; /* Aborted command not found */
319
320#ifdef DEBUG
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100321 shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322#endif
323
Ondrej Zary55b28f92015-02-06 23:11:44 +0100324 tmp_cmd = aha1542->int_cmds[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Ondrej Zary55b28f92015-02-06 23:11:44 +0100326 if (!tmp_cmd || !tmp_cmd->scsi_done) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100327 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100328 shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
329 shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100331 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100333 my_done = tmp_cmd->scsi_done;
334 kfree(tmp_cmd->host_scribble);
335 tmp_cmd->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 /* Fetch the sense data, and tuck it away, in the required slot. The
337 Adaptec automatically fetches it, and there is no guarantee that
338 we will still have it in the cdb when we come back */
339 if (ccb[mbo].tarstat == 2)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100340 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900341 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343
344 /* is there mail :-) */
345
346 /* more error checking left out here */
347 if (mbistatus != 1)
348 /* This is surely wrong, but I don't know what's right */
349 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
350 else
351 errstatus = 0;
352
353#ifdef DEBUG
354 if (errstatus)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100355 shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 ccb[mbo].hastat, ccb[mbo].tarstat);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100357 if (ccb[mbo].tarstat == 2)
358 print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100359 if (errstatus)
360 printk("aha1542_intr_handle: returning %6x\n", errstatus);
361#endif
Ondrej Zary55b28f92015-02-06 23:11:44 +0100362 tmp_cmd->result = errstatus;
363 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
Ondrej Zarye98878f2015-02-06 23:11:25 +0100364 far as queuecommand is concerned */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100365 my_done(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 number_serviced++;
367 };
368}
369
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100370static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
Ondrej Zary09a44832015-02-06 23:11:28 +0100371{
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100372 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100373 u8 direction;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100374 u8 target = cmd->device->id;
375 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100377 int bufflen = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100379 struct mailbox *mb = aha1542->mb;
380 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Ondrej Zary55b28f92015-02-06 23:11:44 +0100382 if (*cmd->cmnd == REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* Don't do the command - we have the sense data already */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100384 cmd->result = 0;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100385 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 return 0;
387 }
388#ifdef DEBUG
Ondrej Zary764a0c72015-02-06 23:11:54 +0100389 {
390 int i = -1;
391 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
392 i = xscsi2int(cmd->cmnd + 2);
393 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
394 i = scsi2int(cmd->cmnd + 2);
395 shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
396 target, *cmd->cmnd, i, bufflen);
397 print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399#endif
400 /* Use the outgoing mailboxes in a round-robin fashion, because this
401 is how the host adapter will scan for them */
402
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100403 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100404 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 if (mbo >= AHA1542_MAILBOXES)
406 mbo = 0;
407
408 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100409 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 break;
411 mbo++;
412 if (mbo >= AHA1542_MAILBOXES)
413 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100414 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Ondrej Zary55b28f92015-02-06 23:11:44 +0100416 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 panic("Unable to find empty mailbox for aha1542.\n");
418
Ondrej Zary55b28f92015-02-06 23:11:44 +0100419 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
Ondrej Zarye98878f2015-02-06 23:11:25 +0100420 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Ondrej Zarye98878f2015-02-06 23:11:25 +0100422 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424#ifdef DEBUG
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100425 shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426#endif
427
Ondrej Zary10be6252015-02-06 23:11:24 +0100428 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430 memset(&ccb[mbo], 0, sizeof(struct ccb));
431
Ondrej Zary55b28f92015-02-06 23:11:44 +0100432 ccb[mbo].cdblen = cmd->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
434 direction = 0;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100435 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 direction = 8;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100437 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 direction = 16;
439
Ondrej Zary55b28f92015-02-06 23:11:44 +0100440 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300442 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200443 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 struct chain *cptr;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100445 int i, sg_count = scsi_sg_count(cmd);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100448 cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300449 GFP_KERNEL | GFP_DMA);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100450 cptr = (struct chain *) cmd->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (cptr == NULL) {
452 /* free the claimed mailbox slot */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100453 aha1542->int_cmds[mbo] = NULL;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100454 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return SCSI_MLQUEUE_HOST_BUSY;
456 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100457 scsi_for_each_sg(cmd, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100458 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
459 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200460 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300462 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100463 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100465 shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
466 print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467#endif
468 } else {
469 ccb[mbo].op = 0; /* SCSI Initiator Command */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100470 cmd->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300471 any2scsi(ccb[mbo].datalen, 0);
472 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 };
474 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
475 ccb[mbo].rsalen = 16;
476 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
477 ccb[mbo].commlinkid = 0;
478
479#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100480 print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100481 printk("aha1542_queuecommand: now waiting for interrupt ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482#endif
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100483 mb[mbo].status = 1;
484 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
485 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
487 return 0;
488}
489
490/* Initialize mailboxes */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100491static void setup_mailboxes(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100493 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100495 struct mailbox *mb = aha1542->mb;
496 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100498 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 for (i = 0; i < AHA1542_MAILBOXES; i++) {
501 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100502 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100504 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100505 any2scsi((mb_cmd + 2), isa_virt_to_bus(mb));
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100506 if (aha1542_out(sh->io_port, mb_cmd, 5))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100507 shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100508 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509}
510
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100511static int aha1542_getconfig(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100513 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100515 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100517 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100519 aha1542_outb(sh->io_port, CMD_RETCONF);
520 aha1542_in(sh->io_port, inquiry_result, 3, 0);
521 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100522 shost_printk(KERN_ERR, sh, "error querying board settings\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100523 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 switch (inquiry_result[0]) {
525 case 0x80:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100526 sh->dma_channel = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 break;
528 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100529 sh->dma_channel = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 break;
531 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100532 sh->dma_channel = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 break;
534 case 0x01:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100535 sh->dma_channel = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 break;
537 case 0:
538 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
539 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100540 sh->dma_channel = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 break;
542 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100543 shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return -1;
545 };
546 switch (inquiry_result[1]) {
547 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100548 sh->irq = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 break;
550 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100551 sh->irq = 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 break;
553 case 0x8:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100554 sh->irq = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 break;
556 case 0x4:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100557 sh->irq = 11;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 break;
559 case 0x2:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100560 sh->irq = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 break;
562 case 0x1:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100563 sh->irq = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 break;
565 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100566 shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 return -1;
568 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100569 sh->this_id = inquiry_result[2] & 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return 0;
571}
572
573/* This function should only be called for 1542C boards - we can detect
574 the special firmware settings and unlock the board */
575
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100576static int aha1542_mbenable(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100578 static u8 mbenable_cmd[3];
579 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 int retval;
581
582 retval = BIOS_TRANSLATION_6432;
583
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100584 aha1542_outb(sh->io_port, CMD_EXTBIOS);
585 if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return retval;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100587 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100588 goto fail;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100589 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
592 mbenable_cmd[0] = CMD_MBENABLE;
593 mbenable_cmd[1] = 0;
594 mbenable_cmd[2] = mbenable_result[1];
595
596 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
597 retval = BIOS_TRANSLATION_25563;
598
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100599 if (aha1542_out(sh->io_port, mbenable_cmd, 3))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100600 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 };
602 while (0) {
603fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100604 shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 }
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100606 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 return retval;
608}
609
610/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100611static int aha1542_query(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100613 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100614 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100616 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100618 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100620 aha1542_outb(sh->io_port, CMD_INQUIRY);
621 aha1542_in(sh->io_port, inquiry_result, 4, 0);
622 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100623 shost_printk(KERN_ERR, sh, "error querying card type\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100624 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100626 aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628 /* For an AHA1740 series board, we ignore the board since there is a
629 hardware bug which can lead to wrong blocks being returned if the board
630 is operating in the 1542 emulation mode. Since there is an extended mode
631 driver, we simply ignore the board and let the 1740 driver pick it up.
632 */
633
634 if (inquiry_result[0] == 0x43) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100635 shost_printk(KERN_INFO, sh, "Emulation mode not supported for AHA-1740 hardware, use aha1740 driver instead.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 return 1;
637 };
638
639 /* Always call this - boards that do not support extended bios translation
640 will ignore the command, and we will set the proper default */
641
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100642 aha1542->bios_translation = aha1542_mbenable(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
644 return 0;
645}
646
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100647static u8 dma_speed_hw(int dma_speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100649 switch (dma_speed) {
650 case 5:
651 return 0x00;
652 case 6:
653 return 0x04;
654 case 7:
655 return 0x01;
656 case 8:
657 return 0x02;
658 case 10:
659 return 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100662 return 0xff; /* invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663}
664
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100665/* Set the Bus on/off-times as not to ruin floppy performance */
Ondrej Zary37d607b2015-02-06 23:11:50 +0100666static void aha1542_set_bus_times(struct Scsi_Host *sh, int bus_on, int bus_off, int dma_speed)
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100667{
Ondrej Zary37d607b2015-02-06 23:11:50 +0100668 if (bus_on > 0) {
669 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100670
Ondrej Zary37d607b2015-02-06 23:11:50 +0100671 aha1542_intr_reset(sh->io_port);
672 if (aha1542_out(sh->io_port, oncmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100673 goto fail;
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100674 }
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100675
Ondrej Zary37d607b2015-02-06 23:11:50 +0100676 if (bus_off > 0) {
677 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100678
Ondrej Zary37d607b2015-02-06 23:11:50 +0100679 aha1542_intr_reset(sh->io_port);
680 if (aha1542_out(sh->io_port, offcmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100681 goto fail;
682 }
683
Ondrej Zary37d607b2015-02-06 23:11:50 +0100684 if (dma_speed_hw(dma_speed) != 0xff) {
685 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100686
Ondrej Zary37d607b2015-02-06 23:11:50 +0100687 aha1542_intr_reset(sh->io_port);
688 if (aha1542_out(sh->io_port, dmacmd, 2))
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100689 goto fail;
690 }
Ondrej Zary37d607b2015-02-06 23:11:50 +0100691 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100692 return;
693fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100694 shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
Ondrej Zary37d607b2015-02-06 23:11:50 +0100695 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100696}
697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100699static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100701 unsigned int base_io = io[indx];
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100702 struct Scsi_Host *sh;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100703 struct aha1542_hostdata *aha1542;
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100704 char dma_info[] = "no DMA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Ondrej Zary3a70c002015-02-06 23:11:40 +0100706 if (base_io == 0)
707 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Ondrej Zary3a70c002015-02-06 23:11:40 +0100709 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
710 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100712 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
713 if (!sh)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100714 goto release;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100715 aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100717 sh->unique_id = base_io;
718 sh->io_port = base_io;
719 sh->n_io_port = AHA1542_REGION_SIZE;
720 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
721 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
722
723 if (!aha1542_test_port(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100724 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Ondrej Zary37d607b2015-02-06 23:11:50 +0100726 aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100727 if (aha1542_query(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100728 goto unregister;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100729 if (aha1542_getconfig(sh) == -1)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100730 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100732 if (sh->dma_channel != 0xFF)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100733 snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
734 shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
735 sh->this_id, base_io, sh->irq, dma_info);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100736 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100737 shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100739 setup_mailboxes(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100741 if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100742 shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100743 goto unregister;
744 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100745 if (sh->dma_channel != 0xFF) {
746 if (request_dma(sh->dma_channel, "aha1542")) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100747 shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100748 goto free_irq;
749 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100750 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
751 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
752 enable_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100753 }
754 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400755
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100756 if (scsi_add_host(sh, pdev))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100757 goto free_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100759 scsi_scan_host(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100761 return sh;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100762free_dma:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100763 if (sh->dma_channel != 0xff)
764 free_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100765free_irq:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100766 free_irq(sh->irq, sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767unregister:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100768 scsi_host_put(sh);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100769release:
770 release_region(base_io, AHA1542_REGION_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Ondrej Zary643a7c42015-02-06 23:11:22 +0100772 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100775static int aha1542_release(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100777 scsi_remove_host(sh);
778 if (sh->dma_channel != 0xff)
779 free_dma(sh->dma_channel);
780 if (sh->irq)
781 free_irq(sh->irq, sh);
782 if (sh->io_port && sh->n_io_port)
783 release_region(sh->io_port, sh->n_io_port);
784 scsi_host_put(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 return 0;
786}
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789/*
790 * This is a device reset. This is handled by sending a special command
791 * to the device.
792 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100793static int aha1542_dev_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100795 struct Scsi_Host *sh = cmd->device->host;
796 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100798 struct mailbox *mb = aha1542->mb;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100799 u8 target = cmd->device->id;
800 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100802 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100804 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100805 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 if (mbo >= AHA1542_MAILBOXES)
807 mbo = 0;
808
809 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100810 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 break;
812 mbo++;
813 if (mbo >= AHA1542_MAILBOXES)
814 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100815 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Ondrej Zary55b28f92015-02-06 23:11:44 +0100817 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 panic("Unable to find empty mailbox for aha1542.\n");
819
Ondrej Zary55b28f92015-02-06 23:11:44 +0100820 aha1542->int_cmds[mbo] = cmd; /* This will effectively
Ondrej Zarye98878f2015-02-06 23:11:25 +0100821 prevent someone else from
822 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Ondrej Zarye98878f2015-02-06 23:11:25 +0100824 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Ondrej Zary10be6252015-02-06 23:11:24 +0100826 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
828 memset(&ccb[mbo], 0, sizeof(struct ccb));
829
830 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
831
832 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
833
834 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
835 ccb[mbo].commlinkid = 0;
836
837 /*
838 * Now tell the 1542 to flush all pending commands for this
839 * target
840 */
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100841 aha1542_outb(sh->io_port, CMD_START_SCSI);
842 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
Ondrej Zary55b28f92015-02-06 23:11:44 +0100844 scmd_printk(KERN_WARNING, cmd,
Jeff Garzik017560f2005-10-24 18:04:36 -0400845 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848}
849
Ondrej Zary55b28f92015-02-06 23:11:44 +0100850static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100852 struct Scsi_Host *sh = cmd->device->host;
853 struct aha1542_hostdata *aha1542 = shost_priv(sh);
854 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 int i;
856
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100857 spin_lock_irqsave(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 /*
859 * This does a scsi reset for all devices on the bus.
860 * In principle, we could also reset the 1542 - should
861 * we do this? Try this first, and we can add that later
862 * if it turns out to be useful.
863 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100864 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Ondrej Zary55b28f92015-02-06 23:11:44 +0100866 if (!wait_mask(STATUS(cmd->device->host->io_port),
Ondrej Zary7061dec2015-02-06 23:11:56 +0100867 STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100868 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zarya13b3722015-02-06 23:11:34 +0100869 return FAILED;
870 }
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100871
Ondrej Zary8537cba2015-02-06 23:11:37 +0100872 /*
873 * We need to do this too before the 1542 can interact with
874 * us again after host reset.
875 */
876 if (reset_cmd & HRST)
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100877 setup_mailboxes(cmd->device->host);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 /*
880 * Now try to pick up the pieces. For all pending commands,
881 * free any internal data structures, and basically clear things
882 * out. We do not try and restart any commands or anything -
883 * the strategy handler takes care of that crap.
884 */
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100885 shost_printk(KERN_WARNING, cmd->device->host, "Sent BUS RESET to scsi host %d\n", cmd->device->host->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100888 if (aha1542->int_cmds[i] != NULL) {
889 struct scsi_cmnd *tmp_cmd;
890 tmp_cmd = aha1542->int_cmds[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Ondrej Zary55b28f92015-02-06 23:11:44 +0100892 if (tmp_cmd->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /*
894 * If this device implements the soft reset option,
895 * then it is still holding onto the command, and
896 * may yet complete it. In this case, we don't
897 * flush the data.
898 */
899 continue;
900 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100901 kfree(tmp_cmd->host_scribble);
902 tmp_cmd->host_scribble = NULL;
903 aha1542->int_cmds[i] = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100904 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 }
906 }
907
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100908 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910}
911
Ondrej Zary55b28f92015-02-06 23:11:44 +0100912static int aha1542_bus_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100914 return aha1542_reset(cmd, SCRST);
Ondrej Zary8537cba2015-02-06 23:11:37 +0100915}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Ondrej Zary55b28f92015-02-06 23:11:44 +0100917static int aha1542_host_reset(struct scsi_cmnd *cmd)
Ondrej Zary8537cba2015-02-06 23:11:37 +0100918{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100919 return aha1542_reset(cmd, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920}
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922static int aha1542_biosparam(struct scsi_device *sdev,
Ondrej Zary17787a02015-02-06 23:11:42 +0100923 struct block_device *bdev, sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100925 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Ondrej Zary17787a02015-02-06 23:11:42 +0100927 if (capacity >= 0x200000 &&
928 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 /* Please verify that this is the same as what DOS returns */
Ondrej Zary17787a02015-02-06 23:11:42 +0100930 geom[0] = 255; /* heads */
931 geom[1] = 63; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 } else {
Ondrej Zary17787a02015-02-06 23:11:42 +0100933 geom[0] = 64; /* heads */
934 geom[1] = 32; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
Ondrej Zary17787a02015-02-06 23:11:42 +0100936 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
938 return 0;
939}
940MODULE_LICENSE("GPL");
941
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100942static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +0100943 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 .proc_name = "aha1542",
945 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 .eh_device_reset_handler= aha1542_dev_reset,
948 .eh_bus_reset_handler = aha1542_bus_reset,
949 .eh_host_reset_handler = aha1542_host_reset,
950 .bios_param = aha1542_biosparam,
951 .can_queue = AHA1542_MAILBOXES,
952 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +0100953 .sg_tablesize = 16,
954 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 .unchecked_isa_dma = 1,
956 .use_clustering = ENABLE_CLUSTERING,
957};
Ondrej Zary643a7c42015-02-06 23:11:22 +0100958
959static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
960{
961 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
962
963 if (!sh)
964 return 0;
965
966 dev_set_drvdata(pdev, sh);
967 return 1;
968}
969
970static int aha1542_isa_remove(struct device *pdev,
971 unsigned int ndev)
972{
973 aha1542_release(dev_get_drvdata(pdev));
974 dev_set_drvdata(pdev, NULL);
975 return 0;
976}
977
978static struct isa_driver aha1542_isa_driver = {
979 .match = aha1542_isa_match,
980 .remove = aha1542_isa_remove,
981 .driver = {
982 .name = "aha1542"
983 },
984};
985static int isa_registered;
986
987#ifdef CONFIG_PNP
988static struct pnp_device_id aha1542_pnp_ids[] = {
989 { .id = "ADP1542" },
990 { .id = "" }
991};
992MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
993
994static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
995{
996 int indx;
997 struct Scsi_Host *sh;
998
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100999 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1000 if (io[indx])
Ondrej Zary643a7c42015-02-06 23:11:22 +01001001 continue;
1002
1003 if (pnp_activate_dev(pdev) < 0)
1004 continue;
1005
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001006 io[indx] = pnp_port_start(pdev, 0);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001007
1008 /* The card can be queried for its DMA, we have
1009 the DMA set up that is enough */
1010
Ondrej Zary2906b3c2015-02-06 23:11:51 +01001011 dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001012 }
1013
1014 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1015 if (!sh)
1016 return -ENODEV;
1017
1018 pnp_set_drvdata(pdev, sh);
1019 return 0;
1020}
1021
1022static void aha1542_pnp_remove(struct pnp_dev *pdev)
1023{
1024 aha1542_release(pnp_get_drvdata(pdev));
1025 pnp_set_drvdata(pdev, NULL);
1026}
1027
1028static struct pnp_driver aha1542_pnp_driver = {
1029 .name = "aha1542",
1030 .id_table = aha1542_pnp_ids,
1031 .probe = aha1542_pnp_probe,
1032 .remove = aha1542_pnp_remove,
1033};
1034static int pnp_registered;
1035#endif /* CONFIG_PNP */
1036
1037static int __init aha1542_init(void)
1038{
1039 int ret = 0;
Ondrej Zary643a7c42015-02-06 23:11:22 +01001040
1041#ifdef CONFIG_PNP
1042 if (isapnp) {
1043 ret = pnp_register_driver(&aha1542_pnp_driver);
1044 if (!ret)
1045 pnp_registered = 1;
1046 }
1047#endif
1048 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1049 if (!ret)
1050 isa_registered = 1;
1051
1052#ifdef CONFIG_PNP
1053 if (pnp_registered)
1054 ret = 0;
1055#endif
1056 if (isa_registered)
1057 ret = 0;
1058
1059 return ret;
1060}
1061
1062static void __exit aha1542_exit(void)
1063{
1064#ifdef CONFIG_PNP
1065 if (pnp_registered)
1066 pnp_unregister_driver(&aha1542_pnp_driver);
1067#endif
1068 if (isa_registered)
1069 isa_unregister_driver(&aha1542_isa_driver);
1070}
1071
1072module_init(aha1542_init);
1073module_exit(aha1542_exit);