/*
* Aic94xx SAS/SATA driver sequencer interface.
*
* Copyright (C) 2005 Adaptec, Inc. All rights reserved.
* Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
*
* Parts of this code adapted from David Chaw's adp94xx_seq.c.
*
* This file is licensed under GPLv2.
*
* This file is part of the aic94xx driver.
*
* The aic94xx driver is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* The aic94xx driver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the aic94xx driver; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/firmware.h>
#include "aic94xx_reg.h"
#include "aic94xx_hwi.h"
#include "aic94xx_seq.h"
#include "aic94xx_dump.h"
/* It takes no more than 0.05 us for an instruction
* to complete. So waiting for 1 us should be more than
* plenty.
*/
#define PAUSE_DELAY 1
#define PAUSE_TRIES 1000
static const struct firmware *sequencer_fw;
static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task,
cseq_idle_loop, lseq_idle_loop;
static const u8 *cseq_code, *lseq_code;
static u32 cseq_code_size, lseq_code_size;
static u16 first_scb_site_no = 0xFFFF;
static u16 last_scb_site_no;
/* ---------- Pause/Unpause CSEQ/LSEQ ---------- */
/**
* asd_pause_cseq - pause the central sequencer
* @asd_ha: pointer to host adapter structure
*
* Return 0 on success, negative on failure.
*/
static int asd_pause_cseq(struct asd_ha_struct *asd_ha)
{
int count = PAUSE_TRIES;
u32 arp2ctl;
arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL);
if (arp2ctl & PAUSED)
return 0;
asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl | EPAUSE);
do {
arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL);
if (a