blob: ba7a5725be04f98a50abb5bac4e2c51e32ad0548 [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 };
David Howells88f06b72017-04-04 16:54:27 +010034module_param_hw_array(io, int, ioport, NULL, 0);
Ondrej Zaryf71429a2015-02-06 23:11:41 +010035MODULE_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];
Christoph Hellwig1794ef22018-11-10 09:28:22 +010061 struct mailbox *mb;
62 dma_addr_t mb_handle;
63 struct ccb *ccb;
64 dma_addr_t ccb_handle;
65};
66
67struct aha1542_cmd {
68 struct chain *chain;
69 dma_addr_t chain_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
Ondrej Zaryf1bbef62015-02-06 23:11:26 +010072static inline void aha1542_intr_reset(u16 base)
73{
74 outb(IRST, CONTROL(base));
75}
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Ondrej Zary2093bfa2015-02-06 23:11:31 +010077static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
78{
79 bool delayed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Ondrej Zary2093bfa2015-02-06 23:11:31 +010081 if (timeout == 0) {
82 timeout = 3000000;
83 delayed = false;
84 }
85
86 while (1) {
87 u8 bits = inb(port) & mask;
88 if ((bits & allof) == allof && ((bits & noneof) == 0))
89 break;
90 if (delayed)
91 mdelay(1);
92 if (--timeout == 0)
93 return false;
94 }
95
96 return true;
97}
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Ondrej Zarycad2fc72015-02-06 23:11:43 +010099static int aha1542_outb(unsigned int base, u8 val)
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100100{
Ondrej Zaryeef77802015-02-06 23:11:57 +0100101 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
102 return 1;
103 outb(val, DATA(base));
104
105 return 0;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100106}
107
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100108static int aha1542_out(unsigned int base, u8 *buf, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100110 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100111 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100112 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100113 outb(*buf++, DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 }
Ondrej Zary23e69402015-02-06 23:11:39 +0100115 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
116 return 1;
Ondrej Zary0c2b6482015-02-06 23:11:33 +0100117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
120
121/* Only used at boot time, so we do not need to worry about latency as much
122 here */
123
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100124static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 while (len--) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100127 if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100128 return 1;
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100129 *buf++ = inb(DATA(base));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132}
133
134static int makecode(unsigned hosterr, unsigned scsierr)
135{
136 switch (hosterr) {
137 case 0x0:
138 case 0xa: /* Linked command complete without error and linked normally */
139 case 0xb: /* Linked command complete without error, interrupt generated */
140 hosterr = 0;
141 break;
142
143 case 0x11: /* Selection time out-The initiator selection or target
144 reselection was not complete within the SCSI Time out period */
145 hosterr = DID_TIME_OUT;
146 break;
147
148 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
149 than was allocated by the Data Length field or the sum of the
150 Scatter / Gather Data Length fields. */
151
152 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
153
154 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
155 invalid. This usually indicates a software failure. */
156
157 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
158 This usually indicates a software failure. */
159
160 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
161 of linked CCB's does not specify the same logical unit number as
162 the first. */
163 case 0x18: /* Invalid Target Direction received from Host-The direction of a
164 Target Mode CCB was invalid. */
165
166 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
167 received to service data transfer between the same target LUN
168 and initiator SCSI ID in the same direction. */
169
170 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
171 length segment or invalid segment list boundaries was received.
172 A CCB parameter was invalid. */
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100173#ifdef DEBUG
174 printk("Aha1542: %x %x\n", hosterr, scsierr);
175#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 hosterr = DID_ERROR; /* Couldn't find any better */
177 break;
178
179 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
180 phase sequence was requested by the target. The host adapter
181 will generate a SCSI Reset Condition, notifying the host with
182 a SCRD interrupt */
183 hosterr = DID_RESET;
184 break;
185 default:
186 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
187 break;
188 }
189 return scsierr | (hosterr << 16);
190}
191
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100192static int aha1542_test_port(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100194 u8 inquiry_result[4];
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100195 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 /* Quick and dirty test for presence of the card. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100198 if (inb(STATUS(sh->io_port)) == 0xff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 return 0;
200
201 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 /* In case some other card was probing here, reset interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100204 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100206 outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
208 mdelay(20); /* Wait a little bit for things to settle down. */
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /* Expect INIT and IDLE, any of the others are bad */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100211 if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
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 /* Shouldn't have generated any interrupts during reset */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100215 if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
Ondrej Zarya13b3722015-02-06 23:11:34 +0100216 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 /* Perform a host adapter inquiry instead so we do not need to set
219 up the mailboxes ahead of time */
220
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100221 aha1542_outb(sh->io_port, CMD_INQUIRY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100223 for (i = 0; i < 4; i++) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100224 if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100225 return 0;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100226 inquiry_result[i] = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 /* Reading port should reset DF */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100230 if (inb(STATUS(sh->io_port)) & DF)
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 /* When HACC, command is completed, and we're though testing */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100234 if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
Ondrej Zarya13b3722015-02-06 23:11:34 +0100235 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 /* Clear interrupts */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100238 outb(IRST, CONTROL(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Ondrej Zarybdebe222015-02-06 23:11:35 +0100240 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241}
242
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100243static void aha1542_free_cmd(struct scsi_cmnd *cmd)
244{
245 struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
246 struct device *dev = cmd->device->host->dma_dev;
247 size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
248
249 if (acmd->chain) {
250 dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
251 kfree(acmd->chain);
252 }
253
254 acmd->chain = NULL;
255 scsi_dma_unmap(cmd);
256}
257
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100258static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100260 struct Scsi_Host *sh = dev_id;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100261 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100262 void (*my_done)(struct scsi_cmnd *) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 int errstatus, mbi, mbo, mbistatus;
264 int number_serviced;
265 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100266 struct scsi_cmnd *tmp_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 int flag;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100268 struct mailbox *mb = aha1542->mb;
269 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271#ifdef DEBUG
272 {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100273 flag = inb(INTRFLAGS(sh->io_port));
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100274 shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 if (!(flag & ANYINTR))
276 printk("no interrupt?");
277 if (flag & MBIF)
278 printk("MBIF ");
279 if (flag & MBOA)
280 printk("MBOF ");
281 if (flag & HACC)
282 printk("HACC ");
283 if (flag & SCRD)
284 printk("SCRD ");
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100285 printk("status %02x\n", inb(STATUS(sh->io_port)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 };
287#endif
288 number_serviced = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100290 spin_lock_irqsave(sh->host_lock, flags);
291 while (1) {
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100292 flag = inb(INTRFLAGS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
294 /* Check for unusual interrupts. If any of these happen, we should
295 probably do something special, but for now just printing a message
296 is sufficient. A SCSI reset detected is something that we really
297 need to deal with in some way. */
298 if (flag & ~MBIF) {
299 if (flag & MBOA)
300 printk("MBOF ");
301 if (flag & HACC)
302 printk("HACC ");
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100303 if (flag & SCRD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 printk("SCRD ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100306 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Ondrej Zarye98878f2015-02-06 23:11:25 +0100308 mbi = aha1542->aha1542_last_mbi_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 if (mbi >= 2 * AHA1542_MAILBOXES)
310 mbi = AHA1542_MAILBOXES;
311
312 do {
313 if (mb[mbi].status != 0)
314 break;
315 mbi++;
316 if (mbi >= 2 * AHA1542_MAILBOXES)
317 mbi = AHA1542_MAILBOXES;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100318 } while (mbi != aha1542->aha1542_last_mbi_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320 if (mb[mbi].status == 0) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100321 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 /* Hmm, no mail. Must have read it the last time around */
Ondrej Zarydfd7c992015-02-06 23:11:36 +0100323 if (!number_serviced)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100324 shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100325 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 };
327
James Bottomley492ca4d2018-11-27 21:41:24 -0800328 mbo = (scsi2int(mb[mbi].ccbptr) - (unsigned long)aha1542->ccb_handle) / sizeof(struct ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 mbistatus = mb[mbi].status;
330 mb[mbi].status = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100331 aha1542->aha1542_last_mbi_used = mbi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
333#ifdef DEBUG
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100334 if (ccb[mbo].tarstat | ccb[mbo].hastat)
335 shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
336 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337#endif
338
339 if (mbistatus == 3)
340 continue; /* Aborted command not found */
341
342#ifdef DEBUG
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100343 shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344#endif
345
Ondrej Zary55b28f92015-02-06 23:11:44 +0100346 tmp_cmd = aha1542->int_cmds[mbo];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Ondrej Zary55b28f92015-02-06 23:11:44 +0100348 if (!tmp_cmd || !tmp_cmd->scsi_done) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100349 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100350 shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
351 shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100353 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 }
Ondrej Zary55b28f92015-02-06 23:11:44 +0100355 my_done = tmp_cmd->scsi_done;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100356 aha1542_free_cmd(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* Fetch the sense data, and tuck it away, in the required slot. The
358 Adaptec automatically fetches it, and there is no guarantee that
359 we will still have it in the cdb when we come back */
360 if (ccb[mbo].tarstat == 2)
Ondrej Zary55b28f92015-02-06 23:11:44 +0100361 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +0900362 SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364
365 /* is there mail :-) */
366
367 /* more error checking left out here */
368 if (mbistatus != 1)
369 /* This is surely wrong, but I don't know what's right */
370 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
371 else
372 errstatus = 0;
373
374#ifdef DEBUG
375 if (errstatus)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100376 shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 ccb[mbo].hastat, ccb[mbo].tarstat);
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100378 if (ccb[mbo].tarstat == 2)
379 print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
Ondrej Zaryfde1fb82015-02-06 23:11:52 +0100380 if (errstatus)
381 printk("aha1542_intr_handle: returning %6x\n", errstatus);
382#endif
Ondrej Zary55b28f92015-02-06 23:11:44 +0100383 tmp_cmd->result = errstatus;
384 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
Ondrej Zarye98878f2015-02-06 23:11:25 +0100385 far as queuecommand is concerned */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100386 my_done(tmp_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 number_serviced++;
388 };
389}
390
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100391static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
Ondrej Zary09a44832015-02-06 23:11:28 +0100392{
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100393 struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100394 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100395 u8 direction;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100396 u8 target = cmd->device->id;
397 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 unsigned long flags;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100399 int bufflen = scsi_bufflen(cmd);
Ondrej Zary8c08a622015-04-21 23:27:50 +0200400 int mbo, sg_count;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100401 struct mailbox *mb = aha1542->mb;
402 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Ondrej Zary55b28f92015-02-06 23:11:44 +0100404 if (*cmd->cmnd == REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 /* Don't do the command - we have the sense data already */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100406 cmd->result = 0;
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100407 cmd->scsi_done(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 return 0;
409 }
410#ifdef DEBUG
Ondrej Zary764a0c72015-02-06 23:11:54 +0100411 {
412 int i = -1;
413 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
414 i = xscsi2int(cmd->cmnd + 2);
415 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
416 i = scsi2int(cmd->cmnd + 2);
417 shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
418 target, *cmd->cmnd, i, bufflen);
419 print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421#endif
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100422 sg_count = scsi_dma_map(cmd);
423 if (sg_count) {
424 size_t len = sg_count * sizeof(struct chain);
425
426 acmd->chain = kmalloc(len, GFP_DMA);
427 if (!acmd->chain)
428 goto out_unmap;
429 acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
430 len, DMA_TO_DEVICE);
431 if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
432 goto out_free_chain;
Ondrej Zary8c08a622015-04-21 23:27:50 +0200433 }
434
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 /* Use the outgoing mailboxes in a round-robin fashion, because this
436 is how the host adapter will scan for them */
437
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100438 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100439 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 if (mbo >= AHA1542_MAILBOXES)
441 mbo = 0;
442
443 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100444 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 break;
446 mbo++;
447 if (mbo >= AHA1542_MAILBOXES)
448 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100449 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Ondrej Zary55b28f92015-02-06 23:11:44 +0100451 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 panic("Unable to find empty mailbox for aha1542.\n");
453
Ondrej Zary55b28f92015-02-06 23:11:44 +0100454 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
Ondrej Zarye98878f2015-02-06 23:11:25 +0100455 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Ondrej Zarye98878f2015-02-06 23:11:25 +0100457 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
459#ifdef DEBUG
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100460 shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461#endif
462
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100463 /* This gets trashed for some reason */
464 any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 memset(&ccb[mbo], 0, sizeof(struct ccb));
467
Ondrej Zary55b28f92015-02-06 23:11:44 +0100468 ccb[mbo].cdblen = cmd->cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 direction = 0;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100471 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 direction = 8;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100473 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 direction = 16;
475
Ondrej Zary55b28f92015-02-06 23:11:44 +0100476 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300478 if (bufflen) {
Jens Axboe51cf2242007-07-16 10:00:31 +0200479 struct scatterlist *sg;
Ondrej Zary8c08a622015-04-21 23:27:50 +0200480 int i;
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100483 scsi_for_each_sg(cmd, sg, sg_count, i) {
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100484 any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg));
485 any2scsi(acmd->chain[i].datalen, sg_dma_len(sg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 };
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300487 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100488 any2scsi(ccb[mbo].dataptr, acmd->chain_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489#ifdef DEBUG
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100490 shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain);
491 print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492#endif
493 } else {
494 ccb[mbo].op = 0; /* SCSI Initiator Command */
Boaz Harroshfc3fdfc2007-09-09 21:02:45 +0300495 any2scsi(ccb[mbo].datalen, 0);
496 any2scsi(ccb[mbo].dataptr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 };
498 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
499 ccb[mbo].rsalen = 16;
500 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
501 ccb[mbo].commlinkid = 0;
502
503#ifdef DEBUG
Ondrej Zary6ddc8cf2015-02-06 23:11:53 +0100504 print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100505 printk("aha1542_queuecommand: now waiting for interrupt ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506#endif
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100507 mb[mbo].status = 1;
508 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
509 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511 return 0;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100512out_free_chain:
513 kfree(acmd->chain);
514 acmd->chain = NULL;
515out_unmap:
516 scsi_dma_unmap(cmd);
517 return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
520/* Initialize mailboxes */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100521static void setup_mailboxes(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100523 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycad2fc72015-02-06 23:11:43 +0100524 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100525 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100528 aha1542->mb[i].status = 0;
529 any2scsi(aha1542->mb[i].ccbptr,
530 aha1542->ccb_handle + i * sizeof(struct ccb));
531 aha1542->mb[AHA1542_MAILBOXES + i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100533 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100534 any2scsi(mb_cmd + 2, aha1542->mb_handle);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100535 if (aha1542_out(sh->io_port, mb_cmd, 5))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100536 shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100537 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538}
539
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100540static int aha1542_getconfig(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100542 u8 inquiry_result[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100544 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100546 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100548 aha1542_outb(sh->io_port, CMD_RETCONF);
549 aha1542_in(sh->io_port, inquiry_result, 3, 0);
550 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100551 shost_printk(KERN_ERR, sh, "error querying board settings\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100552 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 switch (inquiry_result[0]) {
554 case 0x80:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100555 sh->dma_channel = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 break;
557 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100558 sh->dma_channel = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 break;
560 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100561 sh->dma_channel = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 break;
563 case 0x01:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100564 sh->dma_channel = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 break;
566 case 0:
567 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
568 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100569 sh->dma_channel = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 break;
571 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100572 shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 return -1;
574 };
575 switch (inquiry_result[1]) {
576 case 0x40:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100577 sh->irq = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 break;
579 case 0x20:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100580 sh->irq = 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 break;
582 case 0x8:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100583 sh->irq = 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 break;
585 case 0x4:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100586 sh->irq = 11;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 break;
588 case 0x2:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100589 sh->irq = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 break;
591 case 0x1:
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100592 sh->irq = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 break;
594 default:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100595 shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return -1;
597 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100598 sh->this_id = inquiry_result[2] & 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 return 0;
600}
601
602/* This function should only be called for 1542C boards - we can detect
603 the special firmware settings and unlock the board */
604
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100605static int aha1542_mbenable(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100607 static u8 mbenable_cmd[3];
608 static u8 mbenable_result[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 int retval;
610
611 retval = BIOS_TRANSLATION_6432;
612
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100613 aha1542_outb(sh->io_port, CMD_EXTBIOS);
614 if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 return retval;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100616 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100617 goto fail;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100618 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
621 mbenable_cmd[0] = CMD_MBENABLE;
622 mbenable_cmd[1] = 0;
623 mbenable_cmd[2] = mbenable_result[1];
624
625 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
626 retval = BIOS_TRANSLATION_25563;
627
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100628 if (aha1542_out(sh->io_port, mbenable_cmd, 3))
Ondrej Zary2093bfa2015-02-06 23:11:31 +0100629 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 };
631 while (0) {
632fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100633 shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 }
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100635 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 return retval;
637}
638
639/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100640static int aha1542_query(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100642 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Ondrej Zarycb5b5702015-02-06 23:11:27 +0100643 u8 inquiry_result[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 int i;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100645 i = inb(STATUS(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 if (i & DF) {
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100647 i = inb(DATA(sh->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 };
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100649 aha1542_outb(sh->io_port, CMD_INQUIRY);
650 aha1542_in(sh->io_port, inquiry_result, 4, 0);
651 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100652 shost_printk(KERN_ERR, sh, "error querying card type\n");
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100653 aha1542_intr_reset(sh->io_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100655 aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 /* For an AHA1740 series board, we ignore the board since there is a
658 hardware bug which can lead to wrong blocks being returned if the board
659 is operating in the 1542 emulation mode. Since there is an extended mode
660 driver, we simply ignore the board and let the 1740 driver pick it up.
661 */
662
663 if (inquiry_result[0] == 0x43) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100664 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 -0700665 return 1;
666 };
667
668 /* Always call this - boards that do not support extended bios translation
669 will ignore the command, and we will set the proper default */
670
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100671 aha1542->bios_translation = aha1542_mbenable(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 return 0;
674}
675
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100676static u8 dma_speed_hw(int dma_speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100678 switch (dma_speed) {
679 case 5:
680 return 0x00;
681 case 6:
682 return 0x04;
683 case 7:
684 return 0x01;
685 case 8:
686 return 0x02;
687 case 10:
688 return 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100691 return 0xff; /* invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692}
693
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100694/* Set the Bus on/off-times as not to ruin floppy performance */
Ondrej Zary37d607b2015-02-06 23:11:50 +0100695static 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 +0100696{
Ondrej Zary37d607b2015-02-06 23:11:50 +0100697 if (bus_on > 0) {
698 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100699
Ondrej Zary37d607b2015-02-06 23:11:50 +0100700 aha1542_intr_reset(sh->io_port);
701 if (aha1542_out(sh->io_port, oncmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100702 goto fail;
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100703 }
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100704
Ondrej Zary37d607b2015-02-06 23:11:50 +0100705 if (bus_off > 0) {
706 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100707
Ondrej Zary37d607b2015-02-06 23:11:50 +0100708 aha1542_intr_reset(sh->io_port);
709 if (aha1542_out(sh->io_port, offcmd, 2))
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100710 goto fail;
711 }
712
Ondrej Zary37d607b2015-02-06 23:11:50 +0100713 if (dma_speed_hw(dma_speed) != 0xff) {
714 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100715
Ondrej Zary37d607b2015-02-06 23:11:50 +0100716 aha1542_intr_reset(sh->io_port);
717 if (aha1542_out(sh->io_port, dmacmd, 2))
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100718 goto fail;
719 }
Ondrej Zary37d607b2015-02-06 23:11:50 +0100720 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100721 return;
722fail:
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100723 shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
Ondrej Zary37d607b2015-02-06 23:11:50 +0100724 aha1542_intr_reset(sh->io_port);
Ondrej Zaryb847fd02015-02-06 23:11:38 +0100725}
726
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727/* return non-zero on detection */
Ondrej Zary643a7c42015-02-06 23:11:22 +0100728static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729{
Ondrej Zaryf71429a2015-02-06 23:11:41 +0100730 unsigned int base_io = io[indx];
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100731 struct Scsi_Host *sh;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100732 struct aha1542_hostdata *aha1542;
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100733 char dma_info[] = "no DMA";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Ondrej Zary3a70c002015-02-06 23:11:40 +0100735 if (base_io == 0)
736 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Ondrej Zary3a70c002015-02-06 23:11:40 +0100738 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
739 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100741 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
742 if (!sh)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100743 goto release;
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100744 aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100746 sh->unique_id = base_io;
747 sh->io_port = base_io;
748 sh->n_io_port = AHA1542_REGION_SIZE;
749 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
750 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
751
752 if (!aha1542_test_port(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100753 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Ondrej Zary37d607b2015-02-06 23:11:50 +0100755 aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100756 if (aha1542_query(sh))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100757 goto unregister;
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100758 if (aha1542_getconfig(sh) == -1)
Ondrej Zary3a70c002015-02-06 23:11:40 +0100759 goto unregister;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100761 if (sh->dma_channel != 0xFF)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100762 snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
763 shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
764 sh->this_id, base_io, sh->irq, dma_info);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100765 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100766 shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100768 if (dma_set_mask_and_coherent(pdev, DMA_BIT_MASK(24)) < 0)
769 goto unregister;
770
771 aha1542->mb = dma_alloc_coherent(pdev,
772 AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
773 &aha1542->mb_handle, GFP_KERNEL);
774 if (!aha1542->mb)
775 goto unregister;
776
777 aha1542->ccb = dma_alloc_coherent(pdev,
778 AHA1542_MAILBOXES * sizeof(struct ccb),
779 &aha1542->ccb_handle, GFP_KERNEL);
780 if (!aha1542->ccb)
781 goto free_mb;
782
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100783 setup_mailboxes(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100785 if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100786 shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100787 goto free_ccb;
Ondrej Zary3a70c002015-02-06 23:11:40 +0100788 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100789 if (sh->dma_channel != 0xFF) {
790 if (request_dma(sh->dma_channel, "aha1542")) {
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100791 shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
Ondrej Zary3a70c002015-02-06 23:11:40 +0100792 goto free_irq;
793 }
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100794 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
795 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
796 enable_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100797 }
798 }
Jeff Garzik87c4d7b2008-04-24 19:45:32 -0400799
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100800 if (scsi_add_host(sh, pdev))
Ondrej Zary3a70c002015-02-06 23:11:40 +0100801 goto free_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100803 scsi_scan_host(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100805 return sh;
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100806
Ondrej Zary3a70c002015-02-06 23:11:40 +0100807free_dma:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100808 if (sh->dma_channel != 0xff)
809 free_dma(sh->dma_channel);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100810free_irq:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100811 free_irq(sh->irq, sh);
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100812free_ccb:
813 dma_free_coherent(pdev, AHA1542_MAILBOXES * sizeof(struct ccb),
814 aha1542->ccb, aha1542->ccb_handle);
815free_mb:
816 dma_free_coherent(pdev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
817 aha1542->mb, aha1542->mb_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818unregister:
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100819 scsi_host_put(sh);
Ondrej Zary3a70c002015-02-06 23:11:40 +0100820release:
821 release_region(base_io, AHA1542_REGION_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
Ondrej Zary643a7c42015-02-06 23:11:22 +0100823 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100826static int aha1542_release(struct Scsi_Host *sh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100828 struct aha1542_hostdata *aha1542 = shost_priv(sh);
829 struct device *dev = sh->dma_dev;
830
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100831 scsi_remove_host(sh);
832 if (sh->dma_channel != 0xff)
833 free_dma(sh->dma_channel);
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100834 dma_free_coherent(dev, AHA1542_MAILBOXES * sizeof(struct ccb),
835 aha1542->ccb, aha1542->ccb_handle);
836 dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
837 aha1542->mb, aha1542->mb_handle);
Ondrej Zaryc2532f62015-02-06 23:11:45 +0100838 if (sh->irq)
839 free_irq(sh->irq, sh);
840 if (sh->io_port && sh->n_io_port)
841 release_region(sh->io_port, sh->n_io_port);
842 scsi_host_put(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return 0;
844}
845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847/*
848 * This is a device reset. This is handled by sending a special command
849 * to the device.
850 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100851static int aha1542_dev_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100853 struct Scsi_Host *sh = cmd->device->host;
854 struct aha1542_hostdata *aha1542 = shost_priv(sh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 unsigned long flags;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100856 struct mailbox *mb = aha1542->mb;
Ondrej Zary55b28f92015-02-06 23:11:44 +0100857 u8 target = cmd->device->id;
858 u8 lun = cmd->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 int mbo;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100860 struct ccb *ccb = aha1542->ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100862 spin_lock_irqsave(sh->host_lock, flags);
Ondrej Zarye98878f2015-02-06 23:11:25 +0100863 mbo = aha1542->aha1542_last_mbo_used + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (mbo >= AHA1542_MAILBOXES)
865 mbo = 0;
866
867 do {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100868 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 break;
870 mbo++;
871 if (mbo >= AHA1542_MAILBOXES)
872 mbo = 0;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100873 } while (mbo != aha1542->aha1542_last_mbo_used);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
Ondrej Zary55b28f92015-02-06 23:11:44 +0100875 if (mb[mbo].status || aha1542->int_cmds[mbo])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 panic("Unable to find empty mailbox for aha1542.\n");
877
Ondrej Zary55b28f92015-02-06 23:11:44 +0100878 aha1542->int_cmds[mbo] = cmd; /* This will effectively
Ondrej Zarye98878f2015-02-06 23:11:25 +0100879 prevent someone else from
880 screwing with this cdb. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Ondrej Zarye98878f2015-02-06 23:11:25 +0100882 aha1542->aha1542_last_mbo_used = mbo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100884 /* This gets trashed for some reason */
885 any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 memset(&ccb[mbo], 0, sizeof(struct ccb));
888
889 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
890
891 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
892
893 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
894 ccb[mbo].commlinkid = 0;
895
896 /*
897 * Now tell the 1542 to flush all pending commands for this
898 * target
899 */
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100900 aha1542_outb(sh->io_port, CMD_START_SCSI);
901 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Ondrej Zary55b28f92015-02-06 23:11:44 +0100903 scmd_printk(KERN_WARNING, cmd,
Jeff Garzik017560f2005-10-24 18:04:36 -0400904 "Trying device reset for target\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907}
908
Ondrej Zary55b28f92015-02-06 23:11:44 +0100909static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910{
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100911 struct Scsi_Host *sh = cmd->device->host;
912 struct aha1542_hostdata *aha1542 = shost_priv(sh);
913 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 int i;
915
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100916 spin_lock_irqsave(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 /*
918 * This does a scsi reset for all devices on the bus.
919 * In principle, we could also reset the 1542 - should
920 * we do this? Try this first, and we can add that later
921 * if it turns out to be useful.
922 */
Ondrej Zary55b28f92015-02-06 23:11:44 +0100923 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Ondrej Zary55b28f92015-02-06 23:11:44 +0100925 if (!wait_mask(STATUS(cmd->device->host->io_port),
Ondrej Zary7061dec2015-02-06 23:11:56 +0100926 STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100927 spin_unlock_irqrestore(sh->host_lock, flags);
Ondrej Zarya13b3722015-02-06 23:11:34 +0100928 return FAILED;
929 }
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100930
Ondrej Zary8537cba2015-02-06 23:11:37 +0100931 /*
932 * We need to do this too before the 1542 can interact with
933 * us again after host reset.
934 */
935 if (reset_cmd & HRST)
Ondrej Zary68ea9de2015-02-06 23:11:49 +0100936 setup_mailboxes(cmd->device->host);
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100937
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 /*
939 * Now try to pick up the pieces. For all pending commands,
940 * free any internal data structures, and basically clear things
941 * out. We do not try and restart any commands or anything -
942 * the strategy handler takes care of that crap.
943 */
Ondrej Zary2906b3c2015-02-06 23:11:51 +0100944 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 -0700945
946 for (i = 0; i < AHA1542_MAILBOXES; i++) {
Ondrej Zary55b28f92015-02-06 23:11:44 +0100947 if (aha1542->int_cmds[i] != NULL) {
948 struct scsi_cmnd *tmp_cmd;
949 tmp_cmd = aha1542->int_cmds[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
Ondrej Zary55b28f92015-02-06 23:11:44 +0100951 if (tmp_cmd->device->soft_reset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 /*
953 * If this device implements the soft reset option,
954 * then it is still holding onto the command, and
955 * may yet complete it. In this case, we don't
956 * flush the data.
957 */
958 continue;
959 }
Christoph Hellwig1794ef22018-11-10 09:28:22 +0100960 aha1542_free_cmd(tmp_cmd);
Ondrej Zary55b28f92015-02-06 23:11:44 +0100961 aha1542->int_cmds[i] = NULL;
Ondrej Zarye98878f2015-02-06 23:11:25 +0100962 aha1542->mb[i].status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964 }
965
Ondrej Zary1b0224b2015-02-06 23:11:55 +0100966 spin_unlock_irqrestore(sh->host_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 return SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
Ondrej Zary55b28f92015-02-06 23:11:44 +0100970static int aha1542_bus_reset(struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100972 return aha1542_reset(cmd, SCRST);
Ondrej Zary8537cba2015-02-06 23:11:37 +0100973}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Ondrej Zary55b28f92015-02-06 23:11:44 +0100975static int aha1542_host_reset(struct scsi_cmnd *cmd)
Ondrej Zary8537cba2015-02-06 23:11:37 +0100976{
Ondrej Zary55b28f92015-02-06 23:11:44 +0100977 return aha1542_reset(cmd, HRST | SCRST);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978}
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980static int aha1542_biosparam(struct scsi_device *sdev,
Ondrej Zary17787a02015-02-06 23:11:42 +0100981 struct block_device *bdev, sector_t capacity, int geom[])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
Ondrej Zarye98878f2015-02-06 23:11:25 +0100983 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Ondrej Zary17787a02015-02-06 23:11:42 +0100985 if (capacity >= 0x200000 &&
986 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 /* Please verify that this is the same as what DOS returns */
Ondrej Zary17787a02015-02-06 23:11:42 +0100988 geom[0] = 255; /* heads */
989 geom[1] = 63; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 } else {
Ondrej Zary17787a02015-02-06 23:11:42 +0100991 geom[0] = 64; /* heads */
992 geom[1] = 32; /* sectors */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
Ondrej Zary17787a02015-02-06 23:11:42 +0100994 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996 return 0;
997}
998MODULE_LICENSE("GPL");
999
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001000static struct scsi_host_template driver_template = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001001 .module = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 .proc_name = "aha1542",
1003 .name = "Adaptec 1542",
Christoph Hellwig1794ef22018-11-10 09:28:22 +01001004 .cmd_size = sizeof(struct aha1542_cmd),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 .queuecommand = aha1542_queuecommand,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 .eh_device_reset_handler= aha1542_dev_reset,
1007 .eh_bus_reset_handler = aha1542_bus_reset,
1008 .eh_host_reset_handler = aha1542_host_reset,
1009 .bios_param = aha1542_biosparam,
1010 .can_queue = AHA1542_MAILBOXES,
1011 .this_id = 7,
Ondrej Zary10be6252015-02-06 23:11:24 +01001012 .sg_tablesize = 16,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 .unchecked_isa_dma = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014};
Ondrej Zary643a7c42015-02-06 23:11:22 +01001015
1016static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1017{
1018 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1019
1020 if (!sh)
1021 return 0;
1022
1023 dev_set_drvdata(pdev, sh);
1024 return 1;
1025}
1026
1027static int aha1542_isa_remove(struct device *pdev,
1028 unsigned int ndev)
1029{
1030 aha1542_release(dev_get_drvdata(pdev));
1031 dev_set_drvdata(pdev, NULL);
1032 return 0;
1033}
1034
1035static struct isa_driver aha1542_isa_driver = {
1036 .match = aha1542_isa_match,
1037 .remove = aha1542_isa_remove,
1038 .driver = {
1039 .name = "aha1542"
1040 },
1041};
1042static int isa_registered;
1043
1044#ifdef CONFIG_PNP
Arvind Yadav78453a32017-08-16 10:29:24 +05301045static const struct pnp_device_id aha1542_pnp_ids[] = {
Ondrej Zary643a7c42015-02-06 23:11:22 +01001046 { .id = "ADP1542" },
1047 { .id = "" }
1048};
1049MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1050
1051static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1052{
1053 int indx;
1054 struct Scsi_Host *sh;
1055
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001056 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1057 if (io[indx])
Ondrej Zary643a7c42015-02-06 23:11:22 +01001058 continue;
1059
1060 if (pnp_activate_dev(pdev) < 0)
1061 continue;
1062
Ondrej Zaryf71429a2015-02-06 23:11:41 +01001063 io[indx] = pnp_port_start(pdev, 0);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001064
1065 /* The card can be queried for its DMA, we have
1066 the DMA set up that is enough */
1067
Ondrej Zary2906b3c2015-02-06 23:11:51 +01001068 dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
Ondrej Zary643a7c42015-02-06 23:11:22 +01001069 }
1070
1071 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1072 if (!sh)
1073 return -ENODEV;
1074
1075 pnp_set_drvdata(pdev, sh);
1076 return 0;
1077}
1078
1079static void aha1542_pnp_remove(struct pnp_dev *pdev)
1080{
1081 aha1542_release(pnp_get_drvdata(pdev));
1082 pnp_set_drvdata(pdev, NULL);
1083}
1084
1085static struct pnp_driver aha1542_pnp_driver = {
1086 .name = "aha1542",
1087 .id_table = aha1542_pnp_ids,
1088 .probe = aha1542_pnp_probe,
1089 .remove = aha1542_pnp_remove,
1090};
1091static int pnp_registered;
1092#endif /* CONFIG_PNP */
1093
1094static int __init aha1542_init(void)
1095{
1096 int ret = 0;
Ondrej Zary643a7c42015-02-06 23:11:22 +01001097
1098#ifdef CONFIG_PNP
1099 if (isapnp) {
1100 ret = pnp_register_driver(&aha1542_pnp_driver);
1101 if (!ret)
1102 pnp_registered = 1;
1103 }
1104#endif
1105 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1106 if (!ret)
1107 isa_registered = 1;
1108
1109#ifdef CONFIG_PNP
1110 if (pnp_registered)
1111 ret = 0;
1112#endif
1113 if (isa_registered)
1114 ret = 0;
1115
1116 return ret;
1117}
1118
1119static void __exit aha1542_exit(void)
1120{
1121#ifdef CONFIG_PNP
1122 if (pnp_registered)
1123 pnp_unregister_driver(&aha1542_pnp_driver);
1124#endif
1125 if (isa_registered)
1126 isa_unregister_driver(&aha1542_isa_driver);
1127}
1128
1129module_init(aha1542_init);
1130module_exit(aha1542_exit);