xref: /OK3568_Linux_fs/kernel/drivers/scsi/aha1542.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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