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