1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for Adaptec AHA-1542 SCSI host adapters
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 1992 Tommy Thorn
6*4882a593Smuzhiyun * Copyright (C) 1993, 1994, 1995 Eric Youngdale
7*4882a593Smuzhiyun * Copyright (C) 2015 Ondrej Zary
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/types.h>
14*4882a593Smuzhiyun #include <linux/string.h>
15*4882a593Smuzhiyun #include <linux/delay.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun #include <linux/isa.h>
19*4882a593Smuzhiyun #include <linux/pnp.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/io.h>
22*4882a593Smuzhiyun #include <asm/dma.h>
23*4882a593Smuzhiyun #include <scsi/scsi_cmnd.h>
24*4882a593Smuzhiyun #include <scsi/scsi_device.h>
25*4882a593Smuzhiyun #include <scsi/scsi_host.h>
26*4882a593Smuzhiyun #include "aha1542.h"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define MAXBOARDS 4
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static bool isapnp = 1;
31*4882a593Smuzhiyun module_param(isapnp, bool, 0);
32*4882a593Smuzhiyun MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
35*4882a593Smuzhiyun module_param_hw_array(io, int, ioport, NULL, 0);
36*4882a593Smuzhiyun MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* time AHA spends on the AT-bus during data transfer */
39*4882a593Smuzhiyun static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
40*4882a593Smuzhiyun module_param_array(bus_on, int, NULL, 0);
41*4882a593Smuzhiyun MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* time AHA spends off the bus (not to monopolize it) during data transfer */
44*4882a593Smuzhiyun static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
45*4882a593Smuzhiyun module_param_array(bus_off, int, NULL, 0);
46*4882a593Smuzhiyun MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
49*4882a593Smuzhiyun static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
50*4882a593Smuzhiyun module_param_array(dma_speed, int, NULL, 0);
51*4882a593Smuzhiyun MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define BIOS_TRANSLATION_6432 1 /* Default case these days */
54*4882a593Smuzhiyun #define BIOS_TRANSLATION_25563 2 /* Big disk case */
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun struct aha1542_hostdata {
57*4882a593Smuzhiyun /* This will effectively start both of them at the first mailbox */
58*4882a593Smuzhiyun int bios_translation; /* Mapping bios uses - for compatibility */
59*4882a593Smuzhiyun int aha1542_last_mbi_used;
60*4882a593Smuzhiyun int aha1542_last_mbo_used;
61*4882a593Smuzhiyun struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
62*4882a593Smuzhiyun struct mailbox *mb;
63*4882a593Smuzhiyun dma_addr_t mb_handle;
64*4882a593Smuzhiyun struct ccb *ccb;
65*4882a593Smuzhiyun dma_addr_t ccb_handle;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun struct aha1542_cmd {
69*4882a593Smuzhiyun struct chain *chain;
70*4882a593Smuzhiyun dma_addr_t chain_handle;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
aha1542_intr_reset(u16 base)73*4882a593Smuzhiyun static inline void aha1542_intr_reset(u16 base)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun outb(IRST, CONTROL(base));
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
wait_mask(u16 port,u8 mask,u8 allof,u8 noneof,int timeout)78*4882a593Smuzhiyun static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun bool delayed = true;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun if (timeout == 0) {
83*4882a593Smuzhiyun timeout = 3000000;
84*4882a593Smuzhiyun delayed = false;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun while (1) {
88*4882a593Smuzhiyun u8 bits = inb(port) & mask;
89*4882a593Smuzhiyun if ((bits & allof) == allof && ((bits & noneof) == 0))
90*4882a593Smuzhiyun break;
91*4882a593Smuzhiyun if (delayed)
92*4882a593Smuzhiyun mdelay(1);
93*4882a593Smuzhiyun if (--timeout == 0)
94*4882a593Smuzhiyun return false;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun return true;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
aha1542_outb(unsigned int base,u8 val)100*4882a593Smuzhiyun static int aha1542_outb(unsigned int base, u8 val)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
103*4882a593Smuzhiyun return 1;
104*4882a593Smuzhiyun outb(val, DATA(base));
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
aha1542_out(unsigned int base,u8 * buf,int len)109*4882a593Smuzhiyun static int aha1542_out(unsigned int base, u8 *buf, int len)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun while (len--) {
112*4882a593Smuzhiyun if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
113*4882a593Smuzhiyun return 1;
114*4882a593Smuzhiyun outb(*buf++, DATA(base));
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
117*4882a593Smuzhiyun return 1;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun return 0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* Only used at boot time, so we do not need to worry about latency as much
123*4882a593Smuzhiyun here */
124*4882a593Smuzhiyun
aha1542_in(unsigned int base,u8 * buf,int len,int timeout)125*4882a593Smuzhiyun static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun while (len--) {
128*4882a593Smuzhiyun if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
129*4882a593Smuzhiyun return 1;
130*4882a593Smuzhiyun *buf++ = inb(DATA(base));
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
makecode(unsigned hosterr,unsigned scsierr)135*4882a593Smuzhiyun static int makecode(unsigned hosterr, unsigned scsierr)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun switch (hosterr) {
138*4882a593Smuzhiyun case 0x0:
139*4882a593Smuzhiyun case 0xa: /* Linked command complete without error and linked normally */
140*4882a593Smuzhiyun case 0xb: /* Linked command complete without error, interrupt generated */
141*4882a593Smuzhiyun hosterr = 0;
142*4882a593Smuzhiyun break;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun case 0x11: /* Selection time out-The initiator selection or target
145*4882a593Smuzhiyun reselection was not complete within the SCSI Time out period */
146*4882a593Smuzhiyun hosterr = DID_TIME_OUT;
147*4882a593Smuzhiyun break;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
150*4882a593Smuzhiyun than was allocated by the Data Length field or the sum of the
151*4882a593Smuzhiyun Scatter / Gather Data Length fields. */
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
156*4882a593Smuzhiyun invalid. This usually indicates a software failure. */
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
159*4882a593Smuzhiyun This usually indicates a software failure. */
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
162*4882a593Smuzhiyun of linked CCB's does not specify the same logical unit number as
163*4882a593Smuzhiyun the first. */
164*4882a593Smuzhiyun case 0x18: /* Invalid Target Direction received from Host-The direction of a
165*4882a593Smuzhiyun Target Mode CCB was invalid. */
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
168*4882a593Smuzhiyun received to service data transfer between the same target LUN
169*4882a593Smuzhiyun and initiator SCSI ID in the same direction. */
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
172*4882a593Smuzhiyun length segment or invalid segment list boundaries was received.
173*4882a593Smuzhiyun A CCB parameter was invalid. */
174*4882a593Smuzhiyun #ifdef DEBUG
175*4882a593Smuzhiyun printk("Aha1542: %x %x\n", hosterr, scsierr);
176*4882a593Smuzhiyun #endif
177*4882a593Smuzhiyun hosterr = DID_ERROR; /* Couldn't find any better */
178*4882a593Smuzhiyun break;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
181*4882a593Smuzhiyun phase sequence was requested by the target. The host adapter
182*4882a593Smuzhiyun will generate a SCSI Reset Condition, notifying the host with
183*4882a593Smuzhiyun a SCRD interrupt */
184*4882a593Smuzhiyun hosterr = DID_RESET;
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun default:
187*4882a593Smuzhiyun printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
188*4882a593Smuzhiyun break;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun return scsierr | (hosterr << 16);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
aha1542_test_port(struct Scsi_Host * sh)193*4882a593Smuzhiyun static int aha1542_test_port(struct Scsi_Host *sh)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun u8 inquiry_result[4];
196*4882a593Smuzhiyun int i;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* Quick and dirty test for presence of the card. */
199*4882a593Smuzhiyun if (inb(STATUS(sh->io_port)) == 0xff)
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* In case some other card was probing here, reset interrupts */
205*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun mdelay(20); /* Wait a little bit for things to settle down. */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /* Expect INIT and IDLE, any of the others are bad */
212*4882a593Smuzhiyun if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* Shouldn't have generated any interrupts during reset */
216*4882a593Smuzhiyun if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* Perform a host adapter inquiry instead so we do not need to set
220*4882a593Smuzhiyun up the mailboxes ahead of time */
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun aha1542_outb(sh->io_port, CMD_INQUIRY);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
225*4882a593Smuzhiyun if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun inquiry_result[i] = inb(DATA(sh->io_port));
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Reading port should reset DF */
231*4882a593Smuzhiyun if (inb(STATUS(sh->io_port)) & DF)
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* When HACC, command is completed, and we're though testing */
235*4882a593Smuzhiyun if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
236*4882a593Smuzhiyun return 0;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /* Clear interrupts */
239*4882a593Smuzhiyun outb(IRST, CONTROL(sh->io_port));
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun return 1;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
aha1542_free_cmd(struct scsi_cmnd * cmd)244*4882a593Smuzhiyun static void aha1542_free_cmd(struct scsi_cmnd *cmd)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
247*4882a593Smuzhiyun struct device *dev = cmd->device->host->dma_dev;
248*4882a593Smuzhiyun size_t len = scsi_sg_count(cmd) * sizeof(struct chain);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (acmd->chain) {
251*4882a593Smuzhiyun dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE);
252*4882a593Smuzhiyun kfree(acmd->chain);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun acmd->chain = NULL;
256*4882a593Smuzhiyun scsi_dma_unmap(cmd);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
aha1542_interrupt(int irq,void * dev_id)259*4882a593Smuzhiyun static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct Scsi_Host *sh = dev_id;
262*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
263*4882a593Smuzhiyun void (*my_done)(struct scsi_cmnd *) = NULL;
264*4882a593Smuzhiyun int errstatus, mbi, mbo, mbistatus;
265*4882a593Smuzhiyun int number_serviced;
266*4882a593Smuzhiyun unsigned long flags;
267*4882a593Smuzhiyun struct scsi_cmnd *tmp_cmd;
268*4882a593Smuzhiyun int flag;
269*4882a593Smuzhiyun struct mailbox *mb = aha1542->mb;
270*4882a593Smuzhiyun struct ccb *ccb = aha1542->ccb;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun #ifdef DEBUG
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun flag = inb(INTRFLAGS(sh->io_port));
275*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
276*4882a593Smuzhiyun if (!(flag & ANYINTR))
277*4882a593Smuzhiyun printk("no interrupt?");
278*4882a593Smuzhiyun if (flag & MBIF)
279*4882a593Smuzhiyun printk("MBIF ");
280*4882a593Smuzhiyun if (flag & MBOA)
281*4882a593Smuzhiyun printk("MBOF ");
282*4882a593Smuzhiyun if (flag & HACC)
283*4882a593Smuzhiyun printk("HACC ");
284*4882a593Smuzhiyun if (flag & SCRD)
285*4882a593Smuzhiyun printk("SCRD ");
286*4882a593Smuzhiyun printk("status %02x\n", inb(STATUS(sh->io_port)));
287*4882a593Smuzhiyun };
288*4882a593Smuzhiyun #endif
289*4882a593Smuzhiyun number_serviced = 0;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun spin_lock_irqsave(sh->host_lock, flags);
292*4882a593Smuzhiyun while (1) {
293*4882a593Smuzhiyun flag = inb(INTRFLAGS(sh->io_port));
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /* Check for unusual interrupts. If any of these happen, we should
296*4882a593Smuzhiyun probably do something special, but for now just printing a message
297*4882a593Smuzhiyun is sufficient. A SCSI reset detected is something that we really
298*4882a593Smuzhiyun need to deal with in some way. */
299*4882a593Smuzhiyun if (flag & ~MBIF) {
300*4882a593Smuzhiyun if (flag & MBOA)
301*4882a593Smuzhiyun printk("MBOF ");
302*4882a593Smuzhiyun if (flag & HACC)
303*4882a593Smuzhiyun printk("HACC ");
304*4882a593Smuzhiyun if (flag & SCRD)
305*4882a593Smuzhiyun printk("SCRD ");
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun mbi = aha1542->aha1542_last_mbi_used + 1;
310*4882a593Smuzhiyun if (mbi >= 2 * AHA1542_MAILBOXES)
311*4882a593Smuzhiyun mbi = AHA1542_MAILBOXES;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun do {
314*4882a593Smuzhiyun if (mb[mbi].status != 0)
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun mbi++;
317*4882a593Smuzhiyun if (mbi >= 2 * AHA1542_MAILBOXES)
318*4882a593Smuzhiyun mbi = AHA1542_MAILBOXES;
319*4882a593Smuzhiyun } while (mbi != aha1542->aha1542_last_mbi_used);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (mb[mbi].status == 0) {
322*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
323*4882a593Smuzhiyun /* Hmm, no mail. Must have read it the last time around */
324*4882a593Smuzhiyun if (!number_serviced)
325*4882a593Smuzhiyun shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
326*4882a593Smuzhiyun return IRQ_HANDLED;
327*4882a593Smuzhiyun };
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun mbo = (scsi2int(mb[mbi].ccbptr) - (unsigned long)aha1542->ccb_handle) / sizeof(struct ccb);
330*4882a593Smuzhiyun mbistatus = mb[mbi].status;
331*4882a593Smuzhiyun mb[mbi].status = 0;
332*4882a593Smuzhiyun aha1542->aha1542_last_mbi_used = mbi;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun #ifdef DEBUG
335*4882a593Smuzhiyun if (ccb[mbo].tarstat | ccb[mbo].hastat)
336*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
337*4882a593Smuzhiyun ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
338*4882a593Smuzhiyun #endif
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun if (mbistatus == 3)
341*4882a593Smuzhiyun continue; /* Aborted command not found */
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun #ifdef DEBUG
344*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
345*4882a593Smuzhiyun #endif
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun tmp_cmd = aha1542->int_cmds[mbo];
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun if (!tmp_cmd || !tmp_cmd->scsi_done) {
350*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
351*4882a593Smuzhiyun shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
352*4882a593Smuzhiyun shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
353*4882a593Smuzhiyun ccb[mbo].hastat, ccb[mbo].idlun, mbo);
354*4882a593Smuzhiyun return IRQ_HANDLED;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun my_done = tmp_cmd->scsi_done;
357*4882a593Smuzhiyun aha1542_free_cmd(tmp_cmd);
358*4882a593Smuzhiyun /* Fetch the sense data, and tuck it away, in the required slot. The
359*4882a593Smuzhiyun Adaptec automatically fetches it, and there is no guarantee that
360*4882a593Smuzhiyun we will still have it in the cdb when we come back */
361*4882a593Smuzhiyun if (ccb[mbo].tarstat == 2)
362*4882a593Smuzhiyun memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
363*4882a593Smuzhiyun SCSI_SENSE_BUFFERSIZE);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /* is there mail :-) */
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* more error checking left out here */
369*4882a593Smuzhiyun if (mbistatus != 1)
370*4882a593Smuzhiyun /* This is surely wrong, but I don't know what's right */
371*4882a593Smuzhiyun errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
372*4882a593Smuzhiyun else
373*4882a593Smuzhiyun errstatus = 0;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun #ifdef DEBUG
376*4882a593Smuzhiyun if (errstatus)
377*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
378*4882a593Smuzhiyun ccb[mbo].hastat, ccb[mbo].tarstat);
379*4882a593Smuzhiyun if (ccb[mbo].tarstat == 2)
380*4882a593Smuzhiyun print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
381*4882a593Smuzhiyun if (errstatus)
382*4882a593Smuzhiyun printk("aha1542_intr_handle: returning %6x\n", errstatus);
383*4882a593Smuzhiyun #endif
384*4882a593Smuzhiyun tmp_cmd->result = errstatus;
385*4882a593Smuzhiyun aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
386*4882a593Smuzhiyun far as queuecommand is concerned */
387*4882a593Smuzhiyun my_done(tmp_cmd);
388*4882a593Smuzhiyun number_serviced++;
389*4882a593Smuzhiyun };
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
aha1542_queuecommand(struct Scsi_Host * sh,struct scsi_cmnd * cmd)392*4882a593Smuzhiyun static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
395*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
396*4882a593Smuzhiyun u8 direction;
397*4882a593Smuzhiyun u8 target = cmd->device->id;
398*4882a593Smuzhiyun u8 lun = cmd->device->lun;
399*4882a593Smuzhiyun unsigned long flags;
400*4882a593Smuzhiyun int bufflen = scsi_bufflen(cmd);
401*4882a593Smuzhiyun int mbo, sg_count;
402*4882a593Smuzhiyun struct mailbox *mb = aha1542->mb;
403*4882a593Smuzhiyun struct ccb *ccb = aha1542->ccb;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun if (*cmd->cmnd == REQUEST_SENSE) {
406*4882a593Smuzhiyun /* Don't do the command - we have the sense data already */
407*4882a593Smuzhiyun cmd->result = 0;
408*4882a593Smuzhiyun cmd->scsi_done(cmd);
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun #ifdef DEBUG
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun int i = -1;
414*4882a593Smuzhiyun if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
415*4882a593Smuzhiyun i = xscsi2int(cmd->cmnd + 2);
416*4882a593Smuzhiyun else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
417*4882a593Smuzhiyun i = scsi2int(cmd->cmnd + 2);
418*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
419*4882a593Smuzhiyun target, *cmd->cmnd, i, bufflen);
420*4882a593Smuzhiyun print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun #endif
423*4882a593Smuzhiyun sg_count = scsi_dma_map(cmd);
424*4882a593Smuzhiyun if (sg_count) {
425*4882a593Smuzhiyun size_t len = sg_count * sizeof(struct chain);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun acmd->chain = kmalloc(len, GFP_DMA);
428*4882a593Smuzhiyun if (!acmd->chain)
429*4882a593Smuzhiyun goto out_unmap;
430*4882a593Smuzhiyun acmd->chain_handle = dma_map_single(sh->dma_dev, acmd->chain,
431*4882a593Smuzhiyun len, DMA_TO_DEVICE);
432*4882a593Smuzhiyun if (dma_mapping_error(sh->dma_dev, acmd->chain_handle))
433*4882a593Smuzhiyun goto out_free_chain;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /* Use the outgoing mailboxes in a round-robin fashion, because this
437*4882a593Smuzhiyun is how the host adapter will scan for them */
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun spin_lock_irqsave(sh->host_lock, flags);
440*4882a593Smuzhiyun mbo = aha1542->aha1542_last_mbo_used + 1;
441*4882a593Smuzhiyun if (mbo >= AHA1542_MAILBOXES)
442*4882a593Smuzhiyun mbo = 0;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun do {
445*4882a593Smuzhiyun if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun mbo++;
448*4882a593Smuzhiyun if (mbo >= AHA1542_MAILBOXES)
449*4882a593Smuzhiyun mbo = 0;
450*4882a593Smuzhiyun } while (mbo != aha1542->aha1542_last_mbo_used);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun if (mb[mbo].status || aha1542->int_cmds[mbo])
453*4882a593Smuzhiyun panic("Unable to find empty mailbox for aha1542.\n");
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
456*4882a593Smuzhiyun screwing with this cdb. */
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun aha1542->aha1542_last_mbo_used = mbo;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun #ifdef DEBUG
461*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
462*4882a593Smuzhiyun #endif
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun /* This gets trashed for some reason */
465*4882a593Smuzhiyun any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun memset(&ccb[mbo], 0, sizeof(struct ccb));
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun ccb[mbo].cdblen = cmd->cmd_len;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun direction = 0;
472*4882a593Smuzhiyun if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
473*4882a593Smuzhiyun direction = 8;
474*4882a593Smuzhiyun else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
475*4882a593Smuzhiyun direction = 16;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (bufflen) {
480*4882a593Smuzhiyun struct scatterlist *sg;
481*4882a593Smuzhiyun int i;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
484*4882a593Smuzhiyun scsi_for_each_sg(cmd, sg, sg_count, i) {
485*4882a593Smuzhiyun any2scsi(acmd->chain[i].dataptr, sg_dma_address(sg));
486*4882a593Smuzhiyun any2scsi(acmd->chain[i].datalen, sg_dma_len(sg));
487*4882a593Smuzhiyun };
488*4882a593Smuzhiyun any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
489*4882a593Smuzhiyun any2scsi(ccb[mbo].dataptr, acmd->chain_handle);
490*4882a593Smuzhiyun #ifdef DEBUG
491*4882a593Smuzhiyun shost_printk(KERN_DEBUG, sh, "cptr %p: ", acmd->chain);
492*4882a593Smuzhiyun print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, acmd->chain, 18);
493*4882a593Smuzhiyun #endif
494*4882a593Smuzhiyun } else {
495*4882a593Smuzhiyun ccb[mbo].op = 0; /* SCSI Initiator Command */
496*4882a593Smuzhiyun any2scsi(ccb[mbo].datalen, 0);
497*4882a593Smuzhiyun any2scsi(ccb[mbo].dataptr, 0);
498*4882a593Smuzhiyun };
499*4882a593Smuzhiyun ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
500*4882a593Smuzhiyun ccb[mbo].rsalen = 16;
501*4882a593Smuzhiyun ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
502*4882a593Smuzhiyun ccb[mbo].commlinkid = 0;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun #ifdef DEBUG
505*4882a593Smuzhiyun print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
506*4882a593Smuzhiyun printk("aha1542_queuecommand: now waiting for interrupt ");
507*4882a593Smuzhiyun #endif
508*4882a593Smuzhiyun mb[mbo].status = 1;
509*4882a593Smuzhiyun aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
510*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return 0;
513*4882a593Smuzhiyun out_free_chain:
514*4882a593Smuzhiyun kfree(acmd->chain);
515*4882a593Smuzhiyun acmd->chain = NULL;
516*4882a593Smuzhiyun out_unmap:
517*4882a593Smuzhiyun scsi_dma_unmap(cmd);
518*4882a593Smuzhiyun return SCSI_MLQUEUE_HOST_BUSY;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* Initialize mailboxes */
setup_mailboxes(struct Scsi_Host * sh)522*4882a593Smuzhiyun static void setup_mailboxes(struct Scsi_Host *sh)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
525*4882a593Smuzhiyun u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
526*4882a593Smuzhiyun int i;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun for (i = 0; i < AHA1542_MAILBOXES; i++) {
529*4882a593Smuzhiyun aha1542->mb[i].status = 0;
530*4882a593Smuzhiyun any2scsi(aha1542->mb[i].ccbptr,
531*4882a593Smuzhiyun aha1542->ccb_handle + i * sizeof(struct ccb));
532*4882a593Smuzhiyun aha1542->mb[AHA1542_MAILBOXES + i].status = 0;
533*4882a593Smuzhiyun };
534*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
535*4882a593Smuzhiyun any2scsi(mb_cmd + 2, aha1542->mb_handle);
536*4882a593Smuzhiyun if (aha1542_out(sh->io_port, mb_cmd, 5))
537*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
538*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
aha1542_getconfig(struct Scsi_Host * sh)541*4882a593Smuzhiyun static int aha1542_getconfig(struct Scsi_Host *sh)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun u8 inquiry_result[3];
544*4882a593Smuzhiyun int i;
545*4882a593Smuzhiyun i = inb(STATUS(sh->io_port));
546*4882a593Smuzhiyun if (i & DF) {
547*4882a593Smuzhiyun i = inb(DATA(sh->io_port));
548*4882a593Smuzhiyun };
549*4882a593Smuzhiyun aha1542_outb(sh->io_port, CMD_RETCONF);
550*4882a593Smuzhiyun aha1542_in(sh->io_port, inquiry_result, 3, 0);
551*4882a593Smuzhiyun if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
552*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "error querying board settings\n");
553*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
554*4882a593Smuzhiyun switch (inquiry_result[0]) {
555*4882a593Smuzhiyun case 0x80:
556*4882a593Smuzhiyun sh->dma_channel = 7;
557*4882a593Smuzhiyun break;
558*4882a593Smuzhiyun case 0x40:
559*4882a593Smuzhiyun sh->dma_channel = 6;
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun case 0x20:
562*4882a593Smuzhiyun sh->dma_channel = 5;
563*4882a593Smuzhiyun break;
564*4882a593Smuzhiyun case 0x01:
565*4882a593Smuzhiyun sh->dma_channel = 0;
566*4882a593Smuzhiyun break;
567*4882a593Smuzhiyun case 0:
568*4882a593Smuzhiyun /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
569*4882a593Smuzhiyun Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
570*4882a593Smuzhiyun sh->dma_channel = 0xFF;
571*4882a593Smuzhiyun break;
572*4882a593Smuzhiyun default:
573*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
574*4882a593Smuzhiyun return -1;
575*4882a593Smuzhiyun };
576*4882a593Smuzhiyun switch (inquiry_result[1]) {
577*4882a593Smuzhiyun case 0x40:
578*4882a593Smuzhiyun sh->irq = 15;
579*4882a593Smuzhiyun break;
580*4882a593Smuzhiyun case 0x20:
581*4882a593Smuzhiyun sh->irq = 14;
582*4882a593Smuzhiyun break;
583*4882a593Smuzhiyun case 0x8:
584*4882a593Smuzhiyun sh->irq = 12;
585*4882a593Smuzhiyun break;
586*4882a593Smuzhiyun case 0x4:
587*4882a593Smuzhiyun sh->irq = 11;
588*4882a593Smuzhiyun break;
589*4882a593Smuzhiyun case 0x2:
590*4882a593Smuzhiyun sh->irq = 10;
591*4882a593Smuzhiyun break;
592*4882a593Smuzhiyun case 0x1:
593*4882a593Smuzhiyun sh->irq = 9;
594*4882a593Smuzhiyun break;
595*4882a593Smuzhiyun default:
596*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
597*4882a593Smuzhiyun return -1;
598*4882a593Smuzhiyun };
599*4882a593Smuzhiyun sh->this_id = inquiry_result[2] & 7;
600*4882a593Smuzhiyun return 0;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun /* This function should only be called for 1542C boards - we can detect
604*4882a593Smuzhiyun the special firmware settings and unlock the board */
605*4882a593Smuzhiyun
aha1542_mbenable(struct Scsi_Host * sh)606*4882a593Smuzhiyun static int aha1542_mbenable(struct Scsi_Host *sh)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun static u8 mbenable_cmd[3];
609*4882a593Smuzhiyun static u8 mbenable_result[2];
610*4882a593Smuzhiyun int retval;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun retval = BIOS_TRANSLATION_6432;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun aha1542_outb(sh->io_port, CMD_EXTBIOS);
615*4882a593Smuzhiyun if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
616*4882a593Smuzhiyun return retval;
617*4882a593Smuzhiyun if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
618*4882a593Smuzhiyun goto fail;
619*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
622*4882a593Smuzhiyun mbenable_cmd[0] = CMD_MBENABLE;
623*4882a593Smuzhiyun mbenable_cmd[1] = 0;
624*4882a593Smuzhiyun mbenable_cmd[2] = mbenable_result[1];
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
627*4882a593Smuzhiyun retval = BIOS_TRANSLATION_25563;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if (aha1542_out(sh->io_port, mbenable_cmd, 3))
630*4882a593Smuzhiyun goto fail;
631*4882a593Smuzhiyun };
632*4882a593Smuzhiyun while (0) {
633*4882a593Smuzhiyun fail:
634*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
637*4882a593Smuzhiyun return retval;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
aha1542_query(struct Scsi_Host * sh)641*4882a593Smuzhiyun static int aha1542_query(struct Scsi_Host *sh)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
644*4882a593Smuzhiyun u8 inquiry_result[4];
645*4882a593Smuzhiyun int i;
646*4882a593Smuzhiyun i = inb(STATUS(sh->io_port));
647*4882a593Smuzhiyun if (i & DF) {
648*4882a593Smuzhiyun i = inb(DATA(sh->io_port));
649*4882a593Smuzhiyun };
650*4882a593Smuzhiyun aha1542_outb(sh->io_port, CMD_INQUIRY);
651*4882a593Smuzhiyun aha1542_in(sh->io_port, inquiry_result, 4, 0);
652*4882a593Smuzhiyun if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
653*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "error querying card type\n");
654*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun /* For an AHA1740 series board, we ignore the board since there is a
659*4882a593Smuzhiyun hardware bug which can lead to wrong blocks being returned if the board
660*4882a593Smuzhiyun is operating in the 1542 emulation mode. Since there is an extended mode
661*4882a593Smuzhiyun driver, we simply ignore the board and let the 1740 driver pick it up.
662*4882a593Smuzhiyun */
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun if (inquiry_result[0] == 0x43) {
665*4882a593Smuzhiyun shost_printk(KERN_INFO, sh, "Emulation mode not supported for AHA-1740 hardware, use aha1740 driver instead.\n");
666*4882a593Smuzhiyun return 1;
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* Always call this - boards that do not support extended bios translation
670*4882a593Smuzhiyun will ignore the command, and we will set the proper default */
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun aha1542->bios_translation = aha1542_mbenable(sh);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun return 0;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
dma_speed_hw(int dma_speed)677*4882a593Smuzhiyun static u8 dma_speed_hw(int dma_speed)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun switch (dma_speed) {
680*4882a593Smuzhiyun case 5:
681*4882a593Smuzhiyun return 0x00;
682*4882a593Smuzhiyun case 6:
683*4882a593Smuzhiyun return 0x04;
684*4882a593Smuzhiyun case 7:
685*4882a593Smuzhiyun return 0x01;
686*4882a593Smuzhiyun case 8:
687*4882a593Smuzhiyun return 0x02;
688*4882a593Smuzhiyun case 10:
689*4882a593Smuzhiyun return 0x03;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun return 0xff; /* invalid */
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun /* Set the Bus on/off-times as not to ruin floppy performance */
aha1542_set_bus_times(struct Scsi_Host * sh,int bus_on,int bus_off,int dma_speed)696*4882a593Smuzhiyun static void aha1542_set_bus_times(struct Scsi_Host *sh, int bus_on, int bus_off, int dma_speed)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun if (bus_on > 0) {
699*4882a593Smuzhiyun u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
702*4882a593Smuzhiyun if (aha1542_out(sh->io_port, oncmd, 2))
703*4882a593Smuzhiyun goto fail;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun if (bus_off > 0) {
707*4882a593Smuzhiyun u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
710*4882a593Smuzhiyun if (aha1542_out(sh->io_port, offcmd, 2))
711*4882a593Smuzhiyun goto fail;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun if (dma_speed_hw(dma_speed) != 0xff) {
715*4882a593Smuzhiyun u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
718*4882a593Smuzhiyun if (aha1542_out(sh->io_port, dmacmd, 2))
719*4882a593Smuzhiyun goto fail;
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
722*4882a593Smuzhiyun return;
723*4882a593Smuzhiyun fail:
724*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
725*4882a593Smuzhiyun aha1542_intr_reset(sh->io_port);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun /* return non-zero on detection */
aha1542_hw_init(struct scsi_host_template * tpnt,struct device * pdev,int indx)729*4882a593Smuzhiyun static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun unsigned int base_io = io[indx];
732*4882a593Smuzhiyun struct Scsi_Host *sh;
733*4882a593Smuzhiyun struct aha1542_hostdata *aha1542;
734*4882a593Smuzhiyun char dma_info[] = "no DMA";
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun if (base_io == 0)
737*4882a593Smuzhiyun return NULL;
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
740*4882a593Smuzhiyun return NULL;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
743*4882a593Smuzhiyun if (!sh)
744*4882a593Smuzhiyun goto release;
745*4882a593Smuzhiyun aha1542 = shost_priv(sh);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun sh->unique_id = base_io;
748*4882a593Smuzhiyun sh->io_port = base_io;
749*4882a593Smuzhiyun sh->n_io_port = AHA1542_REGION_SIZE;
750*4882a593Smuzhiyun aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
751*4882a593Smuzhiyun aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (!aha1542_test_port(sh))
754*4882a593Smuzhiyun goto unregister;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
757*4882a593Smuzhiyun if (aha1542_query(sh))
758*4882a593Smuzhiyun goto unregister;
759*4882a593Smuzhiyun if (aha1542_getconfig(sh) == -1)
760*4882a593Smuzhiyun goto unregister;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun if (sh->dma_channel != 0xFF)
763*4882a593Smuzhiyun snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
764*4882a593Smuzhiyun shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
765*4882a593Smuzhiyun sh->this_id, base_io, sh->irq, dma_info);
766*4882a593Smuzhiyun if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
767*4882a593Smuzhiyun shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun if (dma_set_mask_and_coherent(pdev, DMA_BIT_MASK(24)) < 0)
770*4882a593Smuzhiyun goto unregister;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun aha1542->mb = dma_alloc_coherent(pdev,
773*4882a593Smuzhiyun AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
774*4882a593Smuzhiyun &aha1542->mb_handle, GFP_KERNEL);
775*4882a593Smuzhiyun if (!aha1542->mb)
776*4882a593Smuzhiyun goto unregister;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun aha1542->ccb = dma_alloc_coherent(pdev,
779*4882a593Smuzhiyun AHA1542_MAILBOXES * sizeof(struct ccb),
780*4882a593Smuzhiyun &aha1542->ccb_handle, GFP_KERNEL);
781*4882a593Smuzhiyun if (!aha1542->ccb)
782*4882a593Smuzhiyun goto free_mb;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun setup_mailboxes(sh);
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
787*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
788*4882a593Smuzhiyun goto free_ccb;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun if (sh->dma_channel != 0xFF) {
791*4882a593Smuzhiyun if (request_dma(sh->dma_channel, "aha1542")) {
792*4882a593Smuzhiyun shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
793*4882a593Smuzhiyun goto free_irq;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
796*4882a593Smuzhiyun set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
797*4882a593Smuzhiyun enable_dma(sh->dma_channel);
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun if (scsi_add_host(sh, pdev))
802*4882a593Smuzhiyun goto free_dma;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun scsi_scan_host(sh);
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun return sh;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun free_dma:
809*4882a593Smuzhiyun if (sh->dma_channel != 0xff)
810*4882a593Smuzhiyun free_dma(sh->dma_channel);
811*4882a593Smuzhiyun free_irq:
812*4882a593Smuzhiyun free_irq(sh->irq, sh);
813*4882a593Smuzhiyun free_ccb:
814*4882a593Smuzhiyun dma_free_coherent(pdev, AHA1542_MAILBOXES * sizeof(struct ccb),
815*4882a593Smuzhiyun aha1542->ccb, aha1542->ccb_handle);
816*4882a593Smuzhiyun free_mb:
817*4882a593Smuzhiyun dma_free_coherent(pdev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
818*4882a593Smuzhiyun aha1542->mb, aha1542->mb_handle);
819*4882a593Smuzhiyun unregister:
820*4882a593Smuzhiyun scsi_host_put(sh);
821*4882a593Smuzhiyun release:
822*4882a593Smuzhiyun release_region(base_io, AHA1542_REGION_SIZE);
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun return NULL;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun
aha1542_release(struct Scsi_Host * sh)827*4882a593Smuzhiyun static int aha1542_release(struct Scsi_Host *sh)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
830*4882a593Smuzhiyun struct device *dev = sh->dma_dev;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun scsi_remove_host(sh);
833*4882a593Smuzhiyun if (sh->dma_channel != 0xff)
834*4882a593Smuzhiyun free_dma(sh->dma_channel);
835*4882a593Smuzhiyun dma_free_coherent(dev, AHA1542_MAILBOXES * sizeof(struct ccb),
836*4882a593Smuzhiyun aha1542->ccb, aha1542->ccb_handle);
837*4882a593Smuzhiyun dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox),
838*4882a593Smuzhiyun aha1542->mb, aha1542->mb_handle);
839*4882a593Smuzhiyun if (sh->irq)
840*4882a593Smuzhiyun free_irq(sh->irq, sh);
841*4882a593Smuzhiyun if (sh->io_port && sh->n_io_port)
842*4882a593Smuzhiyun release_region(sh->io_port, sh->n_io_port);
843*4882a593Smuzhiyun scsi_host_put(sh);
844*4882a593Smuzhiyun return 0;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun /*
849*4882a593Smuzhiyun * This is a device reset. This is handled by sending a special command
850*4882a593Smuzhiyun * to the device.
851*4882a593Smuzhiyun */
aha1542_dev_reset(struct scsi_cmnd * cmd)852*4882a593Smuzhiyun static int aha1542_dev_reset(struct scsi_cmnd *cmd)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun struct Scsi_Host *sh = cmd->device->host;
855*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
856*4882a593Smuzhiyun unsigned long flags;
857*4882a593Smuzhiyun struct mailbox *mb = aha1542->mb;
858*4882a593Smuzhiyun u8 target = cmd->device->id;
859*4882a593Smuzhiyun u8 lun = cmd->device->lun;
860*4882a593Smuzhiyun int mbo;
861*4882a593Smuzhiyun struct ccb *ccb = aha1542->ccb;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun spin_lock_irqsave(sh->host_lock, flags);
864*4882a593Smuzhiyun mbo = aha1542->aha1542_last_mbo_used + 1;
865*4882a593Smuzhiyun if (mbo >= AHA1542_MAILBOXES)
866*4882a593Smuzhiyun mbo = 0;
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun do {
869*4882a593Smuzhiyun if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
870*4882a593Smuzhiyun break;
871*4882a593Smuzhiyun mbo++;
872*4882a593Smuzhiyun if (mbo >= AHA1542_MAILBOXES)
873*4882a593Smuzhiyun mbo = 0;
874*4882a593Smuzhiyun } while (mbo != aha1542->aha1542_last_mbo_used);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun if (mb[mbo].status || aha1542->int_cmds[mbo])
877*4882a593Smuzhiyun panic("Unable to find empty mailbox for aha1542.\n");
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun aha1542->int_cmds[mbo] = cmd; /* This will effectively
880*4882a593Smuzhiyun prevent someone else from
881*4882a593Smuzhiyun screwing with this cdb. */
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun aha1542->aha1542_last_mbo_used = mbo;
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun /* This gets trashed for some reason */
886*4882a593Smuzhiyun any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(*ccb));
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun memset(&ccb[mbo], 0, sizeof(struct ccb));
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
895*4882a593Smuzhiyun ccb[mbo].commlinkid = 0;
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun /*
898*4882a593Smuzhiyun * Now tell the 1542 to flush all pending commands for this
899*4882a593Smuzhiyun * target
900*4882a593Smuzhiyun */
901*4882a593Smuzhiyun aha1542_outb(sh->io_port, CMD_START_SCSI);
902*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun scmd_printk(KERN_WARNING, cmd,
905*4882a593Smuzhiyun "Trying device reset for target\n");
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun return SUCCESS;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun
aha1542_reset(struct scsi_cmnd * cmd,u8 reset_cmd)910*4882a593Smuzhiyun static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun struct Scsi_Host *sh = cmd->device->host;
913*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sh);
914*4882a593Smuzhiyun unsigned long flags;
915*4882a593Smuzhiyun int i;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun spin_lock_irqsave(sh->host_lock, flags);
918*4882a593Smuzhiyun /*
919*4882a593Smuzhiyun * This does a scsi reset for all devices on the bus.
920*4882a593Smuzhiyun * In principle, we could also reset the 1542 - should
921*4882a593Smuzhiyun * we do this? Try this first, and we can add that later
922*4882a593Smuzhiyun * if it turns out to be useful.
923*4882a593Smuzhiyun */
924*4882a593Smuzhiyun outb(reset_cmd, CONTROL(cmd->device->host->io_port));
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun if (!wait_mask(STATUS(cmd->device->host->io_port),
927*4882a593Smuzhiyun STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
928*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
929*4882a593Smuzhiyun return FAILED;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun /*
933*4882a593Smuzhiyun * We need to do this too before the 1542 can interact with
934*4882a593Smuzhiyun * us again after host reset.
935*4882a593Smuzhiyun */
936*4882a593Smuzhiyun if (reset_cmd & HRST)
937*4882a593Smuzhiyun setup_mailboxes(cmd->device->host);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun /*
940*4882a593Smuzhiyun * Now try to pick up the pieces. For all pending commands,
941*4882a593Smuzhiyun * free any internal data structures, and basically clear things
942*4882a593Smuzhiyun * out. We do not try and restart any commands or anything -
943*4882a593Smuzhiyun * the strategy handler takes care of that crap.
944*4882a593Smuzhiyun */
945*4882a593Smuzhiyun shost_printk(KERN_WARNING, cmd->device->host, "Sent BUS RESET to scsi host %d\n", cmd->device->host->host_no);
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun for (i = 0; i < AHA1542_MAILBOXES; i++) {
948*4882a593Smuzhiyun if (aha1542->int_cmds[i] != NULL) {
949*4882a593Smuzhiyun struct scsi_cmnd *tmp_cmd;
950*4882a593Smuzhiyun tmp_cmd = aha1542->int_cmds[i];
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (tmp_cmd->device->soft_reset) {
953*4882a593Smuzhiyun /*
954*4882a593Smuzhiyun * If this device implements the soft reset option,
955*4882a593Smuzhiyun * then it is still holding onto the command, and
956*4882a593Smuzhiyun * may yet complete it. In this case, we don't
957*4882a593Smuzhiyun * flush the data.
958*4882a593Smuzhiyun */
959*4882a593Smuzhiyun continue;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun aha1542_free_cmd(tmp_cmd);
962*4882a593Smuzhiyun aha1542->int_cmds[i] = NULL;
963*4882a593Smuzhiyun aha1542->mb[i].status = 0;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun spin_unlock_irqrestore(sh->host_lock, flags);
968*4882a593Smuzhiyun return SUCCESS;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
aha1542_bus_reset(struct scsi_cmnd * cmd)971*4882a593Smuzhiyun static int aha1542_bus_reset(struct scsi_cmnd *cmd)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun return aha1542_reset(cmd, SCRST);
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
aha1542_host_reset(struct scsi_cmnd * cmd)976*4882a593Smuzhiyun static int aha1542_host_reset(struct scsi_cmnd *cmd)
977*4882a593Smuzhiyun {
978*4882a593Smuzhiyun return aha1542_reset(cmd, HRST | SCRST);
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun
aha1542_biosparam(struct scsi_device * sdev,struct block_device * bdev,sector_t capacity,int geom[])981*4882a593Smuzhiyun static int aha1542_biosparam(struct scsi_device *sdev,
982*4882a593Smuzhiyun struct block_device *bdev, sector_t capacity, int geom[])
983*4882a593Smuzhiyun {
984*4882a593Smuzhiyun struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun if (capacity >= 0x200000 &&
987*4882a593Smuzhiyun aha1542->bios_translation == BIOS_TRANSLATION_25563) {
988*4882a593Smuzhiyun /* Please verify that this is the same as what DOS returns */
989*4882a593Smuzhiyun geom[0] = 255; /* heads */
990*4882a593Smuzhiyun geom[1] = 63; /* sectors */
991*4882a593Smuzhiyun } else {
992*4882a593Smuzhiyun geom[0] = 64; /* heads */
993*4882a593Smuzhiyun geom[1] = 32; /* sectors */
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun return 0;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun static struct scsi_host_template driver_template = {
1002*4882a593Smuzhiyun .module = THIS_MODULE,
1003*4882a593Smuzhiyun .proc_name = "aha1542",
1004*4882a593Smuzhiyun .name = "Adaptec 1542",
1005*4882a593Smuzhiyun .cmd_size = sizeof(struct aha1542_cmd),
1006*4882a593Smuzhiyun .queuecommand = aha1542_queuecommand,
1007*4882a593Smuzhiyun .eh_device_reset_handler= aha1542_dev_reset,
1008*4882a593Smuzhiyun .eh_bus_reset_handler = aha1542_bus_reset,
1009*4882a593Smuzhiyun .eh_host_reset_handler = aha1542_host_reset,
1010*4882a593Smuzhiyun .bios_param = aha1542_biosparam,
1011*4882a593Smuzhiyun .can_queue = AHA1542_MAILBOXES,
1012*4882a593Smuzhiyun .this_id = 7,
1013*4882a593Smuzhiyun .sg_tablesize = 16,
1014*4882a593Smuzhiyun .unchecked_isa_dma = 1,
1015*4882a593Smuzhiyun };
1016*4882a593Smuzhiyun
aha1542_isa_match(struct device * pdev,unsigned int ndev)1017*4882a593Smuzhiyun static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun if (!sh)
1022*4882a593Smuzhiyun return 0;
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun dev_set_drvdata(pdev, sh);
1025*4882a593Smuzhiyun return 1;
1026*4882a593Smuzhiyun }
1027*4882a593Smuzhiyun
aha1542_isa_remove(struct device * pdev,unsigned int ndev)1028*4882a593Smuzhiyun static int aha1542_isa_remove(struct device *pdev,
1029*4882a593Smuzhiyun unsigned int ndev)
1030*4882a593Smuzhiyun {
1031*4882a593Smuzhiyun aha1542_release(dev_get_drvdata(pdev));
1032*4882a593Smuzhiyun dev_set_drvdata(pdev, NULL);
1033*4882a593Smuzhiyun return 0;
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun static struct isa_driver aha1542_isa_driver = {
1037*4882a593Smuzhiyun .match = aha1542_isa_match,
1038*4882a593Smuzhiyun .remove = aha1542_isa_remove,
1039*4882a593Smuzhiyun .driver = {
1040*4882a593Smuzhiyun .name = "aha1542"
1041*4882a593Smuzhiyun },
1042*4882a593Smuzhiyun };
1043*4882a593Smuzhiyun static int isa_registered;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun #ifdef CONFIG_PNP
1046*4882a593Smuzhiyun static const struct pnp_device_id aha1542_pnp_ids[] = {
1047*4882a593Smuzhiyun { .id = "ADP1542" },
1048*4882a593Smuzhiyun { .id = "" }
1049*4882a593Smuzhiyun };
1050*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
1051*4882a593Smuzhiyun
aha1542_pnp_probe(struct pnp_dev * pdev,const struct pnp_device_id * id)1052*4882a593Smuzhiyun static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun int indx;
1055*4882a593Smuzhiyun struct Scsi_Host *sh;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1058*4882a593Smuzhiyun if (io[indx])
1059*4882a593Smuzhiyun continue;
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun if (pnp_activate_dev(pdev) < 0)
1062*4882a593Smuzhiyun continue;
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun io[indx] = pnp_port_start(pdev, 0);
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun /* The card can be queried for its DMA, we have
1067*4882a593Smuzhiyun the DMA set up that is enough */
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1073*4882a593Smuzhiyun if (!sh)
1074*4882a593Smuzhiyun return -ENODEV;
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun pnp_set_drvdata(pdev, sh);
1077*4882a593Smuzhiyun return 0;
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun
aha1542_pnp_remove(struct pnp_dev * pdev)1080*4882a593Smuzhiyun static void aha1542_pnp_remove(struct pnp_dev *pdev)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun aha1542_release(pnp_get_drvdata(pdev));
1083*4882a593Smuzhiyun pnp_set_drvdata(pdev, NULL);
1084*4882a593Smuzhiyun }
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun static struct pnp_driver aha1542_pnp_driver = {
1087*4882a593Smuzhiyun .name = "aha1542",
1088*4882a593Smuzhiyun .id_table = aha1542_pnp_ids,
1089*4882a593Smuzhiyun .probe = aha1542_pnp_probe,
1090*4882a593Smuzhiyun .remove = aha1542_pnp_remove,
1091*4882a593Smuzhiyun };
1092*4882a593Smuzhiyun static int pnp_registered;
1093*4882a593Smuzhiyun #endif /* CONFIG_PNP */
1094*4882a593Smuzhiyun
aha1542_init(void)1095*4882a593Smuzhiyun static int __init aha1542_init(void)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun int ret = 0;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun #ifdef CONFIG_PNP
1100*4882a593Smuzhiyun if (isapnp) {
1101*4882a593Smuzhiyun ret = pnp_register_driver(&aha1542_pnp_driver);
1102*4882a593Smuzhiyun if (!ret)
1103*4882a593Smuzhiyun pnp_registered = 1;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun #endif
1106*4882a593Smuzhiyun ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1107*4882a593Smuzhiyun if (!ret)
1108*4882a593Smuzhiyun isa_registered = 1;
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun #ifdef CONFIG_PNP
1111*4882a593Smuzhiyun if (pnp_registered)
1112*4882a593Smuzhiyun ret = 0;
1113*4882a593Smuzhiyun #endif
1114*4882a593Smuzhiyun if (isa_registered)
1115*4882a593Smuzhiyun ret = 0;
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun return ret;
1118*4882a593Smuzhiyun }
1119*4882a593Smuzhiyun
aha1542_exit(void)1120*4882a593Smuzhiyun static void __exit aha1542_exit(void)
1121*4882a593Smuzhiyun {
1122*4882a593Smuzhiyun #ifdef CONFIG_PNP
1123*4882a593Smuzhiyun if (pnp_registered)
1124*4882a593Smuzhiyun pnp_unregister_driver(&aha1542_pnp_driver);
1125*4882a593Smuzhiyun #endif
1126*4882a593Smuzhiyun if (isa_registered)
1127*4882a593Smuzhiyun isa_unregister_driver(&aha1542_isa_driver);
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun module_init(aha1542_init);
1131*4882a593Smuzhiyun module_exit(aha1542_exit);
1132