18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Adaptec AAC series RAID controller driver 48c2ecf20Sopenharmony_ci * (c) Copyright 2001 Red Hat Inc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * based on the old aacraid driver that is.. 78c2ecf20Sopenharmony_ci * Adaptec aacraid device driver for Linux. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Copyright (c) 2000-2010 Adaptec, Inc. 108c2ecf20Sopenharmony_ci * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) 118c2ecf20Sopenharmony_ci * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Module Name: 148c2ecf20Sopenharmony_ci * sa.c 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Abstract: Drawbridge specific support functions 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/kernel.h> 208c2ecf20Sopenharmony_ci#include <linux/init.h> 218c2ecf20Sopenharmony_ci#include <linux/types.h> 228c2ecf20Sopenharmony_ci#include <linux/pci.h> 238c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 248c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 258c2ecf20Sopenharmony_ci#include <linux/delay.h> 268c2ecf20Sopenharmony_ci#include <linux/completion.h> 278c2ecf20Sopenharmony_ci#include <linux/time.h> 288c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "aacraid.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic irqreturn_t aac_sa_intr(int irq, void *dev_id) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct aac_dev *dev = dev_id; 378c2ecf20Sopenharmony_ci unsigned short intstat, mask; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci intstat = sa_readw(dev, DoorbellReg_p); 408c2ecf20Sopenharmony_ci /* 418c2ecf20Sopenharmony_ci * Read mask and invert because drawbridge is reversed. 428c2ecf20Sopenharmony_ci * This allows us to only service interrupts that have been enabled. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK)); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* Check to see if this is our interrupt. If it isn't just return */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (intstat & mask) { 498c2ecf20Sopenharmony_ci if (intstat & PrintfReady) { 508c2ecf20Sopenharmony_ci aac_printf(dev, sa_readl(dev, Mailbox5)); 518c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ 528c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s, PrintfDone); 538c2ecf20Sopenharmony_ci } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready 548c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); 558c2ecf20Sopenharmony_ci aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); 568c2ecf20Sopenharmony_ci } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready 578c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); 588c2ecf20Sopenharmony_ci aac_response_normal(&dev->queues->queue[HostNormRespQueue]); 598c2ecf20Sopenharmony_ci } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full 608c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); 618c2ecf20Sopenharmony_ci } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full 628c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_4); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci return IRQ_HANDLED; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci return IRQ_NONE; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/** 708c2ecf20Sopenharmony_ci * aac_sa_disable_interrupt - disable interrupt 718c2ecf20Sopenharmony_ci * @dev: Which adapter to enable. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic void aac_sa_disable_interrupt (struct aac_dev *dev) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/** 808c2ecf20Sopenharmony_ci * aac_sa_enable_interrupt - enable interrupt 818c2ecf20Sopenharmony_ci * @dev: Which adapter to enable. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void aac_sa_enable_interrupt (struct aac_dev *dev) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | 878c2ecf20Sopenharmony_ci DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/** 918c2ecf20Sopenharmony_ci * aac_sa_notify_adapter - handle adapter notification 928c2ecf20Sopenharmony_ci * @dev: Adapter that notification is for 938c2ecf20Sopenharmony_ci * @event: Event to notidy 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * Notify the adapter of an event 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic void aac_sa_notify_adapter(struct aac_dev *dev, u32 event) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci switch (event) { 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci case AdapNormCmdQue: 1038c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_1); 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci case HostNormRespNotFull: 1068c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_4); 1078c2ecf20Sopenharmony_ci break; 1088c2ecf20Sopenharmony_ci case AdapNormRespQue: 1098c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_2); 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci case HostNormCmdNotFull: 1128c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_3); 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case HostShutdown: 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0, 1178c2ecf20Sopenharmony_ci NULL, NULL, NULL, NULL, NULL); 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci break; 1208c2ecf20Sopenharmony_ci case FastIo: 1218c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_6); 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci case AdapPrintfDone: 1248c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s,DOORBELL_5); 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci default: 1278c2ecf20Sopenharmony_ci BUG(); 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/** 1348c2ecf20Sopenharmony_ci * sa_sync_cmd - send a command and wait 1358c2ecf20Sopenharmony_ci * @dev: Adapter 1368c2ecf20Sopenharmony_ci * @command: Command to execute 1378c2ecf20Sopenharmony_ci * @p1: first parameter 1388c2ecf20Sopenharmony_ci * @p2: second parameter 1398c2ecf20Sopenharmony_ci * @p3: third parameter 1408c2ecf20Sopenharmony_ci * @p4: forth parameter 1418c2ecf20Sopenharmony_ci * @p5: fifth parameter 1428c2ecf20Sopenharmony_ci * @p6: sixth parameter 1438c2ecf20Sopenharmony_ci * @ret: adapter status 1448c2ecf20Sopenharmony_ci * @r1: first return value 1458c2ecf20Sopenharmony_ci * @r2: second return value 1468c2ecf20Sopenharmony_ci * @r3: third return value 1478c2ecf20Sopenharmony_ci * @r4: forth return value 1488c2ecf20Sopenharmony_ci * 1498c2ecf20Sopenharmony_ci * This routine will send a synchronous command to the adapter and wait 1508c2ecf20Sopenharmony_ci * for its completion. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic int sa_sync_cmd(struct aac_dev *dev, u32 command, 1538c2ecf20Sopenharmony_ci u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, 1548c2ecf20Sopenharmony_ci u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci unsigned long start; 1578c2ecf20Sopenharmony_ci int ok; 1588c2ecf20Sopenharmony_ci /* 1598c2ecf20Sopenharmony_ci * Write the Command into Mailbox 0 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_ci sa_writel(dev, Mailbox0, command); 1628c2ecf20Sopenharmony_ci /* 1638c2ecf20Sopenharmony_ci * Write the parameters into Mailboxes 1 - 4 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_ci sa_writel(dev, Mailbox1, p1); 1668c2ecf20Sopenharmony_ci sa_writel(dev, Mailbox2, p2); 1678c2ecf20Sopenharmony_ci sa_writel(dev, Mailbox3, p3); 1688c2ecf20Sopenharmony_ci sa_writel(dev, Mailbox4, p4); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* 1718c2ecf20Sopenharmony_ci * Clear the synch command doorbell to start on a clean slate. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); 1748c2ecf20Sopenharmony_ci /* 1758c2ecf20Sopenharmony_ci * Signal that there is a new synch command 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellReg_s, DOORBELL_0); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci ok = 0; 1808c2ecf20Sopenharmony_ci start = jiffies; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci while(time_before(jiffies, start+30*HZ)) 1838c2ecf20Sopenharmony_ci { 1848c2ecf20Sopenharmony_ci /* 1858c2ecf20Sopenharmony_ci * Delay 5uS so that the monitor gets access 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci udelay(5); 1888c2ecf20Sopenharmony_ci /* 1898c2ecf20Sopenharmony_ci * Mon110 will set doorbell0 bit when it has 1908c2ecf20Sopenharmony_ci * completed the command. 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0) { 1938c2ecf20Sopenharmony_ci ok = 1; 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci msleep(1); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (ok != 1) 2008c2ecf20Sopenharmony_ci return -ETIMEDOUT; 2018c2ecf20Sopenharmony_ci /* 2028c2ecf20Sopenharmony_ci * Clear the synch command doorbell. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_ci sa_writew(dev, DoorbellClrReg_p, DOORBELL_0); 2058c2ecf20Sopenharmony_ci /* 2068c2ecf20Sopenharmony_ci * Pull the synch status from Mailbox 0. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci if (ret) 2098c2ecf20Sopenharmony_ci *ret = sa_readl(dev, Mailbox0); 2108c2ecf20Sopenharmony_ci if (r1) 2118c2ecf20Sopenharmony_ci *r1 = sa_readl(dev, Mailbox1); 2128c2ecf20Sopenharmony_ci if (r2) 2138c2ecf20Sopenharmony_ci *r2 = sa_readl(dev, Mailbox2); 2148c2ecf20Sopenharmony_ci if (r3) 2158c2ecf20Sopenharmony_ci *r3 = sa_readl(dev, Mailbox3); 2168c2ecf20Sopenharmony_ci if (r4) 2178c2ecf20Sopenharmony_ci *r4 = sa_readl(dev, Mailbox4); 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci/** 2228c2ecf20Sopenharmony_ci * aac_sa_interrupt_adapter - interrupt an adapter 2238c2ecf20Sopenharmony_ci * @dev: Which adapter to enable. 2248c2ecf20Sopenharmony_ci * 2258c2ecf20Sopenharmony_ci * Breakpoint an adapter. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic void aac_sa_interrupt_adapter (struct aac_dev *dev) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, 2318c2ecf20Sopenharmony_ci NULL, NULL, NULL, NULL, NULL); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/** 2358c2ecf20Sopenharmony_ci * aac_sa_start_adapter - activate adapter 2368c2ecf20Sopenharmony_ci * @dev: Adapter 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci * Start up processing on an ARM based AAC adapter 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic void aac_sa_start_adapter(struct aac_dev *dev) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci union aac_init *init; 2448c2ecf20Sopenharmony_ci /* 2458c2ecf20Sopenharmony_ci * Fill in the remaining pieces of the init. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_ci init = dev->init; 2488c2ecf20Sopenharmony_ci init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds()); 2498c2ecf20Sopenharmony_ci /* We can only use a 32 bit address here */ 2508c2ecf20Sopenharmony_ci sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 2518c2ecf20Sopenharmony_ci (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0, 2528c2ecf20Sopenharmony_ci NULL, NULL, NULL, NULL, NULL); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci return -EINVAL; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * aac_sa_check_health 2628c2ecf20Sopenharmony_ci * @dev: device to check if healthy 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * Will attempt to determine if the specified adapter is alive and 2658c2ecf20Sopenharmony_ci * capable of handling requests, returning 0 if alive. 2668c2ecf20Sopenharmony_ci */ 2678c2ecf20Sopenharmony_cistatic int aac_sa_check_health(struct aac_dev *dev) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci long status = sa_readl(dev, Mailbox7); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* 2728c2ecf20Sopenharmony_ci * Check to see if the board failed any self tests. 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_ci if (status & SELF_TEST_FAILED) 2758c2ecf20Sopenharmony_ci return -1; 2768c2ecf20Sopenharmony_ci /* 2778c2ecf20Sopenharmony_ci * Check to see if the board panic'd while booting. 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci if (status & KERNEL_PANIC) 2808c2ecf20Sopenharmony_ci return -2; 2818c2ecf20Sopenharmony_ci /* 2828c2ecf20Sopenharmony_ci * Wait for the adapter to be up and running. Wait up to 3 minutes 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_ci if (!(status & KERNEL_UP_AND_RUNNING)) 2858c2ecf20Sopenharmony_ci return -3; 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * Everything is OK 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** 2938c2ecf20Sopenharmony_ci * aac_sa_ioremap 2948c2ecf20Sopenharmony_ci * @dev: device to ioremap 2958c2ecf20Sopenharmony_ci * @size: mapping resize request 2968c2ecf20Sopenharmony_ci * 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_cistatic int aac_sa_ioremap(struct aac_dev * dev, u32 size) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci if (!size) { 3018c2ecf20Sopenharmony_ci iounmap(dev->regs.sa); 3028c2ecf20Sopenharmony_ci return 0; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci dev->base = dev->regs.sa = ioremap(dev->base_start, size); 3058c2ecf20Sopenharmony_ci return (dev->base == NULL) ? -1 : 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/** 3098c2ecf20Sopenharmony_ci * aac_sa_init - initialize an ARM based AAC card 3108c2ecf20Sopenharmony_ci * @dev: device to configure 3118c2ecf20Sopenharmony_ci * 3128c2ecf20Sopenharmony_ci * Allocate and set up resources for the ARM based AAC variants. The 3138c2ecf20Sopenharmony_ci * device_interface in the commregion will be allocated and linked 3148c2ecf20Sopenharmony_ci * to the comm region. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ciint aac_sa_init(struct aac_dev *dev) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci unsigned long start; 3208c2ecf20Sopenharmony_ci unsigned long status; 3218c2ecf20Sopenharmony_ci int instance; 3228c2ecf20Sopenharmony_ci const char *name; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci instance = dev->id; 3258c2ecf20Sopenharmony_ci name = dev->name; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* 3288c2ecf20Sopenharmony_ci * Fill in the function dispatch table. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; 3328c2ecf20Sopenharmony_ci dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; 3338c2ecf20Sopenharmony_ci dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; 3348c2ecf20Sopenharmony_ci dev->a_ops.adapter_notify = aac_sa_notify_adapter; 3358c2ecf20Sopenharmony_ci dev->a_ops.adapter_sync_cmd = sa_sync_cmd; 3368c2ecf20Sopenharmony_ci dev->a_ops.adapter_check_health = aac_sa_check_health; 3378c2ecf20Sopenharmony_ci dev->a_ops.adapter_restart = aac_sa_restart_adapter; 3388c2ecf20Sopenharmony_ci dev->a_ops.adapter_start = aac_sa_start_adapter; 3398c2ecf20Sopenharmony_ci dev->a_ops.adapter_intr = aac_sa_intr; 3408c2ecf20Sopenharmony_ci dev->a_ops.adapter_deliver = aac_rx_deliver_producer; 3418c2ecf20Sopenharmony_ci dev->a_ops.adapter_ioremap = aac_sa_ioremap; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (aac_sa_ioremap(dev, dev->base_size)) { 3448c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: unable to map adapter.\n", name); 3458c2ecf20Sopenharmony_ci goto error_iounmap; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* 3498c2ecf20Sopenharmony_ci * Check to see if the board failed any self tests. 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_ci if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) { 3528c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance); 3538c2ecf20Sopenharmony_ci goto error_iounmap; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci /* 3568c2ecf20Sopenharmony_ci * Check to see if the board panic'd while booting. 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_ci if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) { 3598c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance); 3608c2ecf20Sopenharmony_ci goto error_iounmap; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci start = jiffies; 3638c2ecf20Sopenharmony_ci /* 3648c2ecf20Sopenharmony_ci * Wait for the adapter to be up and running. Wait up to 3 minutes. 3658c2ecf20Sopenharmony_ci */ 3668c2ecf20Sopenharmony_ci while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { 3678c2ecf20Sopenharmony_ci if (time_after(jiffies, start+startup_timeout*HZ)) { 3688c2ecf20Sopenharmony_ci status = sa_readl(dev, Mailbox7); 3698c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", 3708c2ecf20Sopenharmony_ci name, instance, status); 3718c2ecf20Sopenharmony_ci goto error_iounmap; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci msleep(1); 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * First clear out all interrupts. Then enable the one's that 3788c2ecf20Sopenharmony_ci * we can handle. 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_ci aac_adapter_disable_int(dev); 3818c2ecf20Sopenharmony_ci aac_adapter_enable_int(dev); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci if(aac_init_adapter(dev) == NULL) 3848c2ecf20Sopenharmony_ci goto error_irq; 3858c2ecf20Sopenharmony_ci dev->sync_mode = 0; /* sync. mode not supported */ 3868c2ecf20Sopenharmony_ci if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, 3878c2ecf20Sopenharmony_ci IRQF_SHARED, "aacraid", (void *)dev) < 0) { 3888c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", 3898c2ecf20Sopenharmony_ci name, instance); 3908c2ecf20Sopenharmony_ci goto error_iounmap; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci dev->dbg_base = dev->base_start; 3938c2ecf20Sopenharmony_ci dev->dbg_base_mapped = dev->base; 3948c2ecf20Sopenharmony_ci dev->dbg_size = dev->base_size; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci aac_adapter_enable_int(dev); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* 3998c2ecf20Sopenharmony_ci * Tell the adapter that all is configure, and it can start 4008c2ecf20Sopenharmony_ci * accepting requests 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ci aac_sa_start_adapter(dev); 4038c2ecf20Sopenharmony_ci return 0; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cierror_irq: 4068c2ecf20Sopenharmony_ci aac_sa_disable_interrupt(dev); 4078c2ecf20Sopenharmony_ci free_irq(dev->pdev->irq, (void *)dev); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cierror_iounmap: 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci return -1; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 414