blob: dc5667afeb271677184af001a88aabfe593b8cb5 [file] [log] [blame]
Thomas Gleixner09c434b2019-05-19 13:08:20 +01001// SPDX-License-Identifier: GPL-2.0-only
Ondrej Zary1d084d22015-02-06 23:11:47 +01002/*
3 * Driver for Adaptec AHA-1542 SCSI host adapters
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * Copyright (C) 1992 Tommy Thorn
6 * Copyright (C) 1993, 1994, 1995 Eric Youngdale
Ondrej Zary1d084d22015-02-06 23:11:47 +01007 * Copyright (C) 2015 Ondrej Zary
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/module.h>
11#include <linux/interrupt.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/init.h>
17#include <linux/spinlock.h>
Ondrej Zary643a7c42015-02-06 23:11:22 +010018#include <linux/isa.h>
19#include <linux/pnp.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Ondrej Zary954a9fd2015-02-06 23:11:48 +010021#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <asm/dma.h>
Ondrej Zary954a9fd2015-02-06 23:11:48 +010023#include <scsi/scsi_cmnd.h>
24#include <scsi/scsi_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <scsi/scsi_host.h>
26#include "aha1542.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Ondrej Zaryf71429a2015-02-06 23:11:41 +010028#define MAXBOARDS 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Ondrej Zaryf71429a2015-02-06 23:11:41 +010030static bool isapnp = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070031module_param(isapnp, bool, 0);
Ondrej Zaryf71429a2015-02-06 23:11:41 +010032MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
33
34static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
David Howells88f06b72017-04-04 16:54:27 +010035module_param_hw_array(io, int, ioport, NULL, 0);
Ondrej Zaryf71429a2015-02-06 23:11:41 +010036MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
37
38/* time AHA spends on the AT-bus during data transfer */
39static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
40module_param_array(bus_on, int, NULL, 0);
41MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
42
43/* time AHA spends off the bus (not to monopolize it) during data transfer */
44static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
45module_param_array(bus_off, int, NULL, 0);
46MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
47
48/* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
49static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
50module_param_array(dma_speed, int, NULL, 0);
51MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#define BIOS_TRANSLATION_6432 1 /* Default case these days */
54#define BIOS_TRANSLATION_25563 2 /* Big disk case */
55
56struct aha1542_hostdata {
57 /* This will effectively start both of them at the first mailbox */
58 int bios_translation; /* Mapping bios uses - for compatibility */
59 int aha1542_last_mbi_used;
60 int aha1542_last_mbo_used;
Ondrej Zary55b28f92015-02-06 23:11:44 +010061 struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
Christoph Hellwig1794ef22018-11-10 09:28:22 +010062 struct mailbox *mb;
63 dma_addr_t mb_handle;
64 struct ccb *ccb;
65 dma_addr_t ccb_handle;
66};
67
68struct aha1542_cmd {
69 struct chain *chain;
70 dma_addr_t chain_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071};
72
Ondrej Zaryf1bbef62015-02-06 23:11:26 +010073static inline void aha1542_intr_reset(u16 base)
74{
75 outb(IRST, CONTROL(base));
76}
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Ondrej Zary2093bfa2015-02-06 23:11:31 +010078static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
79{
80 bool delayed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Ondrej Zary2093bfa2015-02-06 23:11:31 +010082 if (timeout == 0) {
83 timeout = 3000000;
84 delayed = false;
85 }
86
87 while (1) {
88 u8 bits = inb(port) & mask;
89 if ((bits & allof) == allof && ((bits & noneof) == 0))
90 break;
91 if (delayed)
92 mdelay(1);
93 if (--timeout == 0)
94 return false;
95 }
96
97 return true;
98}
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100100static int aha1542_outb(unsigned int base, u8 val)
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100101{
Ondrej Zaryeef77802015-02-06 23:11:57 +0100102 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
103 return 1;
104 outb(val, DATA(base));
105
106 return 0;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100107}
108
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100109static int aha1542_out(unsigned int base, u8 *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100111 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100112 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100113 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100114 outb(*buf++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 }
Ondrej Zary23e69402015-02-06 23:11:39 +0100116 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
117 return 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120}
121
122/* Only used at boot time, so we do not need to worry about latency as much
123 here */
124
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100125static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100128 if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100129 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100130 *buf++ = inb(DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
135static int makecode(unsigned hosterr, unsigned scsierr)
136{
137 switch (hosterr) {
138 case 0x0:
139 case 0xa: /* Linked command complete without error and linked normally */
140 case 0xb: /* Linked command complete without error, interrupt generated */
141 hosterr = 0;
142 break;
143
144 case 0x11: /* Selection time out-The initiator selection or target
145 reselection was not complete within the SCSI Time out period */
146 hosterr = DID_TIME_OUT;
147 break;
148
149 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
150 than was allocated by the Data Length field or the sum of the
151 Scatter / Gather Data Length fields. */
152
153 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
154
155 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
156 invalid. This usually indicates a software failure. */
157
158 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
159 This usually indicates a software failure. */
160
161 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
162 of linked CCB's does not specify the same logical unit number as
163 the first. */
164 case 0x18: /* Invalid Target Direction received from Host-The direction of a
165 Target Mode CCB was invalid. */
166
167 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
168 received to service data transfer between the same target LUN
169 and initiator SCSI ID in the same direction. */
170
171 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
172 length segment or invalid segment list boundaries was received.
173 A CCB parameter was invalid. */
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100174#ifdef DEBUG
175 printk("Aha1542: %x %x\n", hosterr, scsierr);
176#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 hosterr = DID_ERROR; /* Couldn't find any better */
178 break;
179
180 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
181 phase sequence was requested by the target. The host adapter
182 will generate a SCSI Reset Condition, notifying the host with
183 a SCRD interrupt */
184 hosterr = DID_RESET;
185 break;
186 default:
187 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
188 break;
189 }
190 return scsierr | (hosterr << 16);
191}
192
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100193static int aha1542_test_port(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100195 u8 inquiry_result[4];
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100196 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
198 /* Quick and dirty test for presence of the card. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100199 if (inb(STATUS(sh->io_port)) == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 return 0;
201
202 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 /* In case some other card was probing here, reset interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100205 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100207 outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 mdelay(20); /* Wait a little bit for things to settle down. */
210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100212 if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100213 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 /* Shouldn't have generated any interrupts during reset */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100216 if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100217 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 /* Perform a host adapter inquiry instead so we do not need to set
220 up the mailboxes ahead of time */
221
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100222 aha1542_outb(sh->io_port, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100224 for (i = 0; i < 4; i++) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100225 if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100226 return 0;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100227 inquiry_result[i] = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 }
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 /* Reading port should reset DF */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100231 if (inb(STATUS(sh->io_port)) & DF)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100232 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 /* When HACC, command is completed, and we're though testing */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100235 if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100236 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 /* Clear interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100239 outb(IRST, CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Ondrej Zarybdebe222015-02-06 23:11:35 +0100241 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
243
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100244static void aha1542_free_cmd(struct scsi_cmnd *cmd)
245{
246 struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
247 struct device *dev = cmd->device->host->dma_dev;
248 size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
249
250 if (acmd->chain) {
251 dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
252 kfree(acmd->chain);
253 }
254
255 acmd->chain = NULL;
256 scsi_dma_unmap(cmd);
257}
258
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100259static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100261 struct Scsi_Host *sh = dev_id;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100262 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100263 void (*my_done)(struct scsi_cmnd *) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 int errstatus, mbi, mbo, mbistatus;
265 int number_serviced;
266 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100267 struct scsi_cmnd *tmp_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100269 struct mailbox *mb = aha1542->mb;
270 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272#ifdef DEBUG
273 {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100274 flag = inb(INTRFLAGS(sh->io_port));
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100275 shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 if (!(flag & ANYINTR))
277 printk("no interrupt?");
278 if (flag & MBIF)
279 printk("MBIF ");
280 if (flag & MBOA)
281 printk("MBOF ");
282 if (flag & HACC)
283 printk("HACC ");
284 if (flag & SCRD)
285 printk("SCRD ");
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100286 printk("status %02x\n", inb(STATUS(sh->io_port)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 };
288#endif
289 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100291 spin_lock_irqsave(sh->host_lock, flags);
292 while (1) {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100293 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
295 /* Check for unusual interrupts. If any of these happen, we should
296 probably do something special, but for now just printing a message
297 is sufficient. A SCSI reset detected is something that we really
298 need to deal with in some way. */
299 if (flag & ~MBIF) {
300 if (flag & MBOA)
301 printk("MBOF ");
302 if (flag & HACC)
303 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100304 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100307 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Ondrej Zarye98878f2015-02-06 23:11:25 +0100309 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 if (mbi >= 2 * AHA1542_MAILBOXES)
311 mbi = AHA1542_MAILBOXES;
312
313 do {
314 if (mb[mbi].status != 0)
315 break;
316 mbi++;
317 if (mbi >= 2 * AHA1542_MAILBOXES)
318 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100319 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 if (mb[mbi].status == 0) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100322 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100324 if (!number_serviced)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100325 shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100326 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 };
328
James Bottomley492ca4d2018-11-27 21:41:24 -0800329 mbo = (scsi2int(mb[mbi].ccbptr) - (unsigned long)aha1542->ccb_handle) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 mbistatus = mb[mbi].status;
331 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100332 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334#ifdef DEBUG
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100335 if (ccb[mbo].tarstat | ccb[mbo].hastat)
336 shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
337 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338#endif
339
340 if (mbistatus == 3)
341 continue; /* Aborted command not found */
342
343#ifdef DEBUG
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100344 shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345#endif
346
Ondrej Zary55b28f92015-02-06 23:11:44 +0100347 tmp_cmd = aha1542->int_cmds[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
Ondrej Zary55b28f92015-02-06 23:11:44 +0100349 if (!tmp_cmd || !tmp_cmd->scsi_done) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100350 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100351 shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
352 shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100354 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100356 my_done = tmp_cmd->scsi_done;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100357 aha1542_free_cmd(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 /* Fetch the sense data, and tuck it away, in the required slot. The
359 Adaptec automatically fetches it, and there is no guarantee that
360 we will still have it in the cdb when we come back */
361 if (ccb[mbo].tarstat == 2)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100362 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900363 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365
366 /* is there mail :-) */
367
368 /* more error checking left out here */
369 if (mbistatus != 1)
370 /* This is surely wrong, but I don't know what's right */
371 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
372 else
373 errstatus = 0;
374
375#ifdef DEBUG
376 if (errstatus)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100377 shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 ccb[mbo].hastat, ccb[mbo].tarstat);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100379 if (ccb[mbo].tarstat == 2)
380 print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100381 if (errstatus)
382 printk("aha1542_intr_handle: returning %6x\n", errstatus);
383#endif
Ondrej Zary55b28f92015-02-06 23:11:44 +0100384 tmp_cmd->result = errstatus;
385 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
Ondrej Zarye98878f2015-02-06 23:11:25 +0100386 far as queuecommand is concerned */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100387 my_done(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 number_serviced++;
389 };
390}
391
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100392static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
Ondrej Zary09a44832015-02-06 23:11:28 +0100393{
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100394 struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100395 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100396 u8 direction;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100397 u8 target = cmd->device->id;
398 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100400 int bufflen = scsi_bufflen(cmd);
Ondrej Zary8c08a622015-04-21 23:27:50 +0200401 int mbo, sg_count;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100402 struct mailbox *mb = aha1542->mb;
403 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Ondrej Zary55b28f92015-02-06 23:11:44 +0100405 if (*cmd->cmnd == REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 /* Don't do the command - we have the sense data already */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100407 cmd->result = 0;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100408 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 return 0;
410 }
411#ifdef DEBUG
Ondrej Zary764a0c72015-02-06 23:11:54 +0100412 {
413 int i = -1;
414 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
415 i = xscsi2int(cmd->cmnd + 2);
416 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
417 i = scsi2int(cmd->cmnd + 2);
418 shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
419 target, *cmd->cmnd, i, bufflen);
420 print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422#endif
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100423 sg_count = scsi_dma_map(cmd);
424 if (sg_count) {
425 size_t len = sg_count * sizeof(struct chain);
426
427 acmd->chain = kmalloc(len, GFP_DMA);
428 if (!acmd->chain)
429 goto out_unmap;
430 acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
431 len, DMA_TO_DEVICE);
432 if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
433 goto out_free_chain;
Ondrej Zary8c08a622015-04-21 23:27:50 +0200434 }
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 /* Use the outgoing mailboxes in a round-robin fashion, because this
437 is how the host adapter will scan for them */
438
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100439 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100440 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 if (mbo >= AHA1542_MAILBOXES)
442 mbo = 0;
443
444 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100445 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 break;
447 mbo++;
448 if (mbo >= AHA1542_MAILBOXES)
449 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100450 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Ondrej Zary55b28f92015-02-06 23:11:44 +0100452 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 panic("Unable to find empty mailbox for aha1542.\n");
454
Ondrej Zary55b28f92015-02-06 23:11:44 +0100455 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
Ondrej Zarye98878f2015-02-06 23:11:25 +0100456 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Ondrej Zarye98878f2015-02-06 23:11:25 +0100458 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
460#ifdef DEBUG
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100461 shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462#endif
463
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100464 /* This gets trashed for some reason */
465 any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467 memset(&ccb[mbo], 0, sizeof(struct ccb));
468
Ondrej Zary55b28f92015-02-06 23:11:44 +0100469 ccb[mbo].cdblen = cmd->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 direction = 0;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100472 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 direction = 8;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100474 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 direction = 16;
476
Ondrej Zary55b28f92015-02-06 23:11:44 +0100477 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300479 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200480 struct scatterlist *sg;
Ondrej Zary8c08a622015-04-21 23:27:50 +0200481 int i;
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100482
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100484 scsi_for_each_sg(cmd, sg, sg_count, i) {
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100485 any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg));
486 any2scsi(acmd->chain[i].datalen, sg_dma_len(sg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300488 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100489 any2scsi(ccb[mbo].dataptr, acmd->chain_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490#ifdef DEBUG
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100491 shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain);
492 print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493#endif
494 } else {
495 ccb[mbo].op = 0; /* SCSI Initiator Command */
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300496 any2scsi(ccb[mbo].datalen, 0);
497 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 };
499 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
500 ccb[mbo].rsalen = 16;
501 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
502 ccb[mbo].commlinkid = 0;
503
504#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100505 print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100506 printk("aha1542_queuecommand: now waiting for interrupt ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507#endif
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100508 mb[mbo].status = 1;
509 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
510 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
512 return 0;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100513out_free_chain:
514 kfree(acmd->chain);
515 acmd->chain = NULL;
516out_unmap:
517 scsi_dma_unmap(cmd);
518 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
521/* Initialize mailboxes */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100522static void setup_mailboxes(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100524 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100525 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100526 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100529 aha1542->mb[i].status = 0;
530 any2scsi(aha1542->mb[i].ccbptr,
531 aha1542->ccb_handle + i * sizeof(struct ccb));
532 aha1542->mb[AHA1542_MAILBOXES + i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100534 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100535 any2scsi(mb_cmd + 2, aha1542->mb_handle);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100536 if (aha1542_out(sh->io_port, mb_cmd, 5))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100537 shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100538 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539}
540
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100541static int aha1542_getconfig(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100543 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100545 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100547 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100549 aha1542_outb(sh->io_port, CMD_RETCONF);
550 aha1542_in(sh->io_port, inquiry_result, 3, 0);
551 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100552 shost_printk(KERN_ERR, sh, "error querying board settings\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100553 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 switch (inquiry_result[0]) {
555 case 0x80:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100556 sh->dma_channel = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 break;
558 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100559 sh->dma_channel = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 break;
561 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100562 sh->dma_channel = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 break;
564 case 0x01:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100565 sh->dma_channel = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 break;
567 case 0:
568 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
569 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100570 sh->dma_channel = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 break;
572 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100573 shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 return -1;
575 };
576 switch (inquiry_result[1]) {
577 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100578 sh->irq = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 break;
580 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100581 sh->irq = 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 break;
583 case 0x8:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100584 sh->irq = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 break;
586 case 0x4:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100587 sh->irq = 11;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 break;
589 case 0x2:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100590 sh->irq = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 break;
592 case 0x1:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100593 sh->irq = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 break;
595 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100596 shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 return -1;
598 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100599 sh->this_id = inquiry_result[2] & 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 return 0;
601}
602
603/* This function should only be called for 1542C boards - we can detect
604 the special firmware settings and unlock the board */
605
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100606static int aha1542_mbenable(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100608 static u8 mbenable_cmd[3];
609 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 int retval;
611
612 retval = BIOS_TRANSLATION_6432;
613
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100614 aha1542_outb(sh->io_port, CMD_EXTBIOS);
615 if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return retval;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100617 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100618 goto fail;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100619 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
622 mbenable_cmd[0] = CMD_MBENABLE;
623 mbenable_cmd[1] = 0;
624 mbenable_cmd[2] = mbenable_result[1];
625
626 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
627 retval = BIOS_TRANSLATION_25563;
628
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100629 if (aha1542_out(sh->io_port, mbenable_cmd, 3))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100630 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 };
632 while (0) {
633fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100634 shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100636 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return retval;
638}
639
640/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100641static int aha1542_query(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100643 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100644 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100646 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100648 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100650 aha1542_outb(sh->io_port, CMD_INQUIRY);
651 aha1542_in(sh->io_port, inquiry_result, 4, 0);
652 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100653 shost_printk(KERN_ERR, sh, "error querying card type\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100654 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100656 aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 /* For an AHA1740 series board, we ignore the board since there is a
659 hardware bug which can lead to wrong blocks being returned if the board
660 is operating in the 1542 emulation mode. Since there is an extended mode
661 driver, we simply ignore the board and let the 1740 driver pick it up.
662 */
663
664 if (inquiry_result[0] == 0x43) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100665 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 -0700666 return 1;
667 };
668
669 /* Always call this - boards that do not support extended bios translation
670 will ignore the command, and we will set the proper default */
671
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100672 aha1542->bios_translation = aha1542_mbenable(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
674 return 0;
675}
676
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100677static u8 dma_speed_hw(int dma_speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100679 switch (dma_speed) {
680 case 5:
681 return 0x00;
682 case 6:
683 return 0x04;
684 case 7:
685 return 0x01;
686 case 8:
687 return 0x02;
688 case 10:
689 return 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100692 return 0xff; /* invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100695/* Set the Bus on/off-times as not to ruin floppy performance */
Ondrej Zary37d607b2015-02-06 23:11:50 +0100696static 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 +0100697{
Ondrej Zary37d607b2015-02-06 23:11:50 +0100698 if (bus_on > 0) {
699 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100700
Ondrej Zary37d607b2015-02-06 23:11:50 +0100701 aha1542_intr_reset(sh->io_port);
702 if (aha1542_out(sh->io_port, oncmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100703 goto fail;
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100704 }
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100705
Ondrej Zary37d607b2015-02-06 23:11:50 +0100706 if (bus_off > 0) {
707 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100708
Ondrej Zary37d607b2015-02-06 23:11:50 +0100709 aha1542_intr_reset(sh->io_port);
710 if (aha1542_out(sh->io_port, offcmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100711 goto fail;
712 }
713
Ondrej Zary37d607b2015-02-06 23:11:50 +0100714 if (dma_speed_hw(dma_speed) != 0xff) {
715 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100716
Ondrej Zary37d607b2015-02-06 23:11:50 +0100717 aha1542_intr_reset(sh->io_port);
718 if (aha1542_out(sh->io_port, dmacmd, 2))
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100719 goto fail;
720 }
Ondrej Zary37d607b2015-02-06 23:11:50 +0100721 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100722 return;
723fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100724 shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
Ondrej Zary37d607b2015-02-06 23:11:50 +0100725 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100726}
727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100729static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100731 unsigned int base_io = io[indx];
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100732 struct Scsi_Host *sh;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100733 struct aha1542_hostdata *aha1542;
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100734 char dma_info[] = "no DMA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Ondrej Zary3a70c002015-02-06 23:11:40 +0100736 if (base_io == 0)
737 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Ondrej Zary3a70c002015-02-06 23:11:40 +0100739 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
740 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100742 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
743 if (!sh)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100744 goto release;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100745 aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100747 sh->unique_id = base_io;
748 sh->io_port = base_io;
749 sh->n_io_port = AHA1542_REGION_SIZE;
750 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
751 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
752
753 if (!aha1542_test_port(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100754 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Ondrej Zary37d607b2015-02-06 23:11:50 +0100756 aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100757 if (aha1542_query(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100758 goto unregister;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100759 if (aha1542_getconfig(sh) == -1)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100760 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100762 if (sh->dma_channel != 0xFF)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100763 snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
764 shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
765 sh->this_id, base_io, sh->irq, dma_info);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100766 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100767 shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100769 if (dma_set_mask_and_coherent(pdev, DMA_BIT_MASK(24)) < 0)
770 goto unregister;
771
772 aha1542->mb = dma_alloc_coherent(pdev,
773 AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
774 &aha1542->mb_handle, GFP_KERNEL);
775 if (!aha1542->mb)
776 goto unregister;
777
778 aha1542->ccb = dma_alloc_coherent(pdev,
779 AHA1542_MAILBOXES * sizeof(struct ccb),
780 &aha1542->ccb_handle, GFP_KERNEL);
781 if (!aha1542->ccb)
782 goto free_mb;
783
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100784 setup_mailboxes(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100786 if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100787 shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100788 goto free_ccb;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100789 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100790 if (sh->dma_channel != 0xFF) {
791 if (request_dma(sh->dma_channel, "aha1542")) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100792 shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100793 goto free_irq;
794 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100795 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
796 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
797 enable_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100798 }
799 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400800
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100801 if (scsi_add_host(sh, pdev))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100802 goto free_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100804 scsi_scan_host(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100806 return sh;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100807
Ondrej Zary3a70c002015-02-06 23:11:40 +0100808free_dma:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100809 if (sh->dma_channel != 0xff)
810 free_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100811free_irq:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100812 free_irq(sh->irq, sh);
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100813free_ccb:
814 dma_free_coherent(pdev, AHA1542_MAILBOXES * sizeof(struct ccb),
815 aha1542->ccb, aha1542->ccb_handle);
816free_mb:
817 dma_free_coherent(pdev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
818 aha1542->mb, aha1542->mb_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819unregister:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100820 scsi_host_put(sh);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100821release:
822 release_region(base_io, AHA1542_REGION_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Ondrej Zary643a7c42015-02-06 23:11:22 +0100824 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825}
826
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100827static int aha1542_release(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100829 struct aha1542_hostdata *aha1542 = shost_priv(sh);
830 struct device *dev = sh->dma_dev;
831
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100832 scsi_remove_host(sh);
833 if (sh->dma_channel != 0xff)
834 free_dma(sh->dma_channel);
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100835 dma_free_coherent(dev, AHA1542_MAILBOXES * sizeof(struct ccb),
836 aha1542->ccb, aha1542->ccb_handle);
837 dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
838 aha1542->mb, aha1542->mb_handle);
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100839 if (sh->irq)
840 free_irq(sh->irq, sh);
841 if (sh->io_port && sh->n_io_port)
842 release_region(sh->io_port, sh->n_io_port);
843 scsi_host_put(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 return 0;
845}
846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848/*
849 * This is a device reset. This is handled by sending a special command
850 * to the device.
851 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100852static int aha1542_dev_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100854 struct Scsi_Host *sh = cmd->device->host;
855 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100857 struct mailbox *mb = aha1542->mb;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100858 u8 target = cmd->device->id;
859 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100861 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100863 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100864 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 if (mbo >= AHA1542_MAILBOXES)
866 mbo = 0;
867
868 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100869 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 break;
871 mbo++;
872 if (mbo >= AHA1542_MAILBOXES)
873 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100874 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
Ondrej Zary55b28f92015-02-06 23:11:44 +0100876 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 panic("Unable to find empty mailbox for aha1542.\n");
878
Ondrej Zary55b28f92015-02-06 23:11:44 +0100879 aha1542->int_cmds[mbo] = cmd; /* This will effectively
Ondrej Zarye98878f2015-02-06 23:11:25 +0100880 prevent someone else from
881 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Ondrej Zarye98878f2015-02-06 23:11:25 +0100883 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100885 /* This gets trashed for some reason */
886 any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 memset(&ccb[mbo], 0, sizeof(struct ccb));
889
890 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
891
892 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
893
894 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
895 ccb[mbo].commlinkid = 0;
896
897 /*
898 * Now tell the 1542 to flush all pending commands for this
899 * target
900 */
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100901 aha1542_outb(sh->io_port, CMD_START_SCSI);
902 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Ondrej Zary55b28f92015-02-06 23:11:44 +0100904 scmd_printk(KERN_WARNING, cmd,
Jeff Garzik017560f2005-10-24 18:04:36 -0400905 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
Ondrej Zary55b28f92015-02-06 23:11:44 +0100910static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100912 struct Scsi_Host *sh = cmd->device->host;
913 struct aha1542_hostdata *aha1542 = shost_priv(sh);
914 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 int i;
916
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100917 spin_lock_irqsave(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 /*
919 * This does a scsi reset for all devices on the bus.
920 * In principle, we could also reset the 1542 - should
921 * we do this? Try this first, and we can add that later
922 * if it turns out to be useful.
923 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100924 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Ondrej Zary55b28f92015-02-06 23:11:44 +0100926 if (!wait_mask(STATUS(cmd->device->host->io_port),
Ondrej Zary7061dec2015-02-06 23:11:56 +0100927 STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100928 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zarya13b3722015-02-06 23:11:34 +0100929 return FAILED;
930 }
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100931
Ondrej Zary8537cba2015-02-06 23:11:37 +0100932 /*
933 * We need to do this too before the 1542 can interact with
934 * us again after host reset.
935 */
936 if (reset_cmd & HRST)
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100937 setup_mailboxes(cmd->device->host);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100938
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 /*
940 * Now try to pick up the pieces. For all pending commands,
941 * free any internal data structures, and basically clear things
942 * out. We do not try and restart any commands or anything -
943 * the strategy handler takes care of that crap.
944 */
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100945 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 -0700946
947 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100948 if (aha1542->int_cmds[i] != NULL) {
949 struct scsi_cmnd *tmp_cmd;
950 tmp_cmd = aha1542->int_cmds[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Ondrej Zary55b28f92015-02-06 23:11:44 +0100952 if (tmp_cmd->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 /*
954 * If this device implements the soft reset option,
955 * then it is still holding onto the command, and
956 * may yet complete it. In this case, we don't
957 * flush the data.
958 */
959 continue;
960 }
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100961 aha1542_free_cmd(tmp_cmd);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100962 aha1542->int_cmds[i] = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100963 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965 }
966
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100967 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969}
970
Ondrej Zary55b28f92015-02-06 23:11:44 +0100971static int aha1542_bus_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100973 return aha1542_reset(cmd, SCRST);
Ondrej Zary8537cba2015-02-06 23:11:37 +0100974}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Ondrej Zary55b28f92015-02-06 23:11:44 +0100976static int aha1542_host_reset(struct scsi_cmnd *cmd)
Ondrej Zary8537cba2015-02-06 23:11:37 +0100977{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100978 return aha1542_reset(cmd, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979}
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981static int aha1542_biosparam(struct scsi_device *sdev,
Ondrej Zary17787a02015-02-06 23:11:42 +0100982 struct block_device *bdev, sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100984 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Ondrej Zary17787a02015-02-06 23:11:42 +0100986 if (capacity >= 0x200000 &&
987 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 /* Please verify that this is the same as what DOS returns */
Ondrej Zary17787a02015-02-06 23:11:42 +0100989 geom[0] = 255; /* heads */
990 geom[1] = 63; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 } else {
Ondrej Zary17787a02015-02-06 23:11:42 +0100992 geom[0] = 64; /* heads */
993 geom[1] = 32; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
Ondrej Zary17787a02015-02-06 23:11:42 +0100995 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 return 0;
998}
999MODULE_LICENSE("GPL");
1000
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001001static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001002 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 .proc_name = "aha1542",
1004 .name = "Adaptec 1542",
Christoph Hellwig1794ef22018-11-10 09:28:22 +01001005 .cmd_size = sizeof(struct aha1542_cmd),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 .eh_device_reset_handler= aha1542_dev_reset,
1008 .eh_bus_reset_handler = aha1542_bus_reset,
1009 .eh_host_reset_handler = aha1542_host_reset,
1010 .bios_param = aha1542_biosparam,
1011 .can_queue = AHA1542_MAILBOXES,
1012 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001013 .sg_tablesize = 16,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 .unchecked_isa_dma = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001016
1017static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1018{
1019 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1020
1021 if (!sh)
1022 return 0;
1023
1024 dev_set_drvdata(pdev, sh);
1025 return 1;
1026}
1027
1028static int aha1542_isa_remove(struct device *pdev,
1029 unsigned int ndev)
1030{
1031 aha1542_release(dev_get_drvdata(pdev));
1032 dev_set_drvdata(pdev, NULL);
1033 return 0;
1034}
1035
1036static struct isa_driver aha1542_isa_driver = {
1037 .match = aha1542_isa_match,
1038 .remove = aha1542_isa_remove,
1039 .driver = {
1040 .name = "aha1542"
1041 },
1042};
1043static int isa_registered;
1044
1045#ifdef CONFIG_PNP
Arvind Yadav78453a32017-08-16 10:29:24 +05301046static const struct pnp_device_id aha1542_pnp_ids[] = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001047 { .id = "ADP1542" },
1048 { .id = "" }
1049};
1050MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1051
1052static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1053{
1054 int indx;
1055 struct Scsi_Host *sh;
1056
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001057 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1058 if (io[indx])
Ondrej Zary643a7c42015-02-06 23:11:22 +01001059 continue;
1060
1061 if (pnp_activate_dev(pdev) < 0)
1062 continue;
1063
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001064 io[indx] = pnp_port_start(pdev, 0);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001065
1066 /* The card can be queried for its DMA, we have
1067 the DMA set up that is enough */
1068
Ondrej Zary2906b3c2015-02-06 23:11:51 +01001069 dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001070 }
1071
1072 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1073 if (!sh)
1074 return -ENODEV;
1075
1076 pnp_set_drvdata(pdev, sh);
1077 return 0;
1078}
1079
1080static void aha1542_pnp_remove(struct pnp_dev *pdev)
1081{
1082 aha1542_release(pnp_get_drvdata(pdev));
1083 pnp_set_drvdata(pdev, NULL);
1084}
1085
1086static struct pnp_driver aha1542_pnp_driver = {
1087 .name = "aha1542",
1088 .id_table = aha1542_pnp_ids,
1089 .probe = aha1542_pnp_probe,
1090 .remove = aha1542_pnp_remove,
1091};
1092static int pnp_registered;
1093#endif /* CONFIG_PNP */
1094
1095static int __init aha1542_init(void)
1096{
1097 int ret = 0;
Ondrej Zary643a7c42015-02-06 23:11:22 +01001098
1099#ifdef CONFIG_PNP
1100 if (isapnp) {
1101 ret = pnp_register_driver(&aha1542_pnp_driver);
1102 if (!ret)
1103 pnp_registered = 1;
1104 }
1105#endif
1106 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1107 if (!ret)
1108 isa_registered = 1;
1109
1110#ifdef CONFIG_PNP
1111 if (pnp_registered)
1112 ret = 0;
1113#endif
1114 if (isa_registered)
1115 ret = 0;
1116
1117 return ret;
1118}
1119
1120static void __exit aha1542_exit(void)
1121{
1122#ifdef CONFIG_PNP
1123 if (pnp_registered)
1124 pnp_unregister_driver(&aha1542_pnp_driver);
1125#endif
1126 if (isa_registered)
1127 isa_unregister_driver(&aha1542_isa_driver);
1128}
1129
1130module_init(aha1542_init);
1131module_exit(aha1542_exit);