11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Adaptec AAC series RAID controller driver
3fa195afe4ad3f6d85a9b7cc236ae85c05ca8db03Alan Cox *	(c) Copyright 2001 Red Hat Inc.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on the old aacraid driver that is..
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adaptec aacraid device driver for Linux.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara * Copyright (c) 2000-2010 Adaptec, Inc.
9e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option)
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version.
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; see the file COPYING.  If not, write to
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Module Name:
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  rx.c
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Abstract: Hardware miniport for Drawbridge specific hardware functions.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/completion.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/time.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aacraid.h"
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampstatic irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct aac_dev *dev = dev_id;
5028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	unsigned long bellbits;
5128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	u8 intstat = rx_readb(dev, MUnit.OISR);
528e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp
5328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	/*
5428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	Read mask and invert because drawbridge is reversed.
5528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	This allows us to only service interrupts that have
5628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	been enabled.
5728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	Check to see if this is our interrupt.  If it isn't just return
5828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 */
59912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (likely(intstat & ~(dev->OIMR))) {
6028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		bellbits = rx_readl(dev, OutboundDoorbellReg);
61912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (unlikely(bellbits & DoorBellPrintfReady)) {
6228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
6328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
6428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
66912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
6728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
6828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
6928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		}
70912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
7128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
7228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
7328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		}
74912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
7528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
77912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
7828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
7928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
8028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		}
8128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		return IRQ_HANDLED;
8228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	}
8328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	return IRQ_NONE;
8428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp}
8528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
8628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampstatic irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
8728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp{
88e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara	int isAif, isFastResponse, isSpecial;
8928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	struct aac_dev *dev = dev_id;
9028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
91912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (unlikely(Index == 0xFFFFFFFFL))
9228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		Index = rx_readl(dev, MUnit.OutboundQueue);
93912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (likely(Index != 0xFFFFFFFFL)) {
9428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		do {
95e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara			isAif = isFastResponse = isSpecial = 0;
96e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara			if (Index & 0x00000002L) {
97e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				isAif = 1;
98e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				if (Index == 0xFFFFFFFEL)
99e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara					isSpecial = 1;
100e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				Index &= ~0x00000002L;
101e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara			} else {
102e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				if (Index & 0x00000001L)
103e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara					isFastResponse = 1;
104e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				Index >>= 2;
105e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara			}
106e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara			if (!isSpecial) {
107e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				if (unlikely(aac_intr_normal(dev,
108e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						Index, isAif,
109e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						isFastResponse, NULL))) {
110e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara					rx_writel(dev,
111e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						MUnit.OutboundQueue,
112e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						Index);
113e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara					rx_writel(dev,
114e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						MUnit.ODR,
115e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara						DoorBellAdapterNormRespReady);
116e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara				}
11728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			}
11828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			Index = rx_readl(dev, MUnit.OutboundQueue);
11928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		} while (Index != 0xFFFFFFFFL);
12028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		return IRQ_HANDLED;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_NONE;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
126bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp *	aac_rx_disable_interrupt	-	Disable interrupts
127bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp *	@dev: Adapter
128bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp */
129bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp
130bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkampstatic void aac_rx_disable_interrupt(struct aac_dev *dev)
131bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp{
132bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
133bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp}
134bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp
135bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp/**
13628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	aac_rx_enable_interrupt_producer	-	Enable interrupts
13728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	@dev: Adapter
13828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp */
13928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
14028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampstatic void aac_rx_enable_interrupt_producer(struct aac_dev *dev)
14128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp{
14228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
14328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp}
14428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
14528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp/**
14628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	aac_rx_enable_interrupt_message	-	Enable interrupts
14728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	@dev: Adapter
14828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp */
14928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
15028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampstatic void aac_rx_enable_interrupt_message(struct aac_dev *dev)
15128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp{
15228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
15328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp}
15428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
15528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp/**
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	rx_sync_cmd	-	send a command and wait
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: Adapter
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@command: Command to execute
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@p1: first parameter
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@ret: adapter status
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	This routine will send a synchronous command to the adapter and wait
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	for its	completion.
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1667c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkampstatic int rx_sync_cmd(struct aac_dev *dev, u32 command,
1677c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
1687c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ok;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Write the command into Mailbox 0
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
17576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	writel(command, &dev->IndexRegs->Mailbox[0]);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1777c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	 *	Write the parameters into Mailboxes 1 - 6
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
17976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	writel(p1, &dev->IndexRegs->Mailbox[1]);
18076a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	writel(p2, &dev->IndexRegs->Mailbox[2]);
18176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	writel(p3, &dev->IndexRegs->Mailbox[3]);
18276a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	writel(p4, &dev->IndexRegs->Mailbox[4]);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Clear the synch command doorbell to start on a clean slate.
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Disable doorbell interrupts
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1907c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Force the completion of the mask register write before issuing
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	the interrupt.
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx_readb (dev, MUnit.OIMR);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Signal that there is a new synch command
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ok = 0;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start = jiffies;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Wait up to 30 seconds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (time_before(jiffies, start+30*HZ))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *	Mon960 will set doorbell0 bit when it has completed the command.
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *	Clear the doorbell.
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ok = 1;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *	Yield the processor in case we are slow
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2241241f3593a8857fab4259b6aa9d17f26e7de3a86Mark Haverkamp		msleep(1);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
226912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (unlikely(ok != 1)) {
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *	Restore interrupt mask even though we timed out
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
23028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		aac_adapter_enable_int(dev);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ETIMEDOUT;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Pull the synch status from Mailbox 0.
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status)
23776a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		*status = readl(&dev->IndexRegs->Mailbox[0]);
2387c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	if (r1)
23976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		*r1 = readl(&dev->IndexRegs->Mailbox[1]);
2407c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	if (r2)
24176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		*r2 = readl(&dev->IndexRegs->Mailbox[2]);
2427c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	if (r3)
24376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		*r3 = readl(&dev->IndexRegs->Mailbox[3]);
2447c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	if (r4)
24576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		*r4 = readl(&dev->IndexRegs->Mailbox[4]);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Clear the synch command doorbell.
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Restore interrupt mask
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
25328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_enable_int(dev);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	aac_rx_interrupt_adapter	-	interrupt adapter
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: Adapter
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Send an interrupt to the i960 and breakpoint it.
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void aac_rx_interrupt_adapter(struct aac_dev *dev)
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2677c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	aac_rx_notify_adapter		-	send an event to the adapter
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: Adapter
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@event: Event to send
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Notify the i960 that something it probably cares about has
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	happened.
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case AdapNormCmdQue:
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case HostNormRespNotFull:
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case AdapNormRespQue:
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case HostNormCmdNotFull:
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case HostShutdown:
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FastIo:
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case AdapPrintfDone:
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	aac_rx_start_adapter		-	activate adapter
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev:	Adapter
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Start up processing on an i960 based AAC adapter
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3169695a25dbff788f26225966c43425e8bae7f06e8Adrian Bunkstatic void aac_rx_start_adapter(struct aac_dev *dev)
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct aac_init *init;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init = dev->init;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// We can only use a 32 bit address here
3237c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
3247c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	aac_rx_check_health
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: device to check if healthy
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Will attempt to determine if the specified adapter is alive and
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	capable of handling requests, returning 0 if alive.
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int aac_rx_check_health(struct aac_dev *dev)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status = rx_readl(dev, MUnit.OMRx[0]);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Check to see if the board failed any self tests.
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
341912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (unlikely(status & SELF_TEST_FAILED))
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Check to see if the board panic'd.
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
346912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (unlikely(status & KERNEL_PANIC)) {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		char * buffer;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct POSTSTATUS {
34956b5871223f66d4a34e6e1069f241077e9f0a154Mark Haverkamp			__le32 Post_Command;
35056b5871223f66d4a34e6e1069f241077e9f0a154Mark Haverkamp			__le32 Post_Address;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} * post;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_addr_t paddr, baddr;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int ret;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
355912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (likely((status & 0xFF000000L) == 0xBC000000L))
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (status >> 16) & 0xFF;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -2;
359912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (unlikely(buffer == NULL))
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		post = pci_alloc_consistent(dev->pdev,
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  sizeof(struct POSTSTATUS), &paddr);
363912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (unlikely(post == NULL)) {
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_free_consistent(dev->pdev, 512, buffer, baddr);
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(buffer, 0, 512);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		post->Post_Address = cpu_to_le32(baddr);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rx_writel(dev, MUnit.IMRx[0], paddr);
3717c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp		rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
3727c00ffa314bf0fb0e23858bbebad33b48b6abbb9Mark Haverkamp		  NULL, NULL, NULL, NULL, NULL);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  post, paddr);
375912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
376ecc3099002c1cc87e9e4b3dc5fdf7821828f6733Andy Shevchenko			ret = (hex_to_bin(buffer[2]) << 4) +
377ecc3099002c1cc87e9e4b3dc5fdf7821828f6733Andy Shevchenko				hex_to_bin(buffer[3]);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(dev->pdev, 512, buffer, baddr);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ret;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Wait for the adapter to be up and running.
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
385912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -3;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Everything is OK
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
39428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	aac_rx_deliver_producer
3958e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp *	@fib: fib to issue
3968e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp *
3978e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp *	Will send a fib, returning 0 if successful.
3988e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp */
3992ab01efd1d2a24db53b4c5d28a2e20cf2b1206c5Salyzyn, Markint aac_rx_deliver_producer(struct fib * fib)
4008e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp{
4018e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	struct aac_dev *dev = fib->dev;
40228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
40328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	unsigned long qflags;
4048e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	u32 Index;
40528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	unsigned long nointr = 0;
4068e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp
40728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	spin_lock_irqsave(q->lock, qflags);
408a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp	aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
40928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
41028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	q->numpending++;
41128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	*(q->headers.producer) = cpu_to_le32(Index + 1);
41228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	spin_unlock_irqrestore(q->lock, qflags);
41328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	if (!(nointr & aac_config.irq_mod))
41428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		aac_adapter_notify(dev, AdapNormCmdQueue);
41528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
41628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	return 0;
41728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp}
41828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
41928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp/**
42028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	aac_rx_deliver_message
42128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	@fib: fib to issue
42228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *
42328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	Will send a fib, returning 0 if successful.
42428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp */
42528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampstatic int aac_rx_deliver_message(struct fib * fib)
42628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp{
42728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	struct aac_dev *dev = fib->dev;
42828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
42928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	unsigned long qflags;
43028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	u32 Index;
43128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	u64 addr;
43228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	volatile void __iomem *device;
43328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
43428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	unsigned long count = 10000000L; /* 50 seconds */
43528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	spin_lock_irqsave(q->lock, qflags);
43628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	q->numpending++;
43728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	spin_unlock_irqrestore(q->lock, qflags);
43828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	for(;;) {
4398e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp		Index = rx_readl(dev, MUnit.InboundQueue);
440912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (unlikely(Index == 0xFFFFFFFFL))
44128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			Index = rx_readl(dev, MUnit.InboundQueue);
442912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark		if (likely(Index != 0xFFFFFFFFL))
44328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			break;
44428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		if (--count == 0) {
44528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			spin_lock_irqsave(q->lock, qflags);
44628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			q->numpending--;
44728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			spin_unlock_irqrestore(q->lock, qflags);
44828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			return -ETIMEDOUT;
44928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		}
45028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		udelay(5);
45128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	}
45276a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	device = dev->base + Index;
45328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	addr = fib->hw_fib_pa;
4548e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	writel((u32)(addr & 0xffffffff), device);
4558e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	device += sizeof(u32);
4568e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	writel((u32)(addr >> 32), device);
4578e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	device += sizeof(u32);
458a8166a52968216ae079a5530ac3269147de2ef31Mark Haverkamp	writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
4598e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	rx_writel(dev, MUnit.InboundQueue, Index);
4608e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	return 0;
4618e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp}
4628e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp
46376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp/**
46476a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp *	aac_rx_ioremap
46576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp *	@size: mapping resize request
46676a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp *
46776a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp */
46876a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkampstatic int aac_rx_ioremap(struct aac_dev * dev, u32 size)
46976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp{
47076a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	if (!size) {
47176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		iounmap(dev->regs.rx);
47276a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		return 0;
47376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	}
47476a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	dev->base = dev->regs.rx = ioremap(dev->scsi_host_ptr->base, size);
47576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	if (dev->base == NULL)
47676a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		return -1;
47776a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	dev->IndexRegs = &dev->regs.rx->IndexRegs;
47876a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	return 0;
47976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp}
48076a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp
4818418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkampstatic int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
4828c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp{
4838c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp	u32 var;
4848c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp
48529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark	if (!(dev->supplement_adapter_info.SupportedOptions2 &
486a3940da5e6fe8b833eecdbca3fac9456b4204d6eSalyzyn, Mark	  AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) {
48729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark		if (bled)
48829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
48929c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark				dev->name, dev->id, bled);
49029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark		else {
49129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
49229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
4939859c1aa7e16822c574e1be89d61fbfe6188b50fSalyzyn, Mark			if (!bled && (var != 0x00000001) && (var != 0x3803000F))
49429c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark				bled = -EINVAL;
49529c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark		}
49629c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark		if (bled && (bled != -ETIMEDOUT))
49729c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			bled = aac_adapter_sync_cmd(dev, IOP_RESET,
49829c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			  0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
4998418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp
50029c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark		if (bled && (bled != -ETIMEDOUT))
50129c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark			return -EINVAL;
50229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark	}
50318a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark	if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
5048418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp		rx_writel(dev, MUnit.reserved2, 3);
5058418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp		msleep(5000); /* Delay 5 seconds */
5068418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp		var = 0x00000001;
5078418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp	}
5088c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp	if (var != 0x00000001)
5098418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp		return -EINVAL;
5108c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp	if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
5118418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp		return -ENODEV;
5121208bab5d07c9a9172f04b76dc107c37507a9bb3Salyzyn, Mark	if (startup_timeout < 300)
5131208bab5d07c9a9172f04b76dc107c37507a9bb3Salyzyn, Mark		startup_timeout = 300;
5148c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp	return 0;
5158c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp}
5168c23cd7457151fc8ace79ec700a8aeaa9fc5b3d9Mark Haverkamp
5178e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp/**
51828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	aac_rx_select_comm	-	Select communications method
51928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	@dev: Adapter
52028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp *	@comm: communications method
52128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp */
52228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
52328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkampint aac_rx_select_comm(struct aac_dev *dev, int comm)
52428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp{
52528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	switch (comm) {
52628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	case AAC_COMM_PRODUCER:
52728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer;
52828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_intr = aac_rx_intr_producer;
52928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
53028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		break;
53128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	case AAC_COMM_MESSAGE:
53228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message;
53328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_intr = aac_rx_intr_message;
53428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		dev->a_ops.adapter_deliver = aac_rx_deliver_message;
53528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		break;
53628713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	default:
53728713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		return 1;
53828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	}
53928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	return 0;
54028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp}
54128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp
54228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp/**
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	aac_rx_init	-	initialize an i960 based AAC card
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: device to configure
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Allocate and set up resources for the i960 based AAC variants. The
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	device_interface in the commregion will be allocated and linked
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	to the comm region.
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkampint _aac_rx_init(struct aac_dev *dev)
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long status;
55518a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark	int restart = 0;
556912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	int instance = dev->id;
557912d4e8851389eee5c289ce0a7953e9067198232Salyzyn, Mark	const char * name = dev->name;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	if (aac_adapter_ioremap(dev, dev->base_size)) {
56076a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
56176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp		goto error_iounmap;
56276a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	}
56376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp
56418a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark	/* Failure to reset here is an option ... */
565a5694ec545a880f9d23463fddc894f5096cc68faSalyzyn, Mark	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
566a5694ec545a880f9d23463fddc894f5096cc68faSalyzyn, Mark	dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
56718a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark	dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
5681208bab5d07c9a9172f04b76dc107c37507a9bb3Salyzyn, Mark	if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) &&
56918a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark	  !aac_rx_restart_adapter(dev, 0))
570f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark		/* Make sure the Hardware FIFO is empty */
571f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark		while ((++restart < 512) &&
572f858317d894a22eb2c26edcd26c7060fc4f40a15Salyzyn, Mark		  (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL));
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5748e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp	 *	Check to see if the board panic'd while booting.
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
57676a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	status = rx_readl(dev, MUnit.OMRx[0]);
5778418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp	if (status & KERNEL_PANIC) {
57818a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
5798418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp			goto error_iounmap;
58018a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		++restart;
5818418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp	}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Check to see if the board failed any self tests.
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
58576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	status = rx_readl(dev, MUnit.OMRx[0]);
58676a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	if (status & SELF_TEST_FAILED) {
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_iounmap;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Check to see if the monitor panic'd while booting.
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
59376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	if (status & MONITOR_PANIC) {
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error_iounmap;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start = jiffies;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
60176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
60318a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		if ((restart &&
60418a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
60518a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		  time_after(jiffies, start+HZ*startup_timeout)) {
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, instance, status);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto error_iounmap;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
61018a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		if (!restart &&
61118a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
61218a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		  time_after(jiffies, start + HZ *
61318a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		  ((startup_timeout > 60)
61418a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		    ? (startup_timeout - 60)
61518a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		    : (startup_timeout / 2))))) {
61618a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark			if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
61718a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark				start = jiffies;
61818a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark			++restart;
61918a6598f2d3bb7275dadba77df5f06bc996a77d4Salyzyn, Mark		}
620404d9a900b5bc83a3780ec337ca6fdcb04b766c0Mark Haverkamp		msleep(1);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
62229c976844d0bef07d97babc8db60fa6c46788133Salyzyn, Mark	if (restart && aac_commit)
6231208bab5d07c9a9172f04b76dc107c37507a9bb3Salyzyn, Mark		aac_commit = 1;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
62528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	Fill in the common function dispatch table.
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
628bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->a_ops.adapter_check_health = aac_rx_check_health;
6328418852d11f0bbaeebeedd4243560d8fdc85410dMark Haverkamp	dev->a_ops.adapter_restart = aac_rx_restart_adapter;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
634bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	/*
635bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	 *	First clear out all interrupts.  Then enable the one's that we
636bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	 *	can handle.
637bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	 */
63828713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_comm(dev, AAC_COMM_PRODUCER);
63928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_disable_int(dev);
640bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp	rx_writel(dev, MUnit.ODR, 0xffffffff);
64128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_enable_int(dev);
642bd1aac809ddbcf7772cfd809d8cfb29c729c6cf9Mark Haverkamp
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (aac_init_adapter(dev) == NULL)
64428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		goto error_iounmap;
64528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_comm(dev, dev->comm_interface);
646116046127d1a3bad2853d02781ad9fee33f05e5aMahesh Rajashekhara	dev->sync_mode = 0;	/* sync. mode not supported */
6478ef2224707996aede1808f40116cd467b7c8d549Salyzyn, Mark	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
6488ef2224707996aede1808f40116cd467b7c8d549Salyzyn, Mark	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
64928713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
6508ef2224707996aede1808f40116cd467b7c8d549Salyzyn, Mark		if (dev->msi)
6518ef2224707996aede1808f40116cd467b7c8d549Salyzyn, Mark			pci_disable_msi(dev->pdev);
65228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
65328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp			name, instance);
65428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp		goto error_iounmap;
65528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	}
656e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara	dev->dbg_base = dev->scsi_host_ptr->base;
657e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara	dev->dbg_base_mapped = dev->base;
658e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara	dev->dbg_size = dev->base_size;
659e8b12f0fb8352237525961f14ec933e915848840Mahesh Rajashekhara
66028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_adapter_enable_int(dev);
66128713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	/*
66228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 *	Tell the adapter that all is configured, and it can
66328713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 * start accepting requests
66428713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	 */
66528713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	aac_rx_start_adapter(dev);
6668e0c5ebde82b08f6d996e11983890fc4cc085fabMark Haverkamp
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror_iounmap:
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
67376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp
67476a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkampint aac_rx_init(struct aac_dev *dev)
67576a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp{
67676a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	/*
67776a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	 *	Fill in the function dispatch table.
67876a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	 */
67976a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp	dev->a_ops.adapter_ioremap = aac_rx_ioremap;
68028713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	dev->a_ops.adapter_comm = aac_rx_select_comm;
68176a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp
68228713324a0f3c055186ecec27239673c36ba1de5Mark Haverkamp	return _aac_rx_init(dev);
68376a7f8fdc0c2381ae1ba55ef71837712223ecb3cMark Haverkamp}
684