xref: /openbmc/linux/drivers/scsi/aacraid/src.c (revision 71552505)
1e8b12f0fSMahesh Rajashekhara /*
2e8b12f0fSMahesh Rajashekhara  *	Adaptec AAC series RAID controller driver
3e8b12f0fSMahesh Rajashekhara  *	(c) Copyright 2001 Red Hat Inc.
4e8b12f0fSMahesh Rajashekhara  *
5e8b12f0fSMahesh Rajashekhara  * based on the old aacraid driver that is..
6e8b12f0fSMahesh Rajashekhara  * Adaptec aacraid device driver for Linux.
7e8b12f0fSMahesh Rajashekhara  *
8e8b12f0fSMahesh Rajashekhara  * Copyright (c) 2000-2010 Adaptec, Inc.
9e8b12f0fSMahesh Rajashekhara  *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
10e8b12f0fSMahesh Rajashekhara  *
11e8b12f0fSMahesh Rajashekhara  * This program is free software; you can redistribute it and/or modify
12e8b12f0fSMahesh Rajashekhara  * it under the terms of the GNU General Public License as published by
13e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation; either version 2, or (at your option)
14e8b12f0fSMahesh Rajashekhara  * any later version.
15e8b12f0fSMahesh Rajashekhara  *
16e8b12f0fSMahesh Rajashekhara  * This program is distributed in the hope that it will be useful,
17e8b12f0fSMahesh Rajashekhara  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18e8b12f0fSMahesh Rajashekhara  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19e8b12f0fSMahesh Rajashekhara  * GNU General Public License for more details.
20e8b12f0fSMahesh Rajashekhara  *
21e8b12f0fSMahesh Rajashekhara  * You should have received a copy of the GNU General Public License
22e8b12f0fSMahesh Rajashekhara  * along with this program; see the file COPYING.  If not, write to
23e8b12f0fSMahesh Rajashekhara  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24e8b12f0fSMahesh Rajashekhara  *
25e8b12f0fSMahesh Rajashekhara  * Module Name:
26e8b12f0fSMahesh Rajashekhara  *  src.c
27e8b12f0fSMahesh Rajashekhara  *
28e8b12f0fSMahesh Rajashekhara  * Abstract: Hardware Device Interface for PMC SRC based controllers
29e8b12f0fSMahesh Rajashekhara  *
30e8b12f0fSMahesh Rajashekhara  */
31e8b12f0fSMahesh Rajashekhara 
32e8b12f0fSMahesh Rajashekhara #include <linux/kernel.h>
33e8b12f0fSMahesh Rajashekhara #include <linux/init.h>
34e8b12f0fSMahesh Rajashekhara #include <linux/types.h>
35e8b12f0fSMahesh Rajashekhara #include <linux/pci.h>
36e8b12f0fSMahesh Rajashekhara #include <linux/spinlock.h>
37e8b12f0fSMahesh Rajashekhara #include <linux/slab.h>
38e8b12f0fSMahesh Rajashekhara #include <linux/blkdev.h>
39e8b12f0fSMahesh Rajashekhara #include <linux/delay.h>
40e8b12f0fSMahesh Rajashekhara #include <linux/completion.h>
41e8b12f0fSMahesh Rajashekhara #include <linux/time.h>
42e8b12f0fSMahesh Rajashekhara #include <linux/interrupt.h>
43e8b12f0fSMahesh Rajashekhara #include <scsi/scsi_host.h>
44e8b12f0fSMahesh Rajashekhara 
45e8b12f0fSMahesh Rajashekhara #include "aacraid.h"
46e8b12f0fSMahesh Rajashekhara 
47e8b12f0fSMahesh Rajashekhara static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
48e8b12f0fSMahesh Rajashekhara {
49e8b12f0fSMahesh Rajashekhara 	struct aac_dev *dev = dev_id;
50e8b12f0fSMahesh Rajashekhara 	unsigned long bellbits, bellbits_shifted;
51e8b12f0fSMahesh Rajashekhara 	int our_interrupt = 0;
52e8b12f0fSMahesh Rajashekhara 	int isFastResponse;
53e8b12f0fSMahesh Rajashekhara 	u32 index, handle;
54e8b12f0fSMahesh Rajashekhara 
55e8b12f0fSMahesh Rajashekhara 	bellbits = src_readl(dev, MUnit.ODR_R);
56e8b12f0fSMahesh Rajashekhara 	if (bellbits & PmDoorBellResponseSent) {
57e8b12f0fSMahesh Rajashekhara 		bellbits = PmDoorBellResponseSent;
58e8b12f0fSMahesh Rajashekhara 		/* handle async. status */
59e8b12f0fSMahesh Rajashekhara 		our_interrupt = 1;
60e8b12f0fSMahesh Rajashekhara 		index = dev->host_rrq_idx;
61e8b12f0fSMahesh Rajashekhara 		if (dev->host_rrq[index] == 0) {
62e8b12f0fSMahesh Rajashekhara 			u32 old_index = index;
63e8b12f0fSMahesh Rajashekhara 			/* adjust index */
64e8b12f0fSMahesh Rajashekhara 			do {
65e8b12f0fSMahesh Rajashekhara 				index++;
66e8b12f0fSMahesh Rajashekhara 				if (index == dev->scsi_host_ptr->can_queue +
67e8b12f0fSMahesh Rajashekhara 							AAC_NUM_MGT_FIB)
68e8b12f0fSMahesh Rajashekhara 					index = 0;
69e8b12f0fSMahesh Rajashekhara 				if (dev->host_rrq[index] != 0)
70e8b12f0fSMahesh Rajashekhara 					break;
71e8b12f0fSMahesh Rajashekhara 			} while (index != old_index);
72e8b12f0fSMahesh Rajashekhara 			dev->host_rrq_idx = index;
73e8b12f0fSMahesh Rajashekhara 		}
74e8b12f0fSMahesh Rajashekhara 		for (;;) {
75e8b12f0fSMahesh Rajashekhara 			isFastResponse = 0;
76e8b12f0fSMahesh Rajashekhara 			/* remove toggle bit (31) */
77e8b12f0fSMahesh Rajashekhara 			handle = (dev->host_rrq[index] & 0x7fffffff);
78e8b12f0fSMahesh Rajashekhara 			/* check fast response bit (30) */
79e8b12f0fSMahesh Rajashekhara 			if (handle & 0x40000000)
80e8b12f0fSMahesh Rajashekhara 				isFastResponse = 1;
81e8b12f0fSMahesh Rajashekhara 			handle &= 0x0000ffff;
82e8b12f0fSMahesh Rajashekhara 			if (handle == 0)
83e8b12f0fSMahesh Rajashekhara 				break;
84e8b12f0fSMahesh Rajashekhara 
85e8b12f0fSMahesh Rajashekhara 			aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
86e8b12f0fSMahesh Rajashekhara 
87e8b12f0fSMahesh Rajashekhara 			dev->host_rrq[index++] = 0;
88e8b12f0fSMahesh Rajashekhara 			if (index == dev->scsi_host_ptr->can_queue +
89e8b12f0fSMahesh Rajashekhara 						AAC_NUM_MGT_FIB)
90e8b12f0fSMahesh Rajashekhara 				index = 0;
91e8b12f0fSMahesh Rajashekhara 			dev->host_rrq_idx = index;
92e8b12f0fSMahesh Rajashekhara 		}
93e8b12f0fSMahesh Rajashekhara 	} else {
94e8b12f0fSMahesh Rajashekhara 		bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
95e8b12f0fSMahesh Rajashekhara 		if (bellbits_shifted & DoorBellAifPending) {
96e8b12f0fSMahesh Rajashekhara 			our_interrupt = 1;
97e8b12f0fSMahesh Rajashekhara 			/* handle AIF */
98e8b12f0fSMahesh Rajashekhara 			aac_intr_normal(dev, 0, 2, 0, NULL);
9911604612SMahesh Rajashekhara 		} else if (bellbits_shifted & OUTBOUNDDOORBELL_0) {
10011604612SMahesh Rajashekhara 			unsigned long sflags;
10111604612SMahesh Rajashekhara 			struct list_head *entry;
10211604612SMahesh Rajashekhara 			int send_it = 0;
10311604612SMahesh Rajashekhara 
10411604612SMahesh Rajashekhara 			if (dev->sync_fib) {
10511604612SMahesh Rajashekhara 				our_interrupt = 1;
10611604612SMahesh Rajashekhara 				if (dev->sync_fib->callback)
10711604612SMahesh Rajashekhara 					dev->sync_fib->callback(dev->sync_fib->callback_data,
10811604612SMahesh Rajashekhara 						dev->sync_fib);
10911604612SMahesh Rajashekhara 				spin_lock_irqsave(&dev->sync_fib->event_lock, sflags);
11011604612SMahesh Rajashekhara 				if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) {
11111604612SMahesh Rajashekhara 					dev->management_fib_count--;
11211604612SMahesh Rajashekhara 					up(&dev->sync_fib->event_wait);
11311604612SMahesh Rajashekhara 				}
11411604612SMahesh Rajashekhara 				spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags);
11511604612SMahesh Rajashekhara 				spin_lock_irqsave(&dev->sync_lock, sflags);
11611604612SMahesh Rajashekhara 				if (!list_empty(&dev->sync_fib_list)) {
11711604612SMahesh Rajashekhara 					entry = dev->sync_fib_list.next;
11811604612SMahesh Rajashekhara 					dev->sync_fib = list_entry(entry, struct fib, fiblink);
11911604612SMahesh Rajashekhara 					list_del(entry);
12011604612SMahesh Rajashekhara 					send_it = 1;
12111604612SMahesh Rajashekhara 				} else {
12211604612SMahesh Rajashekhara 					dev->sync_fib = NULL;
12311604612SMahesh Rajashekhara 				}
12411604612SMahesh Rajashekhara 				spin_unlock_irqrestore(&dev->sync_lock, sflags);
12511604612SMahesh Rajashekhara 				if (send_it) {
12611604612SMahesh Rajashekhara 					aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
12711604612SMahesh Rajashekhara 						(u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0,
12811604612SMahesh Rajashekhara 						NULL, NULL, NULL, NULL, NULL);
12911604612SMahesh Rajashekhara 				}
13011604612SMahesh Rajashekhara 			}
131e8b12f0fSMahesh Rajashekhara 		}
132e8b12f0fSMahesh Rajashekhara 	}
133e8b12f0fSMahesh Rajashekhara 
134e8b12f0fSMahesh Rajashekhara 	if (our_interrupt) {
135e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C, bellbits);
136e8b12f0fSMahesh Rajashekhara 		return IRQ_HANDLED;
137e8b12f0fSMahesh Rajashekhara 	}
138e8b12f0fSMahesh Rajashekhara 	return IRQ_NONE;
139e8b12f0fSMahesh Rajashekhara }
140e8b12f0fSMahesh Rajashekhara 
141e8b12f0fSMahesh Rajashekhara /**
142e8b12f0fSMahesh Rajashekhara  *	aac_src_disable_interrupt	-	Disable interrupts
143e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
144e8b12f0fSMahesh Rajashekhara  */
145e8b12f0fSMahesh Rajashekhara 
146e8b12f0fSMahesh Rajashekhara static void aac_src_disable_interrupt(struct aac_dev *dev)
147e8b12f0fSMahesh Rajashekhara {
148e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
149e8b12f0fSMahesh Rajashekhara }
150e8b12f0fSMahesh Rajashekhara 
151e8b12f0fSMahesh Rajashekhara /**
152e8b12f0fSMahesh Rajashekhara  *	aac_src_enable_interrupt_message	-	Enable interrupts
153e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
154e8b12f0fSMahesh Rajashekhara  */
155e8b12f0fSMahesh Rajashekhara 
156e8b12f0fSMahesh Rajashekhara static void aac_src_enable_interrupt_message(struct aac_dev *dev)
157e8b12f0fSMahesh Rajashekhara {
158e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8);
159e8b12f0fSMahesh Rajashekhara }
160e8b12f0fSMahesh Rajashekhara 
161e8b12f0fSMahesh Rajashekhara /**
162e8b12f0fSMahesh Rajashekhara  *	src_sync_cmd	-	send a command and wait
163e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
164e8b12f0fSMahesh Rajashekhara  *	@command: Command to execute
165e8b12f0fSMahesh Rajashekhara  *	@p1: first parameter
166e8b12f0fSMahesh Rajashekhara  *	@ret: adapter status
167e8b12f0fSMahesh Rajashekhara  *
168e8b12f0fSMahesh Rajashekhara  *	This routine will send a synchronous command to the adapter and wait
169e8b12f0fSMahesh Rajashekhara  *	for its	completion.
170e8b12f0fSMahesh Rajashekhara  */
171e8b12f0fSMahesh Rajashekhara 
172e8b12f0fSMahesh Rajashekhara static int src_sync_cmd(struct aac_dev *dev, u32 command,
173e8b12f0fSMahesh Rajashekhara 	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
174e8b12f0fSMahesh Rajashekhara 	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
175e8b12f0fSMahesh Rajashekhara {
176e8b12f0fSMahesh Rajashekhara 	unsigned long start;
177e8b12f0fSMahesh Rajashekhara 	int ok;
178e8b12f0fSMahesh Rajashekhara 
179e8b12f0fSMahesh Rajashekhara 	/*
180e8b12f0fSMahesh Rajashekhara 	 *	Write the command into Mailbox 0
181e8b12f0fSMahesh Rajashekhara 	 */
182e8b12f0fSMahesh Rajashekhara 	writel(command, &dev->IndexRegs->Mailbox[0]);
183e8b12f0fSMahesh Rajashekhara 	/*
184e8b12f0fSMahesh Rajashekhara 	 *	Write the parameters into Mailboxes 1 - 6
185e8b12f0fSMahesh Rajashekhara 	 */
186e8b12f0fSMahesh Rajashekhara 	writel(p1, &dev->IndexRegs->Mailbox[1]);
187e8b12f0fSMahesh Rajashekhara 	writel(p2, &dev->IndexRegs->Mailbox[2]);
188e8b12f0fSMahesh Rajashekhara 	writel(p3, &dev->IndexRegs->Mailbox[3]);
189e8b12f0fSMahesh Rajashekhara 	writel(p4, &dev->IndexRegs->Mailbox[4]);
190e8b12f0fSMahesh Rajashekhara 
191e8b12f0fSMahesh Rajashekhara 	/*
192e8b12f0fSMahesh Rajashekhara 	 *	Clear the synch command doorbell to start on a clean slate.
193e8b12f0fSMahesh Rajashekhara 	 */
194e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
195e8b12f0fSMahesh Rajashekhara 
196e8b12f0fSMahesh Rajashekhara 	/*
197e8b12f0fSMahesh Rajashekhara 	 *	Disable doorbell interrupts
198e8b12f0fSMahesh Rajashekhara 	 */
199e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
200e8b12f0fSMahesh Rajashekhara 
201e8b12f0fSMahesh Rajashekhara 	/*
202e8b12f0fSMahesh Rajashekhara 	 *	Force the completion of the mask register write before issuing
203e8b12f0fSMahesh Rajashekhara 	 *	the interrupt.
204e8b12f0fSMahesh Rajashekhara 	 */
205e8b12f0fSMahesh Rajashekhara 	src_readl(dev, MUnit.OIMR);
206e8b12f0fSMahesh Rajashekhara 
207e8b12f0fSMahesh Rajashekhara 	/*
208e8b12f0fSMahesh Rajashekhara 	 *	Signal that there is a new synch command
209e8b12f0fSMahesh Rajashekhara 	 */
210e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
211e8b12f0fSMahesh Rajashekhara 
21211604612SMahesh Rajashekhara 	if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) {
213e8b12f0fSMahesh Rajashekhara 		ok = 0;
214e8b12f0fSMahesh Rajashekhara 		start = jiffies;
215e8b12f0fSMahesh Rajashekhara 
216e8b12f0fSMahesh Rajashekhara 		/*
21711604612SMahesh Rajashekhara 		 *	Wait up to 5 minutes
218e8b12f0fSMahesh Rajashekhara 		 */
21911604612SMahesh Rajashekhara 		while (time_before(jiffies, start+300*HZ)) {
22011604612SMahesh Rajashekhara 			udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
22111604612SMahesh Rajashekhara 			/*
22211604612SMahesh Rajashekhara 			 *	Mon960 will set doorbell0 bit when it has completed the command.
223e8b12f0fSMahesh Rajashekhara 			 */
224e8b12f0fSMahesh Rajashekhara 			if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) {
22511604612SMahesh Rajashekhara 				/*
22611604612SMahesh Rajashekhara 				 *	Clear the doorbell.
22711604612SMahesh Rajashekhara 				 */
22811604612SMahesh Rajashekhara 				src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
229e8b12f0fSMahesh Rajashekhara 				ok = 1;
230e8b12f0fSMahesh Rajashekhara 				break;
231e8b12f0fSMahesh Rajashekhara 			}
23211604612SMahesh Rajashekhara 			/*
23311604612SMahesh Rajashekhara 			 *	Yield the processor in case we are slow
23411604612SMahesh Rajashekhara 			 */
235e8b12f0fSMahesh Rajashekhara 			msleep(1);
236e8b12f0fSMahesh Rajashekhara 		}
237e8b12f0fSMahesh Rajashekhara 		if (unlikely(ok != 1)) {
23811604612SMahesh Rajashekhara 			/*
23911604612SMahesh Rajashekhara 			 *	Restore interrupt mask even though we timed out
24011604612SMahesh Rajashekhara 			 */
241e8b12f0fSMahesh Rajashekhara 			aac_adapter_enable_int(dev);
242e8b12f0fSMahesh Rajashekhara 			return -ETIMEDOUT;
243e8b12f0fSMahesh Rajashekhara 		}
24411604612SMahesh Rajashekhara 		/*
24511604612SMahesh Rajashekhara 		 *	Pull the synch status from Mailbox 0.
24611604612SMahesh Rajashekhara 		 */
247e8b12f0fSMahesh Rajashekhara 		if (status)
248e8b12f0fSMahesh Rajashekhara 			*status = readl(&dev->IndexRegs->Mailbox[0]);
249e8b12f0fSMahesh Rajashekhara 		if (r1)
250e8b12f0fSMahesh Rajashekhara 			*r1 = readl(&dev->IndexRegs->Mailbox[1]);
251e8b12f0fSMahesh Rajashekhara 		if (r2)
252e8b12f0fSMahesh Rajashekhara 			*r2 = readl(&dev->IndexRegs->Mailbox[2]);
253e8b12f0fSMahesh Rajashekhara 		if (r3)
254e8b12f0fSMahesh Rajashekhara 			*r3 = readl(&dev->IndexRegs->Mailbox[3]);
255e8b12f0fSMahesh Rajashekhara 		if (r4)
256e8b12f0fSMahesh Rajashekhara 			*r4 = readl(&dev->IndexRegs->Mailbox[4]);
257e8b12f0fSMahesh Rajashekhara 
25811604612SMahesh Rajashekhara 		/*
25911604612SMahesh Rajashekhara 		 *	Clear the synch command doorbell.
26011604612SMahesh Rajashekhara 		 */
261e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
26211604612SMahesh Rajashekhara 	}
263e8b12f0fSMahesh Rajashekhara 
26411604612SMahesh Rajashekhara 	/*
26511604612SMahesh Rajashekhara 	 *	Restore interrupt mask
26611604612SMahesh Rajashekhara 	 */
267e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
268e8b12f0fSMahesh Rajashekhara 	return 0;
269e8b12f0fSMahesh Rajashekhara }
270e8b12f0fSMahesh Rajashekhara 
271e8b12f0fSMahesh Rajashekhara /**
272e8b12f0fSMahesh Rajashekhara  *	aac_src_interrupt_adapter	-	interrupt adapter
273e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
274e8b12f0fSMahesh Rajashekhara  *
275e8b12f0fSMahesh Rajashekhara  *	Send an interrupt to the i960 and breakpoint it.
276e8b12f0fSMahesh Rajashekhara  */
277e8b12f0fSMahesh Rajashekhara 
278e8b12f0fSMahesh Rajashekhara static void aac_src_interrupt_adapter(struct aac_dev *dev)
279e8b12f0fSMahesh Rajashekhara {
280e8b12f0fSMahesh Rajashekhara 	src_sync_cmd(dev, BREAKPOINT_REQUEST,
281e8b12f0fSMahesh Rajashekhara 		0, 0, 0, 0, 0, 0,
282e8b12f0fSMahesh Rajashekhara 		NULL, NULL, NULL, NULL, NULL);
283e8b12f0fSMahesh Rajashekhara }
284e8b12f0fSMahesh Rajashekhara 
285e8b12f0fSMahesh Rajashekhara /**
286e8b12f0fSMahesh Rajashekhara  *	aac_src_notify_adapter		-	send an event to the adapter
287e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
288e8b12f0fSMahesh Rajashekhara  *	@event: Event to send
289e8b12f0fSMahesh Rajashekhara  *
290e8b12f0fSMahesh Rajashekhara  *	Notify the i960 that something it probably cares about has
291e8b12f0fSMahesh Rajashekhara  *	happened.
292e8b12f0fSMahesh Rajashekhara  */
293e8b12f0fSMahesh Rajashekhara 
294e8b12f0fSMahesh Rajashekhara static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
295e8b12f0fSMahesh Rajashekhara {
296e8b12f0fSMahesh Rajashekhara 	switch (event) {
297e8b12f0fSMahesh Rajashekhara 
298e8b12f0fSMahesh Rajashekhara 	case AdapNormCmdQue:
299e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
300e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
301e8b12f0fSMahesh Rajashekhara 		break;
302e8b12f0fSMahesh Rajashekhara 	case HostNormRespNotFull:
303e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
304e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
305e8b12f0fSMahesh Rajashekhara 		break;
306e8b12f0fSMahesh Rajashekhara 	case AdapNormRespQue:
307e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
308e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
309e8b12f0fSMahesh Rajashekhara 		break;
310e8b12f0fSMahesh Rajashekhara 	case HostNormCmdNotFull:
311e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
312e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
313e8b12f0fSMahesh Rajashekhara 		break;
314e8b12f0fSMahesh Rajashekhara 	case FastIo:
315e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
316e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
317e8b12f0fSMahesh Rajashekhara 		break;
318e8b12f0fSMahesh Rajashekhara 	case AdapPrintfDone:
319e8b12f0fSMahesh Rajashekhara 		src_writel(dev, MUnit.ODR_C,
320e8b12f0fSMahesh Rajashekhara 			INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
321e8b12f0fSMahesh Rajashekhara 		break;
322e8b12f0fSMahesh Rajashekhara 	default:
323e8b12f0fSMahesh Rajashekhara 		BUG();
324e8b12f0fSMahesh Rajashekhara 		break;
325e8b12f0fSMahesh Rajashekhara 	}
326e8b12f0fSMahesh Rajashekhara }
327e8b12f0fSMahesh Rajashekhara 
328e8b12f0fSMahesh Rajashekhara /**
329e8b12f0fSMahesh Rajashekhara  *	aac_src_start_adapter		-	activate adapter
330e8b12f0fSMahesh Rajashekhara  *	@dev:	Adapter
331e8b12f0fSMahesh Rajashekhara  *
332e8b12f0fSMahesh Rajashekhara  *	Start up processing on an i960 based AAC adapter
333e8b12f0fSMahesh Rajashekhara  */
334e8b12f0fSMahesh Rajashekhara 
335e8b12f0fSMahesh Rajashekhara static void aac_src_start_adapter(struct aac_dev *dev)
336e8b12f0fSMahesh Rajashekhara {
337e8b12f0fSMahesh Rajashekhara 	struct aac_init *init;
338e8b12f0fSMahesh Rajashekhara 
339e8b12f0fSMahesh Rajashekhara 	init = dev->init;
340e8b12f0fSMahesh Rajashekhara 	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
341e8b12f0fSMahesh Rajashekhara 
342e8b12f0fSMahesh Rajashekhara 	/* We can only use a 32 bit address here */
343e8b12f0fSMahesh Rajashekhara 	src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
344e8b12f0fSMahesh Rajashekhara 	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
345e8b12f0fSMahesh Rajashekhara }
346e8b12f0fSMahesh Rajashekhara 
347e8b12f0fSMahesh Rajashekhara /**
348e8b12f0fSMahesh Rajashekhara  *	aac_src_check_health
349e8b12f0fSMahesh Rajashekhara  *	@dev: device to check if healthy
350e8b12f0fSMahesh Rajashekhara  *
351e8b12f0fSMahesh Rajashekhara  *	Will attempt to determine if the specified adapter is alive and
352e8b12f0fSMahesh Rajashekhara  *	capable of handling requests, returning 0 if alive.
353e8b12f0fSMahesh Rajashekhara  */
354e8b12f0fSMahesh Rajashekhara static int aac_src_check_health(struct aac_dev *dev)
355e8b12f0fSMahesh Rajashekhara {
356e8b12f0fSMahesh Rajashekhara 	u32 status = src_readl(dev, MUnit.OMR);
357e8b12f0fSMahesh Rajashekhara 
358e8b12f0fSMahesh Rajashekhara 	/*
359e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
360e8b12f0fSMahesh Rajashekhara 	 */
361e8b12f0fSMahesh Rajashekhara 	if (unlikely(status & SELF_TEST_FAILED))
362e8b12f0fSMahesh Rajashekhara 		return -1;
363e8b12f0fSMahesh Rajashekhara 
364e8b12f0fSMahesh Rajashekhara 	/*
365e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd.
366e8b12f0fSMahesh Rajashekhara 	 */
367e8b12f0fSMahesh Rajashekhara 	if (unlikely(status & KERNEL_PANIC))
368e8b12f0fSMahesh Rajashekhara 		return (status >> 16) & 0xFF;
369e8b12f0fSMahesh Rajashekhara 	/*
370e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running.
371e8b12f0fSMahesh Rajashekhara 	 */
372e8b12f0fSMahesh Rajashekhara 	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
373e8b12f0fSMahesh Rajashekhara 		return -3;
374e8b12f0fSMahesh Rajashekhara 	/*
375e8b12f0fSMahesh Rajashekhara 	 *	Everything is OK
376e8b12f0fSMahesh Rajashekhara 	 */
377e8b12f0fSMahesh Rajashekhara 	return 0;
378e8b12f0fSMahesh Rajashekhara }
379e8b12f0fSMahesh Rajashekhara 
380e8b12f0fSMahesh Rajashekhara /**
381e8b12f0fSMahesh Rajashekhara  *	aac_src_deliver_message
382e8b12f0fSMahesh Rajashekhara  *	@fib: fib to issue
383e8b12f0fSMahesh Rajashekhara  *
384e8b12f0fSMahesh Rajashekhara  *	Will send a fib, returning 0 if successful.
385e8b12f0fSMahesh Rajashekhara  */
386e8b12f0fSMahesh Rajashekhara static int aac_src_deliver_message(struct fib *fib)
387e8b12f0fSMahesh Rajashekhara {
388e8b12f0fSMahesh Rajashekhara 	struct aac_dev *dev = fib->dev;
389e8b12f0fSMahesh Rajashekhara 	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
390e8b12f0fSMahesh Rajashekhara 	unsigned long qflags;
391e8b12f0fSMahesh Rajashekhara 	u32 fibsize;
392e8b12f0fSMahesh Rajashekhara 	u64 address;
393e8b12f0fSMahesh Rajashekhara 	struct aac_fib_xporthdr *pFibX;
394e8b12f0fSMahesh Rajashekhara 
395e8b12f0fSMahesh Rajashekhara 	spin_lock_irqsave(q->lock, qflags);
396e8b12f0fSMahesh Rajashekhara 	q->numpending++;
397e8b12f0fSMahesh Rajashekhara 	spin_unlock_irqrestore(q->lock, qflags);
398e8b12f0fSMahesh Rajashekhara 
399e8b12f0fSMahesh Rajashekhara 	/* Calculate the amount to the fibsize bits */
400e8b12f0fSMahesh Rajashekhara 	fibsize = (sizeof(struct aac_fib_xporthdr) +
401e8b12f0fSMahesh Rajashekhara 		fib->hw_fib_va->header.Size + 127) / 128 - 1;
402e8b12f0fSMahesh Rajashekhara 	if (fibsize > (ALIGN32 - 1))
403e8b12f0fSMahesh Rajashekhara 		fibsize = ALIGN32 - 1;
404e8b12f0fSMahesh Rajashekhara 
405e8b12f0fSMahesh Rajashekhara     /* Fill XPORT header */
406e8b12f0fSMahesh Rajashekhara 	pFibX = (struct aac_fib_xporthdr *)
407e8b12f0fSMahesh Rajashekhara 		((unsigned char *)fib->hw_fib_va -
408e8b12f0fSMahesh Rajashekhara 		sizeof(struct aac_fib_xporthdr));
409e8b12f0fSMahesh Rajashekhara 	pFibX->Handle = fib->hw_fib_va->header.SenderData + 1;
410e8b12f0fSMahesh Rajashekhara 	pFibX->HostAddress = fib->hw_fib_pa;
411e8b12f0fSMahesh Rajashekhara 	pFibX->Size = fib->hw_fib_va->header.Size;
412e8b12f0fSMahesh Rajashekhara 	address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr);
413e8b12f0fSMahesh Rajashekhara 
414e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.IQ_H, (u32)(address >> 32));
415e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize);
416e8b12f0fSMahesh Rajashekhara 	return 0;
417e8b12f0fSMahesh Rajashekhara }
418e8b12f0fSMahesh Rajashekhara 
419e8b12f0fSMahesh Rajashekhara /**
420e8b12f0fSMahesh Rajashekhara  *	aac_src_ioremap
421e8b12f0fSMahesh Rajashekhara  *	@size: mapping resize request
422e8b12f0fSMahesh Rajashekhara  *
423e8b12f0fSMahesh Rajashekhara  */
424e8b12f0fSMahesh Rajashekhara static int aac_src_ioremap(struct aac_dev *dev, u32 size)
425e8b12f0fSMahesh Rajashekhara {
426e8b12f0fSMahesh Rajashekhara 	if (!size) {
42771552505STomas Henzl 		iounmap(dev->regs.src.bar1);
42871552505STomas Henzl 		dev->regs.src.bar1 = NULL;
429e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
43011604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
431e8b12f0fSMahesh Rajashekhara 		return 0;
432e8b12f0fSMahesh Rajashekhara 	}
433e8b12f0fSMahesh Rajashekhara 	dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
434e8b12f0fSMahesh Rajashekhara 		AAC_MIN_SRC_BAR1_SIZE);
435e8b12f0fSMahesh Rajashekhara 	dev->base = NULL;
436e8b12f0fSMahesh Rajashekhara 	if (dev->regs.src.bar1 == NULL)
437e8b12f0fSMahesh Rajashekhara 		return -1;
438e8b12f0fSMahesh Rajashekhara 	dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base,
439e8b12f0fSMahesh Rajashekhara 				size);
440e8b12f0fSMahesh Rajashekhara 	if (dev->base == NULL) {
441e8b12f0fSMahesh Rajashekhara 		iounmap(dev->regs.src.bar1);
442e8b12f0fSMahesh Rajashekhara 		dev->regs.src.bar1 = NULL;
443e8b12f0fSMahesh Rajashekhara 		return -1;
444e8b12f0fSMahesh Rajashekhara 	}
445e8b12f0fSMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
44611604612SMahesh Rajashekhara 		dev->base)->u.tupelo.IndexRegs;
44711604612SMahesh Rajashekhara 	return 0;
44811604612SMahesh Rajashekhara }
44911604612SMahesh Rajashekhara 
45011604612SMahesh Rajashekhara /**
45111604612SMahesh Rajashekhara  *  aac_srcv_ioremap
45211604612SMahesh Rajashekhara  *	@size: mapping resize request
45311604612SMahesh Rajashekhara  *
45411604612SMahesh Rajashekhara  */
45511604612SMahesh Rajashekhara static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
45611604612SMahesh Rajashekhara {
45711604612SMahesh Rajashekhara 	if (!size) {
45811604612SMahesh Rajashekhara 		iounmap(dev->regs.src.bar0);
45911604612SMahesh Rajashekhara 		dev->base = dev->regs.src.bar0 = NULL;
46011604612SMahesh Rajashekhara 		return 0;
46111604612SMahesh Rajashekhara 	}
46211604612SMahesh Rajashekhara 	dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, size);
46311604612SMahesh Rajashekhara 	if (dev->base == NULL)
46411604612SMahesh Rajashekhara 		return -1;
46511604612SMahesh Rajashekhara 	dev->IndexRegs = &((struct src_registers __iomem *)
46611604612SMahesh Rajashekhara 		dev->base)->u.denali.IndexRegs;
467e8b12f0fSMahesh Rajashekhara 	return 0;
468e8b12f0fSMahesh Rajashekhara }
469e8b12f0fSMahesh Rajashekhara 
470e8b12f0fSMahesh Rajashekhara static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
471e8b12f0fSMahesh Rajashekhara {
472e8b12f0fSMahesh Rajashekhara 	u32 var, reset_mask;
473e8b12f0fSMahesh Rajashekhara 
474e8b12f0fSMahesh Rajashekhara 	if (bled >= 0) {
475e8b12f0fSMahesh Rajashekhara 		if (bled)
476e8b12f0fSMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
477e8b12f0fSMahesh Rajashekhara 				dev->name, dev->id, bled);
478e8b12f0fSMahesh Rajashekhara 		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
479e8b12f0fSMahesh Rajashekhara 			0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
480e8b12f0fSMahesh Rajashekhara 			if (bled || (var != 0x00000001))
48111604612SMahesh Rajashekhara 				return -EINVAL;
482e8b12f0fSMahesh Rajashekhara 		if (dev->supplement_adapter_info.SupportedOptions2 &
483e8b12f0fSMahesh Rajashekhara 			AAC_OPTION_DOORBELL_RESET) {
484e8b12f0fSMahesh Rajashekhara 			src_writel(dev, MUnit.IDR, reset_mask);
485e8b12f0fSMahesh Rajashekhara 			msleep(5000); /* Delay 5 seconds */
486e8b12f0fSMahesh Rajashekhara 		}
487e8b12f0fSMahesh Rajashekhara 	}
488e8b12f0fSMahesh Rajashekhara 
489e8b12f0fSMahesh Rajashekhara 	if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
490e8b12f0fSMahesh Rajashekhara 		return -ENODEV;
491e8b12f0fSMahesh Rajashekhara 
492e8b12f0fSMahesh Rajashekhara 	if (startup_timeout < 300)
493e8b12f0fSMahesh Rajashekhara 		startup_timeout = 300;
494e8b12f0fSMahesh Rajashekhara 
495e8b12f0fSMahesh Rajashekhara 	return 0;
496e8b12f0fSMahesh Rajashekhara }
497e8b12f0fSMahesh Rajashekhara 
498e8b12f0fSMahesh Rajashekhara /**
499e8b12f0fSMahesh Rajashekhara  *	aac_src_select_comm	-	Select communications method
500e8b12f0fSMahesh Rajashekhara  *	@dev: Adapter
501e8b12f0fSMahesh Rajashekhara  *	@comm: communications method
502e8b12f0fSMahesh Rajashekhara  */
503e8b12f0fSMahesh Rajashekhara int aac_src_select_comm(struct aac_dev *dev, int comm)
504e8b12f0fSMahesh Rajashekhara {
505e8b12f0fSMahesh Rajashekhara 	switch (comm) {
506e8b12f0fSMahesh Rajashekhara 	case AAC_COMM_MESSAGE:
507e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
508e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_intr = aac_src_intr_message;
509e8b12f0fSMahesh Rajashekhara 		dev->a_ops.adapter_deliver = aac_src_deliver_message;
510e8b12f0fSMahesh Rajashekhara 		break;
511e8b12f0fSMahesh Rajashekhara 	default:
512e8b12f0fSMahesh Rajashekhara 		return 1;
513e8b12f0fSMahesh Rajashekhara 	}
514e8b12f0fSMahesh Rajashekhara 	return 0;
515e8b12f0fSMahesh Rajashekhara }
516e8b12f0fSMahesh Rajashekhara 
517e8b12f0fSMahesh Rajashekhara /**
518e8b12f0fSMahesh Rajashekhara  *  aac_src_init	-	initialize an Cardinal Frey Bar card
519e8b12f0fSMahesh Rajashekhara  *  @dev: device to configure
520e8b12f0fSMahesh Rajashekhara  *
521e8b12f0fSMahesh Rajashekhara  */
522e8b12f0fSMahesh Rajashekhara 
523e8b12f0fSMahesh Rajashekhara int aac_src_init(struct aac_dev *dev)
524e8b12f0fSMahesh Rajashekhara {
525e8b12f0fSMahesh Rajashekhara 	unsigned long start;
526e8b12f0fSMahesh Rajashekhara 	unsigned long status;
527e8b12f0fSMahesh Rajashekhara 	int restart = 0;
528e8b12f0fSMahesh Rajashekhara 	int instance = dev->id;
529e8b12f0fSMahesh Rajashekhara 	const char *name = dev->name;
530e8b12f0fSMahesh Rajashekhara 
531e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_src_ioremap;
532e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
533e8b12f0fSMahesh Rajashekhara 
534e8b12f0fSMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
535e8b12f0fSMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
536e8b12f0fSMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
537e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
538e8b12f0fSMahesh Rajashekhara 	}
539e8b12f0fSMahesh Rajashekhara 
540e8b12f0fSMahesh Rajashekhara 	/* Failure to reset here is an option ... */
541e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
542e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
543e8b12f0fSMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
544e8b12f0fSMahesh Rajashekhara 		!aac_src_restart_adapter(dev, 0))
545e8b12f0fSMahesh Rajashekhara 		++restart;
546e8b12f0fSMahesh Rajashekhara 	/*
547e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
548e8b12f0fSMahesh Rajashekhara 	 */
549e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
550e8b12f0fSMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
551e8b12f0fSMahesh Rajashekhara 		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
552e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
553e8b12f0fSMahesh Rajashekhara 		++restart;
554e8b12f0fSMahesh Rajashekhara 	}
555e8b12f0fSMahesh Rajashekhara 	/*
556e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
557e8b12f0fSMahesh Rajashekhara 	 */
558e8b12f0fSMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
559e8b12f0fSMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
560e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
561e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
562e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
563e8b12f0fSMahesh Rajashekhara 	}
564e8b12f0fSMahesh Rajashekhara 	/*
565e8b12f0fSMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
566e8b12f0fSMahesh Rajashekhara 	 */
567e8b12f0fSMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
568e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n",
569e8b12f0fSMahesh Rajashekhara 			dev->name, instance);
570e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
571e8b12f0fSMahesh Rajashekhara 	}
572e8b12f0fSMahesh Rajashekhara 	start = jiffies;
573e8b12f0fSMahesh Rajashekhara 	/*
574e8b12f0fSMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
575e8b12f0fSMahesh Rajashekhara 	 */
576e8b12f0fSMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) &
577e8b12f0fSMahesh Rajashekhara 		KERNEL_UP_AND_RUNNING)) {
578e8b12f0fSMahesh Rajashekhara 		if ((restart &&
579e8b12f0fSMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
580e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
581e8b12f0fSMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
582e8b12f0fSMahesh Rajashekhara 					dev->name, instance, status);
583e8b12f0fSMahesh Rajashekhara 			goto error_iounmap;
584e8b12f0fSMahesh Rajashekhara 		}
585e8b12f0fSMahesh Rajashekhara 		if (!restart &&
586e8b12f0fSMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
587e8b12f0fSMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
588e8b12f0fSMahesh Rajashekhara 		  ((startup_timeout > 60)
589e8b12f0fSMahesh Rajashekhara 		    ? (startup_timeout - 60)
590e8b12f0fSMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
591e8b12f0fSMahesh Rajashekhara 			if (likely(!aac_src_restart_adapter(dev,
592e8b12f0fSMahesh Rajashekhara 			    aac_src_check_health(dev))))
593e8b12f0fSMahesh Rajashekhara 				start = jiffies;
594e8b12f0fSMahesh Rajashekhara 			++restart;
595e8b12f0fSMahesh Rajashekhara 		}
596e8b12f0fSMahesh Rajashekhara 		msleep(1);
597e8b12f0fSMahesh Rajashekhara 	}
598e8b12f0fSMahesh Rajashekhara 	if (restart && aac_commit)
599e8b12f0fSMahesh Rajashekhara 		aac_commit = 1;
600e8b12f0fSMahesh Rajashekhara 	/*
601e8b12f0fSMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
602e8b12f0fSMahesh Rajashekhara 	 */
603e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
604e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
605e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
606e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
607e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
608e8b12f0fSMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
609e8b12f0fSMahesh Rajashekhara 
610e8b12f0fSMahesh Rajashekhara 	/*
611e8b12f0fSMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
612e8b12f0fSMahesh Rajashekhara 	 *	can handle.
613e8b12f0fSMahesh Rajashekhara 	 */
614e8b12f0fSMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
615e8b12f0fSMahesh Rajashekhara 	aac_adapter_disable_int(dev);
616e8b12f0fSMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
617e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
618e8b12f0fSMahesh Rajashekhara 
619e8b12f0fSMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
620e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
621e8b12f0fSMahesh Rajashekhara 	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
622e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
623e8b12f0fSMahesh Rajashekhara 
624e8b12f0fSMahesh Rajashekhara 	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
625e8b12f0fSMahesh Rajashekhara 
626e8b12f0fSMahesh Rajashekhara 	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
627e8b12f0fSMahesh Rajashekhara 			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
628e8b12f0fSMahesh Rajashekhara 
629e8b12f0fSMahesh Rajashekhara 		if (dev->msi)
630e8b12f0fSMahesh Rajashekhara 			pci_disable_msi(dev->pdev);
631e8b12f0fSMahesh Rajashekhara 
632e8b12f0fSMahesh Rajashekhara 		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
633e8b12f0fSMahesh Rajashekhara 			name, instance);
634e8b12f0fSMahesh Rajashekhara 		goto error_iounmap;
635e8b12f0fSMahesh Rajashekhara 	}
636e8b12f0fSMahesh Rajashekhara 	dev->dbg_base = pci_resource_start(dev->pdev, 2);
637e8b12f0fSMahesh Rajashekhara 	dev->dbg_base_mapped = dev->regs.src.bar1;
638e8b12f0fSMahesh Rajashekhara 	dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
639e8b12f0fSMahesh Rajashekhara 
640e8b12f0fSMahesh Rajashekhara 	aac_adapter_enable_int(dev);
64111604612SMahesh Rajashekhara 
64211604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
643e8b12f0fSMahesh Rajashekhara 		/*
644e8b12f0fSMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
645e8b12f0fSMahesh Rajashekhara 		 * start accepting requests
646e8b12f0fSMahesh Rajashekhara 		 */
647e8b12f0fSMahesh Rajashekhara 		aac_src_start_adapter(dev);
64811604612SMahesh Rajashekhara 	}
649e8b12f0fSMahesh Rajashekhara 	return 0;
650e8b12f0fSMahesh Rajashekhara 
651e8b12f0fSMahesh Rajashekhara error_iounmap:
652e8b12f0fSMahesh Rajashekhara 
653e8b12f0fSMahesh Rajashekhara 	return -1;
654e8b12f0fSMahesh Rajashekhara }
65511604612SMahesh Rajashekhara 
65611604612SMahesh Rajashekhara /**
65711604612SMahesh Rajashekhara  *  aac_srcv_init	-	initialize an SRCv card
65811604612SMahesh Rajashekhara  *  @dev: device to configure
65911604612SMahesh Rajashekhara  *
66011604612SMahesh Rajashekhara  */
66111604612SMahesh Rajashekhara 
66211604612SMahesh Rajashekhara int aac_srcv_init(struct aac_dev *dev)
66311604612SMahesh Rajashekhara {
66411604612SMahesh Rajashekhara 	unsigned long start;
66511604612SMahesh Rajashekhara 	unsigned long status;
66611604612SMahesh Rajashekhara 	int restart = 0;
66711604612SMahesh Rajashekhara 	int instance = dev->id;
66811604612SMahesh Rajashekhara 	const char *name = dev->name;
66911604612SMahesh Rajashekhara 
67011604612SMahesh Rajashekhara 	dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
67111604612SMahesh Rajashekhara 	dev->a_ops.adapter_comm = aac_src_select_comm;
67211604612SMahesh Rajashekhara 
67311604612SMahesh Rajashekhara 	dev->base_size = AAC_MIN_SRCV_BAR0_SIZE;
67411604612SMahesh Rajashekhara 	if (aac_adapter_ioremap(dev, dev->base_size)) {
67511604612SMahesh Rajashekhara 		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
67611604612SMahesh Rajashekhara 		goto error_iounmap;
67711604612SMahesh Rajashekhara 	}
67811604612SMahesh Rajashekhara 
67911604612SMahesh Rajashekhara 	/* Failure to reset here is an option ... */
68011604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
68111604612SMahesh Rajashekhara 	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
68211604612SMahesh Rajashekhara 	if ((aac_reset_devices || reset_devices) &&
68311604612SMahesh Rajashekhara 		!aac_src_restart_adapter(dev, 0))
68411604612SMahesh Rajashekhara 		++restart;
68511604612SMahesh Rajashekhara 	/*
68611604612SMahesh Rajashekhara 	 *	Check to see if the board panic'd while booting.
68711604612SMahesh Rajashekhara 	 */
68811604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
68911604612SMahesh Rajashekhara 	if (status & KERNEL_PANIC) {
69011604612SMahesh Rajashekhara 		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
69111604612SMahesh Rajashekhara 			goto error_iounmap;
69211604612SMahesh Rajashekhara 		++restart;
69311604612SMahesh Rajashekhara 	}
69411604612SMahesh Rajashekhara 	/*
69511604612SMahesh Rajashekhara 	 *	Check to see if the board failed any self tests.
69611604612SMahesh Rajashekhara 	 */
69711604612SMahesh Rajashekhara 	status = src_readl(dev, MUnit.OMR);
69811604612SMahesh Rajashekhara 	if (status & SELF_TEST_FAILED) {
69911604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
70011604612SMahesh Rajashekhara 		goto error_iounmap;
70111604612SMahesh Rajashekhara 	}
70211604612SMahesh Rajashekhara 	/*
70311604612SMahesh Rajashekhara 	 *	Check to see if the monitor panic'd while booting.
70411604612SMahesh Rajashekhara 	 */
70511604612SMahesh Rajashekhara 	if (status & MONITOR_PANIC) {
70611604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
70711604612SMahesh Rajashekhara 		goto error_iounmap;
70811604612SMahesh Rajashekhara 	}
70911604612SMahesh Rajashekhara 	start = jiffies;
71011604612SMahesh Rajashekhara 	/*
71111604612SMahesh Rajashekhara 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
71211604612SMahesh Rajashekhara 	 */
71311604612SMahesh Rajashekhara 	while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)) {
71411604612SMahesh Rajashekhara 		if ((restart &&
71511604612SMahesh Rajashekhara 		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
71611604612SMahesh Rajashekhara 		  time_after(jiffies, start+HZ*startup_timeout)) {
71711604612SMahesh Rajashekhara 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
71811604612SMahesh Rajashekhara 					dev->name, instance, status);
71911604612SMahesh Rajashekhara 			goto error_iounmap;
72011604612SMahesh Rajashekhara 		}
72111604612SMahesh Rajashekhara 		if (!restart &&
72211604612SMahesh Rajashekhara 		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
72311604612SMahesh Rajashekhara 		  time_after(jiffies, start + HZ *
72411604612SMahesh Rajashekhara 		  ((startup_timeout > 60)
72511604612SMahesh Rajashekhara 		    ? (startup_timeout - 60)
72611604612SMahesh Rajashekhara 		    : (startup_timeout / 2))))) {
72711604612SMahesh Rajashekhara 			if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev))))
72811604612SMahesh Rajashekhara 				start = jiffies;
72911604612SMahesh Rajashekhara 			++restart;
73011604612SMahesh Rajashekhara 		}
73111604612SMahesh Rajashekhara 		msleep(1);
73211604612SMahesh Rajashekhara 	}
73311604612SMahesh Rajashekhara 	if (restart && aac_commit)
73411604612SMahesh Rajashekhara 		aac_commit = 1;
73511604612SMahesh Rajashekhara 	/*
73611604612SMahesh Rajashekhara 	 *	Fill in the common function dispatch table.
73711604612SMahesh Rajashekhara 	 */
73811604612SMahesh Rajashekhara 	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
73911604612SMahesh Rajashekhara 	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
74011604612SMahesh Rajashekhara 	dev->a_ops.adapter_notify = aac_src_notify_adapter;
74111604612SMahesh Rajashekhara 	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
74211604612SMahesh Rajashekhara 	dev->a_ops.adapter_check_health = aac_src_check_health;
74311604612SMahesh Rajashekhara 	dev->a_ops.adapter_restart = aac_src_restart_adapter;
74411604612SMahesh Rajashekhara 
74511604612SMahesh Rajashekhara 	/*
74611604612SMahesh Rajashekhara 	 *	First clear out all interrupts.  Then enable the one's that we
74711604612SMahesh Rajashekhara 	 *	can handle.
74811604612SMahesh Rajashekhara 	 */
74911604612SMahesh Rajashekhara 	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
75011604612SMahesh Rajashekhara 	aac_adapter_disable_int(dev);
75111604612SMahesh Rajashekhara 	src_writel(dev, MUnit.ODR_C, 0xffffffff);
75211604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
75311604612SMahesh Rajashekhara 
75411604612SMahesh Rajashekhara 	if (aac_init_adapter(dev) == NULL)
75511604612SMahesh Rajashekhara 		goto error_iounmap;
75611604612SMahesh Rajashekhara 	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
75711604612SMahesh Rajashekhara 		goto error_iounmap;
75811604612SMahesh Rajashekhara 	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
75911604612SMahesh Rajashekhara 	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
76011604612SMahesh Rajashekhara 		IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
76111604612SMahesh Rajashekhara 		if (dev->msi)
76211604612SMahesh Rajashekhara 			pci_disable_msi(dev->pdev);
76311604612SMahesh Rajashekhara 		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
76411604612SMahesh Rajashekhara 			name, instance);
76511604612SMahesh Rajashekhara 		goto error_iounmap;
76611604612SMahesh Rajashekhara 	}
76711604612SMahesh Rajashekhara 	dev->dbg_base = dev->scsi_host_ptr->base;
76811604612SMahesh Rajashekhara 	dev->dbg_base_mapped = dev->base;
76911604612SMahesh Rajashekhara 	dev->dbg_size = dev->base_size;
77011604612SMahesh Rajashekhara 
77111604612SMahesh Rajashekhara 	aac_adapter_enable_int(dev);
77211604612SMahesh Rajashekhara 
77311604612SMahesh Rajashekhara 	if (!dev->sync_mode) {
77411604612SMahesh Rajashekhara 		/*
77511604612SMahesh Rajashekhara 		 * Tell the adapter that all is configured, and it can
77611604612SMahesh Rajashekhara 		 * start accepting requests
77711604612SMahesh Rajashekhara 		 */
77811604612SMahesh Rajashekhara 		aac_src_start_adapter(dev);
77911604612SMahesh Rajashekhara 	}
78011604612SMahesh Rajashekhara 	return 0;
78111604612SMahesh Rajashekhara 
78211604612SMahesh Rajashekhara error_iounmap:
78311604612SMahesh Rajashekhara 
78411604612SMahesh Rajashekhara 	return -1;
78511604612SMahesh Rajashekhara }
78611604612SMahesh Rajashekhara 
787