blob: af821f340a85452d6f5e1c876f49d1b3827bf301 [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 Zary0c2b6482015-02-06 23:11:33 +010094 while (1) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +010095 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
Ondrej Zary0c2b6482015-02-06 23:11:33 +010096 return 1;
Ondrej Zary1b0224b2015-02-06 23:11:55 +010097 if (inb(STATUS(base)) & CDF)
Ondrej Zary0c2b6482015-02-06 23:11:33 +010098 continue;
Ondrej Zarycad2fc72015-02-06 23:11:43 +010099 outb(val, DATA(base));
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100100 return 0;
101 }
102}
103
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100104static int aha1542_out(unsigned int base, u8 *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100106 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100107 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100108 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100109 outb(*buf++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 }
Ondrej Zary23e69402015-02-06 23:11:39 +0100111 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
112 return 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
117/* Only used at boot time, so we do not need to worry about latency as much
118 here */
119
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100120static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100123 if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100124 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100125 *buf++ = inb(DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
130static int makecode(unsigned hosterr, unsigned scsierr)
131{
132 switch (hosterr) {
133 case 0x0:
134 case 0xa: /* Linked command complete without error and linked normally */
135 case 0xb: /* Linked command complete without error, interrupt generated */
136 hosterr = 0;
137 break;
138
139 case 0x11: /* Selection time out-The initiator selection or target
140 reselection was not complete within the SCSI Time out period */
141 hosterr = DID_TIME_OUT;
142 break;
143
144 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
145 than was allocated by the Data Length field or the sum of the
146 Scatter / Gather Data Length fields. */
147
148 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
149
150 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
151 invalid. This usually indicates a software failure. */
152
153 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
154 This usually indicates a software failure. */
155
156 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
157 of linked CCB's does not specify the same logical unit number as
158 the first. */
159 case 0x18: /* Invalid Target Direction received from Host-The direction of a
160 Target Mode CCB was invalid. */
161
162 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
163 received to service data transfer between the same target LUN
164 and initiator SCSI ID in the same direction. */
165
166 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
167 length segment or invalid segment list boundaries was received.
168 A CCB parameter was invalid. */
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100169#ifdef DEBUG
170 printk("Aha1542: %x %x\n", hosterr, scsierr);
171#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 hosterr = DID_ERROR; /* Couldn't find any better */
173 break;
174
175 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
176 phase sequence was requested by the target. The host adapter
177 will generate a SCSI Reset Condition, notifying the host with
178 a SCRD interrupt */
179 hosterr = DID_RESET;
180 break;
181 default:
182 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
183 break;
184 }
185 return scsierr | (hosterr << 16);
186}
187
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100188static int aha1542_test_port(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100190 u8 inquiry_result[4];
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100191 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 /* Quick and dirty test for presence of the card. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100194 if (inb(STATUS(sh->io_port)) == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 return 0;
196
197 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 /* In case some other card was probing here, reset interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100200 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100202 outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204 mdelay(20); /* Wait a little bit for things to settle down. */
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100207 if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100208 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /* Shouldn't have generated any interrupts during reset */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100211 if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100212 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 /* Perform a host adapter inquiry instead so we do not need to set
215 up the mailboxes ahead of time */
216
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100217 aha1542_outb(sh->io_port, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100219 for (i = 0; i < 4; i++) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100220 if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100221 return 0;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100222 inquiry_result[i] = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 }
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 /* Reading port should reset DF */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100226 if (inb(STATUS(sh->io_port)) & DF)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100227 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 /* When HACC, command is completed, and we're though testing */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100230 if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100231 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 /* Clear interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100234 outb(IRST, CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Ondrej Zarybdebe222015-02-06 23:11:35 +0100236 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237}
238
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100239static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100241 struct Scsi_Host *sh = dev_id;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100242 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100243 void (*my_done)(struct scsi_cmnd *) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 int errstatus, mbi, mbo, mbistatus;
245 int number_serviced;
246 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100247 struct scsi_cmnd *tmp_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100249 struct mailbox *mb = aha1542->mb;
250 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252#ifdef DEBUG
253 {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100254 flag = inb(INTRFLAGS(sh->io_port));
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100255 shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 if (!(flag & ANYINTR))
257 printk("no interrupt?");
258 if (flag & MBIF)
259 printk("MBIF ");
260 if (flag & MBOA)
261 printk("MBOF ");
262 if (flag & HACC)
263 printk("HACC ");
264 if (flag & SCRD)
265 printk("SCRD ");
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100266 printk("status %02x\n", inb(STATUS(sh->io_port)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 };
268#endif
269 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100271 spin_lock_irqsave(sh->host_lock, flags);
272 while (1) {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100273 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 /* Check for unusual interrupts. If any of these happen, we should
276 probably do something special, but for now just printing a message
277 is sufficient. A SCSI reset detected is something that we really
278 need to deal with in some way. */
279 if (flag & ~MBIF) {
280 if (flag & MBOA)
281 printk("MBOF ");
282 if (flag & HACC)
283 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100284 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100287 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Ondrej Zarye98878f2015-02-06 23:11:25 +0100289 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 if (mbi >= 2 * AHA1542_MAILBOXES)
291 mbi = AHA1542_MAILBOXES;
292
293 do {
294 if (mb[mbi].status != 0)
295 break;
296 mbi++;
297 if (mbi >= 2 * AHA1542_MAILBOXES)
298 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100299 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 if (mb[mbi].status == 0) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100302 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100304 if (!number_serviced)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100305 shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100306 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 };
308
Ondrej Zary10be6252015-02-06 23:11:24 +0100309 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 mbistatus = mb[mbi].status;
311 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100312 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314#ifdef DEBUG
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100315 if (ccb[mbo].tarstat | ccb[mbo].hastat)
316 shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
317 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318#endif
319
320 if (mbistatus == 3)
321 continue; /* Aborted command not found */
322
323#ifdef DEBUG
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100324 shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325#endif
326
Ondrej Zary55b28f92015-02-06 23:11:44 +0100327 tmp_cmd = aha1542->int_cmds[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328
Ondrej Zary55b28f92015-02-06 23:11:44 +0100329 if (!tmp_cmd || !tmp_cmd->scsi_done) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100330 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100331 shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
332 shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100334 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100336 my_done = tmp_cmd->scsi_done;
337 kfree(tmp_cmd->host_scribble);
338 tmp_cmd->host_scribble = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 /* Fetch the sense data, and tuck it away, in the required slot. The
340 Adaptec automatically fetches it, and there is no guarantee that
341 we will still have it in the cdb when we come back */
342 if (ccb[mbo].tarstat == 2)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100343 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900344 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346
347 /* is there mail :-) */
348
349 /* more error checking left out here */
350 if (mbistatus != 1)
351 /* This is surely wrong, but I don't know what's right */
352 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
353 else
354 errstatus = 0;
355
356#ifdef DEBUG
357 if (errstatus)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100358 shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 ccb[mbo].hastat, ccb[mbo].tarstat);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100360 if (ccb[mbo].tarstat == 2)
361 print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100362 if (errstatus)
363 printk("aha1542_intr_handle: returning %6x\n", errstatus);
364#endif
Ondrej Zary55b28f92015-02-06 23:11:44 +0100365 tmp_cmd->result = errstatus;
366 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
Ondrej Zarye98878f2015-02-06 23:11:25 +0100367 far as queuecommand is concerned */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100368 my_done(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 number_serviced++;
370 };
371}
372
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100373static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
Ondrej Zary09a44832015-02-06 23:11:28 +0100374{
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100375 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100376 u8 direction;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100377 u8 target = cmd->device->id;
378 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100380 int bufflen = scsi_bufflen(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100382 struct mailbox *mb = aha1542->mb;
383 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Ondrej Zary55b28f92015-02-06 23:11:44 +0100385 if (*cmd->cmnd == REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 /* Don't do the command - we have the sense data already */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100387 cmd->result = 0;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100388 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 return 0;
390 }
391#ifdef DEBUG
Ondrej Zary764a0c72015-02-06 23:11:54 +0100392 {
393 int i = -1;
394 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
395 i = xscsi2int(cmd->cmnd + 2);
396 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
397 i = scsi2int(cmd->cmnd + 2);
398 shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
399 target, *cmd->cmnd, i, bufflen);
400 print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402#endif
403 /* Use the outgoing mailboxes in a round-robin fashion, because this
404 is how the host adapter will scan for them */
405
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100406 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100407 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 if (mbo >= AHA1542_MAILBOXES)
409 mbo = 0;
410
411 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100412 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 break;
414 mbo++;
415 if (mbo >= AHA1542_MAILBOXES)
416 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100417 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Ondrej Zary55b28f92015-02-06 23:11:44 +0100419 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 panic("Unable to find empty mailbox for aha1542.\n");
421
Ondrej Zary55b28f92015-02-06 23:11:44 +0100422 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
Ondrej Zarye98878f2015-02-06 23:11:25 +0100423 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Ondrej Zarye98878f2015-02-06 23:11:25 +0100425 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427#ifdef DEBUG
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100428 shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429#endif
430
Ondrej Zary10be6252015-02-06 23:11:24 +0100431 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
433 memset(&ccb[mbo], 0, sizeof(struct ccb));
434
Ondrej Zary55b28f92015-02-06 23:11:44 +0100435 ccb[mbo].cdblen = cmd->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 direction = 0;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100438 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 direction = 8;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100440 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 direction = 16;
442
Ondrej Zary55b28f92015-02-06 23:11:44 +0100443 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300445 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200446 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 struct chain *cptr;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100448 int i, sg_count = scsi_sg_count(cmd);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100451 cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300452 GFP_KERNEL | GFP_DMA);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100453 cptr = (struct chain *) cmd->host_scribble;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 if (cptr == NULL) {
455 /* free the claimed mailbox slot */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100456 aha1542->int_cmds[mbo] = NULL;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100457 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 return SCSI_MLQUEUE_HOST_BUSY;
459 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100460 scsi_for_each_sg(cmd, sg, sg_count, i) {
Ondrej Zary10be6252015-02-06 23:11:24 +0100461 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
462 + sg->offset);
Jens Axboe51cf2242007-07-16 10:00:31 +0200463 any2scsi(cptr[i].datalen, sg->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300465 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Ondrej Zary10be6252015-02-06 23:11:24 +0100466 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100468 shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
469 print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470#endif
471 } else {
472 ccb[mbo].op = 0; /* SCSI Initiator Command */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100473 cmd->host_scribble = NULL;
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300474 any2scsi(ccb[mbo].datalen, 0);
475 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 };
477 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
478 ccb[mbo].rsalen = 16;
479 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
480 ccb[mbo].commlinkid = 0;
481
482#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100483 print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100484 printk("aha1542_queuecommand: now waiting for interrupt ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485#endif
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100486 mb[mbo].status = 1;
487 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
488 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
490 return 0;
491}
492
493/* Initialize mailboxes */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100494static void setup_mailboxes(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100496 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 int i;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100498 struct mailbox *mb = aha1542->mb;
499 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100501 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 for (i = 0; i < AHA1542_MAILBOXES; i++) {
504 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
Ondrej Zary10be6252015-02-06 23:11:24 +0100505 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100507 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100508 any2scsi((mb_cmd + 2), isa_virt_to_bus(mb));
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100509 if (aha1542_out(sh->io_port, mb_cmd, 5))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100510 shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100511 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512}
513
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100514static int aha1542_getconfig(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100516 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100518 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100520 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100522 aha1542_outb(sh->io_port, CMD_RETCONF);
523 aha1542_in(sh->io_port, inquiry_result, 3, 0);
524 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100525 shost_printk(KERN_ERR, sh, "error querying board settings\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100526 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 switch (inquiry_result[0]) {
528 case 0x80:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100529 sh->dma_channel = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 break;
531 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100532 sh->dma_channel = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 break;
534 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100535 sh->dma_channel = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 break;
537 case 0x01:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100538 sh->dma_channel = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 break;
540 case 0:
541 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
542 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100543 sh->dma_channel = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 break;
545 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100546 shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 return -1;
548 };
549 switch (inquiry_result[1]) {
550 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100551 sh->irq = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 break;
553 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100554 sh->irq = 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 break;
556 case 0x8:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100557 sh->irq = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 break;
559 case 0x4:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100560 sh->irq = 11;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 break;
562 case 0x2:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100563 sh->irq = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 break;
565 case 0x1:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100566 sh->irq = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 break;
568 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100569 shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return -1;
571 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100572 sh->this_id = inquiry_result[2] & 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 return 0;
574}
575
576/* This function should only be called for 1542C boards - we can detect
577 the special firmware settings and unlock the board */
578
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100579static int aha1542_mbenable(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100581 static u8 mbenable_cmd[3];
582 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 int retval;
584
585 retval = BIOS_TRANSLATION_6432;
586
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100587 aha1542_outb(sh->io_port, CMD_EXTBIOS);
588 if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 return retval;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100590 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100591 goto fail;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100592 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
594 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
595 mbenable_cmd[0] = CMD_MBENABLE;
596 mbenable_cmd[1] = 0;
597 mbenable_cmd[2] = mbenable_result[1];
598
599 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
600 retval = BIOS_TRANSLATION_25563;
601
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100602 if (aha1542_out(sh->io_port, mbenable_cmd, 3))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100603 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 };
605 while (0) {
606fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100607 shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 }
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100609 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 return retval;
611}
612
613/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100614static int aha1542_query(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615{
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100616 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100617 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100619 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100621 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100623 aha1542_outb(sh->io_port, CMD_INQUIRY);
624 aha1542_in(sh->io_port, inquiry_result, 4, 0);
625 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100626 shost_printk(KERN_ERR, sh, "error querying card type\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100627 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100629 aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 /* For an AHA1740 series board, we ignore the board since there is a
632 hardware bug which can lead to wrong blocks being returned if the board
633 is operating in the 1542 emulation mode. Since there is an extended mode
634 driver, we simply ignore the board and let the 1740 driver pick it up.
635 */
636
637 if (inquiry_result[0] == 0x43) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100638 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 -0700639 return 1;
640 };
641
642 /* Always call this - boards that do not support extended bios translation
643 will ignore the command, and we will set the proper default */
644
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100645 aha1542->bios_translation = aha1542_mbenable(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
647 return 0;
648}
649
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100650static u8 dma_speed_hw(int dma_speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100652 switch (dma_speed) {
653 case 5:
654 return 0x00;
655 case 6:
656 return 0x04;
657 case 7:
658 return 0x01;
659 case 8:
660 return 0x02;
661 case 10:
662 return 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100665 return 0xff; /* invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}
667
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100668/* Set the Bus on/off-times as not to ruin floppy performance */
Ondrej Zary37d607b2015-02-06 23:11:50 +0100669static 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 +0100670{
Ondrej Zary37d607b2015-02-06 23:11:50 +0100671 if (bus_on > 0) {
672 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100673
Ondrej Zary37d607b2015-02-06 23:11:50 +0100674 aha1542_intr_reset(sh->io_port);
675 if (aha1542_out(sh->io_port, oncmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100676 goto fail;
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100677 }
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100678
Ondrej Zary37d607b2015-02-06 23:11:50 +0100679 if (bus_off > 0) {
680 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100681
Ondrej Zary37d607b2015-02-06 23:11:50 +0100682 aha1542_intr_reset(sh->io_port);
683 if (aha1542_out(sh->io_port, offcmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100684 goto fail;
685 }
686
Ondrej Zary37d607b2015-02-06 23:11:50 +0100687 if (dma_speed_hw(dma_speed) != 0xff) {
688 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100689
Ondrej Zary37d607b2015-02-06 23:11:50 +0100690 aha1542_intr_reset(sh->io_port);
691 if (aha1542_out(sh->io_port, dmacmd, 2))
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100692 goto fail;
693 }
Ondrej Zary37d607b2015-02-06 23:11:50 +0100694 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100695 return;
696fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100697 shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
Ondrej Zary37d607b2015-02-06 23:11:50 +0100698 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100699}
700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100702static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100704 unsigned int base_io = io[indx];
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100705 struct Scsi_Host *sh;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100706 struct aha1542_hostdata *aha1542;
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100707 char dma_info[] = "no DMA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Ondrej Zary3a70c002015-02-06 23:11:40 +0100709 if (base_io == 0)
710 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Ondrej Zary3a70c002015-02-06 23:11:40 +0100712 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
713 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100715 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
716 if (!sh)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100717 goto release;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100718 aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100720 sh->unique_id = base_io;
721 sh->io_port = base_io;
722 sh->n_io_port = AHA1542_REGION_SIZE;
723 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
724 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
725
726 if (!aha1542_test_port(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100727 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
Ondrej Zary37d607b2015-02-06 23:11:50 +0100729 aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100730 if (aha1542_query(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100731 goto unregister;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100732 if (aha1542_getconfig(sh) == -1)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100733 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100735 if (sh->dma_channel != 0xFF)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100736 snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
737 shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
738 sh->this_id, base_io, sh->irq, dma_info);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100739 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100740 shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100742 setup_mailboxes(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100744 if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100745 shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100746 goto unregister;
747 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100748 if (sh->dma_channel != 0xFF) {
749 if (request_dma(sh->dma_channel, "aha1542")) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100750 shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100751 goto free_irq;
752 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100753 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
754 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
755 enable_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100756 }
757 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400758
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100759 if (scsi_add_host(sh, pdev))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100760 goto free_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100762 scsi_scan_host(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100764 return sh;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100765free_dma:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100766 if (sh->dma_channel != 0xff)
767 free_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100768free_irq:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100769 free_irq(sh->irq, sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770unregister:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100771 scsi_host_put(sh);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100772release:
773 release_region(base_io, AHA1542_REGION_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ondrej Zary643a7c42015-02-06 23:11:22 +0100775 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776}
777
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100778static int aha1542_release(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100780 scsi_remove_host(sh);
781 if (sh->dma_channel != 0xff)
782 free_dma(sh->dma_channel);
783 if (sh->irq)
784 free_irq(sh->irq, sh);
785 if (sh->io_port && sh->n_io_port)
786 release_region(sh->io_port, sh->n_io_port);
787 scsi_host_put(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 return 0;
789}
790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792/*
793 * This is a device reset. This is handled by sending a special command
794 * to the device.
795 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100796static int aha1542_dev_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100798 struct Scsi_Host *sh = cmd->device->host;
799 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100801 struct mailbox *mb = aha1542->mb;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100802 u8 target = cmd->device->id;
803 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100805 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100807 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100808 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (mbo >= AHA1542_MAILBOXES)
810 mbo = 0;
811
812 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100813 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 break;
815 mbo++;
816 if (mbo >= AHA1542_MAILBOXES)
817 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100818 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Ondrej Zary55b28f92015-02-06 23:11:44 +0100820 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 panic("Unable to find empty mailbox for aha1542.\n");
822
Ondrej Zary55b28f92015-02-06 23:11:44 +0100823 aha1542->int_cmds[mbo] = cmd; /* This will effectively
Ondrej Zarye98878f2015-02-06 23:11:25 +0100824 prevent someone else from
825 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
Ondrej Zarye98878f2015-02-06 23:11:25 +0100827 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Ondrej Zary10be6252015-02-06 23:11:24 +0100829 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
831 memset(&ccb[mbo], 0, sizeof(struct ccb));
832
833 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
834
835 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
836
837 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
838 ccb[mbo].commlinkid = 0;
839
840 /*
841 * Now tell the 1542 to flush all pending commands for this
842 * target
843 */
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100844 aha1542_outb(sh->io_port, CMD_START_SCSI);
845 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Ondrej Zary55b28f92015-02-06 23:11:44 +0100847 scmd_printk(KERN_WARNING, cmd,
Jeff Garzik017560f2005-10-24 18:04:36 -0400848 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
850 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
852
Ondrej Zary55b28f92015-02-06 23:11:44 +0100853static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100855 struct Scsi_Host *sh = cmd->device->host;
856 struct aha1542_hostdata *aha1542 = shost_priv(sh);
857 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 int i;
859
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100860 spin_lock_irqsave(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /*
862 * This does a scsi reset for all devices on the bus.
863 * In principle, we could also reset the 1542 - should
864 * we do this? Try this first, and we can add that later
865 * if it turns out to be useful.
866 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100867 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Ondrej Zary55b28f92015-02-06 23:11:44 +0100869 if (!wait_mask(STATUS(cmd->device->host->io_port),
Ondrej Zary7061dec2015-02-06 23:11:56 +0100870 STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100871 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zarya13b3722015-02-06 23:11:34 +0100872 return FAILED;
873 }
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100874
Ondrej Zary8537cba2015-02-06 23:11:37 +0100875 /*
876 * We need to do this too before the 1542 can interact with
877 * us again after host reset.
878 */
879 if (reset_cmd & HRST)
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100880 setup_mailboxes(cmd->device->host);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /*
883 * Now try to pick up the pieces. For all pending commands,
884 * free any internal data structures, and basically clear things
885 * out. We do not try and restart any commands or anything -
886 * the strategy handler takes care of that crap.
887 */
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100888 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 -0700889
890 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100891 if (aha1542->int_cmds[i] != NULL) {
892 struct scsi_cmnd *tmp_cmd;
893 tmp_cmd = aha1542->int_cmds[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
Ondrej Zary55b28f92015-02-06 23:11:44 +0100895 if (tmp_cmd->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 /*
897 * If this device implements the soft reset option,
898 * then it is still holding onto the command, and
899 * may yet complete it. In this case, we don't
900 * flush the data.
901 */
902 continue;
903 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100904 kfree(tmp_cmd->host_scribble);
905 tmp_cmd->host_scribble = NULL;
906 aha1542->int_cmds[i] = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100907 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909 }
910
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100911 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913}
914
Ondrej Zary55b28f92015-02-06 23:11:44 +0100915static int aha1542_bus_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100917 return aha1542_reset(cmd, SCRST);
Ondrej Zary8537cba2015-02-06 23:11:37 +0100918}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Ondrej Zary55b28f92015-02-06 23:11:44 +0100920static int aha1542_host_reset(struct scsi_cmnd *cmd)
Ondrej Zary8537cba2015-02-06 23:11:37 +0100921{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100922 return aha1542_reset(cmd, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923}
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925static int aha1542_biosparam(struct scsi_device *sdev,
Ondrej Zary17787a02015-02-06 23:11:42 +0100926 struct block_device *bdev, sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100928 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Ondrej Zary17787a02015-02-06 23:11:42 +0100930 if (capacity >= 0x200000 &&
931 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 /* Please verify that this is the same as what DOS returns */
Ondrej Zary17787a02015-02-06 23:11:42 +0100933 geom[0] = 255; /* heads */
934 geom[1] = 63; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 } else {
Ondrej Zary17787a02015-02-06 23:11:42 +0100936 geom[0] = 64; /* heads */
937 geom[1] = 32; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
Ondrej Zary17787a02015-02-06 23:11:42 +0100939 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
941 return 0;
942}
943MODULE_LICENSE("GPL");
944
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100945static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +0100946 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 .proc_name = "aha1542",
948 .name = "Adaptec 1542",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 .eh_device_reset_handler= aha1542_dev_reset,
951 .eh_bus_reset_handler = aha1542_bus_reset,
952 .eh_host_reset_handler = aha1542_host_reset,
953 .bios_param = aha1542_biosparam,
954 .can_queue = AHA1542_MAILBOXES,
955 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +0100956 .sg_tablesize = 16,
957 .cmd_per_lun = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 .unchecked_isa_dma = 1,
959 .use_clustering = ENABLE_CLUSTERING,
960};
Ondrej Zary643a7c42015-02-06 23:11:22 +0100961
962static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
963{
964 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
965
966 if (!sh)
967 return 0;
968
969 dev_set_drvdata(pdev, sh);
970 return 1;
971}
972
973static int aha1542_isa_remove(struct device *pdev,
974 unsigned int ndev)
975{
976 aha1542_release(dev_get_drvdata(pdev));
977 dev_set_drvdata(pdev, NULL);
978 return 0;
979}
980
981static struct isa_driver aha1542_isa_driver = {
982 .match = aha1542_isa_match,
983 .remove = aha1542_isa_remove,
984 .driver = {
985 .name = "aha1542"
986 },
987};
988static int isa_registered;
989
990#ifdef CONFIG_PNP
991static struct pnp_device_id aha1542_pnp_ids[] = {
992 { .id = "ADP1542" },
993 { .id = "" }
994};
995MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
996
997static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
998{
999 int indx;
1000 struct Scsi_Host *sh;
1001
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001002 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1003 if (io[indx])
Ondrej Zary643a7c42015-02-06 23:11:22 +01001004 continue;
1005
1006 if (pnp_activate_dev(pdev) < 0)
1007 continue;
1008
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001009 io[indx] = pnp_port_start(pdev, 0);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001010
1011 /* The card can be queried for its DMA, we have
1012 the DMA set up that is enough */
1013
Ondrej Zary2906b3c2015-02-06 23:11:51 +01001014 dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001015 }
1016
1017 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1018 if (!sh)
1019 return -ENODEV;
1020
1021 pnp_set_drvdata(pdev, sh);
1022 return 0;
1023}
1024
1025static void aha1542_pnp_remove(struct pnp_dev *pdev)
1026{
1027 aha1542_release(pnp_get_drvdata(pdev));
1028 pnp_set_drvdata(pdev, NULL);
1029}
1030
1031static struct pnp_driver aha1542_pnp_driver = {
1032 .name = "aha1542",
1033 .id_table = aha1542_pnp_ids,
1034 .probe = aha1542_pnp_probe,
1035 .remove = aha1542_pnp_remove,
1036};
1037static int pnp_registered;
1038#endif /* CONFIG_PNP */
1039
1040static int __init aha1542_init(void)
1041{
1042 int ret = 0;
Ondrej Zary643a7c42015-02-06 23:11:22 +01001043
1044#ifdef CONFIG_PNP
1045 if (isapnp) {
1046 ret = pnp_register_driver(&aha1542_pnp_driver);
1047 if (!ret)
1048 pnp_registered = 1;
1049 }
1050#endif
1051 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1052 if (!ret)
1053 isa_registered = 1;
1054
1055#ifdef CONFIG_PNP
1056 if (pnp_registered)
1057 ret = 0;
1058#endif
1059 if (isa_registered)
1060 ret = 0;
1061
1062 return ret;
1063}
1064
1065static void __exit aha1542_exit(void)
1066{
1067#ifdef CONFIG_PNP
1068 if (pnp_registered)
1069 pnp_unregister_driver(&aha1542_pnp_driver);
1070#endif
1071 if (isa_registered)
1072 isa_unregister_driver(&aha1542_isa_driver);
1073}
1074
1075module_init(aha1542_init);
1076module_exit(aha1542_exit);