/*
* SuperTrak EX Series Storage Controller driver for Linux
*
* Copyright (C) 2005, 2006 Promise Technology Inc.
*
* This program 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; either version
* 2 of the License, or (at your option) any later version.
*
* Written By:
* Ed Lin <promise_linux@promise.com>
*
* Version: 2.9.0.13
*
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#define DRV_NAME "stex"
#define ST_DRIVER_VERSION "2.9.0.13"
#define ST_VER_MAJOR 2
#define ST_VER_MINOR 9
#define ST_OEM 0
#define ST_BUILD_VER 13
enum {
/* MU register offset */
IMR0 = 0x10, /* MU_INBOUND_MESSAGE_REG0 */
IMR1 = 0x14, /* MU_INBOUND_MESSAGE_REG1 */
OMR0 = 0x18, /* MU_OUTBOUND_MESSAGE_REG0 */
OMR1 = 0x1c, /* MU_OUTBOUND_MESSAGE_REG1 */
IDBL = 0x20, /* MU_INBOUND_DOORBELL */
IIS = 0x24, /* MU_INBOUND_INTERRUPT_STATUS */
IIM = 0x28, /* MU_INBOUND_INTERRUPT_MASK */
ODBL = 0x2c, /* MU_OUTBOUND_DOORBELL */
OIS = 0x30, /* MU_OUTBOUND_INTERRUPT_STATUS */
OIM = 0x3c, /* MU_OUTBOUND_INTERRUPT_MASK */
/* MU register value */
MU_INBOUND_DOORBELL_HANDSHAKE = 1,
MU_INBOUND_DOORBELL_REQHEADCHANGED = 2,
MU_INBOUND_DOORBELL_STATUSTAILCHANGED = 4,
MU_INBOUND_DOORBELL_HMUSTOPPED = 8,
MU_INBOUND_DOORBELL_RESET = 16,
MU_OUTBOUND_DOORBELL_HANDSHAKE = 1,
MU_OUTBOUND_DOORBELL_REQUESTTAILCHANGED = 2,
MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED = 4,
MU_OUTBOUND_DOORBELL_BUSCHANGE = 8,
MU_OUTBOUND_DOORBELL_HASEVENT = 16,
/* MU status code */
MU_STATE_STARTING = 1,
MU_STATE_FMU_READY_FOR_HANDSHAKE = 2,
MU_STATE_SEND_HANDSHAKE_FRAME = 3,
MU_STATE_STARTED = 4,
MU_STATE_RESETTING = 5,
MU_MAX_DELAY_TIME = 240000,
MU_HANDSHAKE_SIGNATURE = 0x55aaaa55,
HMU_PARTNER_TYPE = 2,
/* firmware returned values */
SRB_STATUS_SUCCESS = 0x01,
SRB_STATUS_ERROR = 0x04,
SRB_STATUS_BUSY = 0x05,
SRB_STATUS_INVALID_REQUEST = 0x06,
SRB_STATUS_SELECTION_TIMEOUT = 0x0A,
SRB_SEE_SENSE = 0x80,
/* task attribute */
TASK_ATTRIBUTE_SIMPLE = 0x0,
TASK_ATTRIBUTE_HEADOFQUEUE = 0x1,
TASK_ATTRIBUTE_ORDERED = 0x2,
TASK_ATTRIBUTE_ACA = 0x4,
/* request count, etc. */
MU_MAX_REQUEST = 32,
/* one message wasted, use MU_MAX_REQUEST+1
to handle MU_MAX_REQUEST messages */
MU_REQ_COUNT = (MU_MAX_REQUEST + 1),
MU_STATUS_COUNT = (MU_MAX_REQUEST + 1),
STEX_CDB_LENGTH = MAX_COMMAND_SIZE,
REQ_VARIABLE_LEN = 1024,
STATUS_VAR_LEN = 128,
ST_CAN_QUEUE = MU_MAX_REQUEST,
ST_CMD_PER_LUN = MU_MAX_REQUEST,
ST_MAX_SG =