1edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
2edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    Disk Array driver for HP Smart Array SAS controllers
3edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
4edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
5edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    This program is free software; you can redistribute it and/or modify
6edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    it under the terms of the GNU General Public License as published by
7edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    the Free Software Foundation; version 2 of the License.
8edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
9edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    This program is distributed in the hope that it will be useful,
10edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    NON INFRINGEMENT.  See the GNU General Public License for more details.
13edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
14edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    You should have received a copy of the GNU General Public License
15edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    along with this program; if not, write to the Free Software
16edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
18edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
19edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
20edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
21edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#ifndef HPSA_H
22edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_H
23edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
24edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#include <scsi/scsicam.h>
25edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
26edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define IO_OK		0
27edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define IO_ERROR	1
28edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
29edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstruct ctlr_info;
30edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
31edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstruct access_method {
32edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	void (*submit_command)(struct ctlr_info *h,
33edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		struct CommandList *c);
34edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
35edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long (*fifo_full)(struct ctlr_info *h);
36900c54404a9456b3ff10745e5e8f64b12c3a6ef7Stephen M. Cameron	bool (*intr_pending)(struct ctlr_info *h);
37edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long (*command_completed)(struct ctlr_info *h);
38edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron};
39edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
40edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstruct hpsa_scsi_dev_t {
41edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int devtype;
42edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int bus, target, lun;		/* as presented to the OS */
43edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned char scsi3addr[8];	/* as presented to the HW */
44edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
45edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned char device_id[16];    /* from inquiry pg. 0x83 */
46edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
47edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned char model[16];        /* bytes 16-31 of inquiry data */
48edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned char raid_level;	/* from inquiry page 0xC1 */
49edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron};
50edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
51edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstruct ctlr_info {
52edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int	ctlr;
53edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	char	devname[8];
54edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	char    *product_name;
55edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct pci_dev *pdev;
5601a02ffcd55b74e3459bb7358140970e126d4731Stephen M. Cameron	u32	board_id;
57edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	void __iomem *vaddr;
58edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long paddr;
59edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int 	nr_cmds; /* Number of commands allowed on this controller */
60edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct CfgTable __iomem *cfgtable;
61edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int	interrupts_enabled;
62edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int	major;
63edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int 	max_commands;
64edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int	commands_outstanding;
65edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int 	max_outstanding; /* Debug */
66edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int	usage_count;  /* number of opens all all minor devices */
67303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#	define PERF_MODE_INT	0
68303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#	define DOORBELL_INT	1
69edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#	define SIMPLE_MODE_INT	2
70edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#	define MEMQ_MODE_INT	3
71edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int intr[4];
72edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int msix_vector;
73edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int msi_vector;
74a9a3a2739a44fc05dcaba0d4d36e52dc444c294fStephen M. Cameron	int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
75edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct access_method access;
76edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
77edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	/* queue and queue Info */
789e0fc764eaec082cd2ffcf82568dfdd086935934Stephen M. Cameron	struct list_head reqQ;
799e0fc764eaec082cd2ffcf82568dfdd086935934Stephen M. Cameron	struct list_head cmpQ;
80edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int Qdepth;
81edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int maxQsinceinit;
82edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned int maxSG;
83edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	spinlock_t lock;
8433a2ffce51d9598380d73c515a27fc6cff3bd9c4Stephen M. Cameron	int maxsgentries;
8533a2ffce51d9598380d73c515a27fc6cff3bd9c4Stephen M. Cameron	u8 max_cmd_sg_entries;
8633a2ffce51d9598380d73c515a27fc6cff3bd9c4Stephen M. Cameron	int chainsize;
8733a2ffce51d9598380d73c515a27fc6cff3bd9c4Stephen M. Cameron	struct SGDescriptor **cmd_sg_list;
88edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
89edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	/* pointers to command and error info pool */
90edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct CommandList 	*cmd_pool;
91edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	dma_addr_t		cmd_pool_dhandle;
92edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct ErrorInfo 	*errinfo_pool;
93edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	dma_addr_t		errinfo_pool_dhandle;
94edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long  		*cmd_pool_bits;
95edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int			nr_allocs;
96edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int			nr_frees;
97a08a8471b7aed3d50df8e9c852dc2baa08ec8b01Stephen M. Cameron	int			scan_finished;
98a08a8471b7aed3d50df8e9c852dc2baa08ec8b01Stephen M. Cameron	spinlock_t		scan_lock;
99a08a8471b7aed3d50df8e9c852dc2baa08ec8b01Stephen M. Cameron	wait_queue_head_t	scan_wait_queue;
100edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
101edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct Scsi_Host *scsi_host;
102edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	spinlock_t devlock; /* to protect hba[ctlr]->dev[];  */
103edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	int ndevices; /* number of used elements in .dev[] array. */
104cfe5badcab2e993e71ebebbc07c21c270e5580c0Scott Teel	struct hpsa_scsi_dev_t *dev[HPSA_MAX_DEVICES];
105303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/*
106303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 * Performant mode tables.
107303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 */
108303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	u32 trans_support;
109303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	u32 trans_offset;
110303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	struct TransTable_struct *transtable;
111303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	unsigned long transMethod;
112303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
113303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/*
114303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 * Performant mode completion buffer
115303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 */
116303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	u64 *reply_pool;
117303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	dma_addr_t reply_pool_dhandle;
118303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	u64 *reply_pool_head;
119303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	size_t reply_pool_size;
120303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	unsigned char reply_pool_wraparound;
121303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	u32 *blockFetchTable;
122339b2b14c634da58626eb742370d915591c2fb6dStephen M. Cameron	unsigned char *hba_inquiry_data;
123a0c124137a40fc22730ae87caf17e821f2dce1edStephen M. Cameron	u64 last_intr_timestamp;
124a0c124137a40fc22730ae87caf17e821f2dce1edStephen M. Cameron	u32 last_heartbeat;
125a0c124137a40fc22730ae87caf17e821f2dce1edStephen M. Cameron	u64 last_heartbeat_timestamp;
126a0c124137a40fc22730ae87caf17e821f2dce1edStephen M. Cameron	u32 lockup_detected;
127a0c124137a40fc22730ae87caf17e821f2dce1edStephen M. Cameron	struct list_head lockup_list;
128edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron};
129edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_ABORT_MSG 0
130edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_DEVICE_RESET_MSG 1
13164670ac8702ec37a00ad6e479f3cacbde0fd4efaStephen M. Cameron#define HPSA_RESET_TYPE_CONTROLLER 0x00
13264670ac8702ec37a00ad6e479f3cacbde0fd4efaStephen M. Cameron#define HPSA_RESET_TYPE_BUS 0x01
13364670ac8702ec37a00ad6e479f3cacbde0fd4efaStephen M. Cameron#define HPSA_RESET_TYPE_TARGET 0x03
13464670ac8702ec37a00ad6e479f3cacbde0fd4efaStephen M. Cameron#define HPSA_RESET_TYPE_LUN 0x04
135edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_MSG_SEND_RETRY_LIMIT 10
136516fda49e8596904a741693059c8746f11ce579cStephen M. Cameron#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000)
137edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
138edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/* Maximum time in seconds driver will wait for command completions
139edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * when polling before giving up.
140edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
141edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_MAX_POLL_TIME_SECS (20)
142edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
143edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/* During SCSI error recovery, HPSA_TUR_RETRY_LIMIT defines
144edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * how many times to retry TEST UNIT READY on a device
145edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * while waiting for it to become ready before giving up.
146edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * HPSA_MAX_WAIT_INTERVAL_SECS is the max wait interval
147edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * between sending TURs while waiting for a device
148edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * to become ready.
149edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
150edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_TUR_RETRY_LIMIT (20)
151edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_MAX_WAIT_INTERVAL_SECS (30)
152edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
153edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/* HPSA_BOARD_READY_WAIT_SECS is how long to wait for a board
154edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * to become ready, in seconds, before giving up on it.
155edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * HPSA_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait
156edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * between polling the board to see if it is ready, in
157edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * milliseconds.  HPSA_BOARD_READY_POLL_INTERVAL and
158edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * HPSA_BOARD_READY_ITERATIONS are derived from those.
159edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
160edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_BOARD_READY_WAIT_SECS (120)
1612ed7127bceb10a6a7d5a38c30ab65176d4e4bc0fStephen M. Cameron#define HPSA_BOARD_NOT_READY_WAIT_SECS (100)
162edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
163edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_BOARD_READY_POLL_INTERVAL \
164edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
165edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_BOARD_READY_ITERATIONS \
166edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
167edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
168fe5389c87f13c16cd77d976801c93422d0c05a49Stephen M. Cameron#define HPSA_BOARD_NOT_READY_ITERATIONS \
169fe5389c87f13c16cd77d976801c93422d0c05a49Stephen M. Cameron	((HPSA_BOARD_NOT_READY_WAIT_SECS * 1000) / \
170fe5389c87f13c16cd77d976801c93422d0c05a49Stephen M. Cameron		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
171edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_POST_RESET_PAUSE_MSECS (3000)
172edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_POST_RESET_NOOP_RETRIES (12)
173edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
174edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*  Defining the diffent access_menthods */
175edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
176edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron * Memory mapped FIFO interface (SMART 53xx cards)
177edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
178edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_DOORBELL	0x20
179edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_REQUEST_PORT_OFFSET	0x40
180edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_REPLY_INTR_MASK_OFFSET	0x34
181edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_REPLY_PORT_OFFSET		0x44
182edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_INTR_STATUS		0x30
183edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_SCRATCHPAD_OFFSET	0xB0
184edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
185edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_CTCFG_OFFSET	0xB4
186edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_CTMEM_OFFSET	0xB8
187edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
188edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_INTR_OFF		0x08
189edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5B_INTR_OFF		0x04
190edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5_INTR_PENDING	0x08
191edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define SA5B_INTR_PENDING	0x04
192edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define FIFO_EMPTY		0xffffffff
193edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_FIRMWARE_READY	0xffff0000 /* value in scratchpad register */
194edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
195edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_ERROR_BIT		0x02
196edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
197303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace/* Performant mode flags */
198303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_PERF_INTR_PENDING   0x04
199303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_PERF_INTR_OFF       0x05
200303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_OUTDB_STATUS_PERF_BIT       0x01
201303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_OUTDB_CLEAR_PERF_BIT        0x01
202303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_OUTDB_CLEAR         0xA0
203303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_OUTDB_CLEAR_PERF_BIT        0x01
204303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace#define SA5_OUTDB_STATUS        0x9C
205303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
206303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
207edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_INTR_ON 	1
208edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#define HPSA_INTR_OFF	0
209edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
210edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	Send the command to the hardware
211edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron*/
212edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstatic void SA5_submit_command(struct ctlr_info *h,
213edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct CommandList *c)
214edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron{
215303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr,
216303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		c->Header.Tag.lower);
217edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
218fec62c368b9c8b05d5124ca6c3b8336b537f26f3Stephen M. Cameron	(void) readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
219edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	h->commands_outstanding++;
220edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	if (h->commands_outstanding > h->max_outstanding)
221edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		h->max_outstanding = h->commands_outstanding;
222edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron}
223edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
224edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
225edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *  This card is the opposite of the other cards.
226edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *   0 turns interrupts on...
227edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *   0x08 turns them off...
228edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
229edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstatic void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
230edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron{
231edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	if (val) { /* Turn interrupts on */
232edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		h->interrupts_enabled = 1;
233edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
2348cd21da71c952843f9cc215436286cf7f991cc6eStephen M. Cameron		(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
235edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	} else { /* Turn them off */
236edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		h->interrupts_enabled = 0;
237edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		writel(SA5_INTR_OFF,
238edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron			h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
2398cd21da71c952843f9cc215436286cf7f991cc6eStephen M. Cameron		(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
240edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	}
241edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron}
242303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
243303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Bracestatic void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
244303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace{
245303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if (val) { /* turn on interrupts */
246303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		h->interrupts_enabled = 1;
247303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
2488cd21da71c952843f9cc215436286cf7f991cc6eStephen M. Cameron		(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
249303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	} else {
250303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		h->interrupts_enabled = 0;
251303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		writel(SA5_PERF_INTR_OFF,
252303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace			h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
2538cd21da71c952843f9cc215436286cf7f991cc6eStephen M. Cameron		(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
254303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	}
255303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace}
256303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
257303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Bracestatic unsigned long SA5_performant_completed(struct ctlr_info *h)
258303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace{
259303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	unsigned long register_value = FIFO_EMPTY;
260303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
261303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/* flush the controller write of the reply queue by reading
262303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 * outbound doorbell status register.
263303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	 */
264303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
265303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/* msi auto clears the interrupt pending bit. */
266303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if (!(h->msi_vector || h->msix_vector)) {
267303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
268303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		/* Do a read in order to flush the write to the controller
269303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		 * (as per spec.)
270303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		 */
271303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
272303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	}
273303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
274303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
275303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		register_value = *(h->reply_pool_head);
276303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		(h->reply_pool_head)++;
277303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		h->commands_outstanding--;
278303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	} else {
279303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		register_value = FIFO_EMPTY;
280303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	}
281303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/* Check for wraparound */
282303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
283303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		h->reply_pool_head = h->reply_pool;
284303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		h->reply_pool_wraparound ^= 1;
285303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	}
286303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
287303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	return register_value;
288303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace}
289303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
290edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
291edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *  Returns true if fifo is full.
292edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *
293edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
294edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstatic unsigned long SA5_fifo_full(struct ctlr_info *h)
295edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron{
296edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	if (h->commands_outstanding >= h->max_commands)
297edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		return 1;
298edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	else
299edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		return 0;
300edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
301edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron}
302edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
303edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *   returns value read from hardware.
304edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *     returns FIFO_EMPTY if there is nothing to read
305edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
306edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstatic unsigned long SA5_completed(struct ctlr_info *h)
307edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron{
308edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long register_value
309edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
310edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
311edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	if (register_value != FIFO_EMPTY)
312edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		h->commands_outstanding--;
313edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
314edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#ifdef HPSA_DEBUG
315edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	if (register_value != FIFO_EMPTY)
31684ca0be2a2cd9730683310b831db9d2fa60b3b0bStephen M. Cameron		dev_dbg(&h->pdev->dev, "Read %lx back from board\n",
317edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron			register_value);
318edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	else
319f79cfec6b1906ab10ef70dccd601db25c97bae17Stephen M. Cameron		dev_dbg(&h->pdev->dev, "FIFO Empty read\n");
320edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#endif
321edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
322edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	return register_value;
323edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron}
324edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron/*
325edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron *	Returns true if an interrupt is pending..
326edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron */
327900c54404a9456b3ff10745e5e8f64b12c3a6ef7Stephen M. Cameronstatic bool SA5_intr_pending(struct ctlr_info *h)
328edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron{
329edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	unsigned long register_value  =
330edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron		readl(h->vaddr + SA5_INTR_STATUS);
33184ca0be2a2cd9730683310b831db9d2fa60b3b0bStephen M. Cameron	dev_dbg(&h->pdev->dev, "intr_pending %lx\n", register_value);
332900c54404a9456b3ff10745e5e8f64b12c3a6ef7Stephen M. Cameron	return register_value & SA5_INTR_PENDING;
333edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron}
334edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
335303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Bracestatic bool SA5_performant_intr_pending(struct ctlr_info *h)
336303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace{
337303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS);
338303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
339303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if (!register_value)
340303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		return false;
341303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
342303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	if (h->msi_vector || h->msix_vector)
343303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace		return true;
344303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
345303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	/* Read outbound doorbell to flush */
346303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
347303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	return register_value & SA5_OUTDB_STATUS_PERF_BIT;
348303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace}
349edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
350edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstatic struct access_method SA5_access = {
351edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	SA5_submit_command,
352edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	SA5_intr_mask,
353edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	SA5_fifo_full,
354edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	SA5_intr_pending,
355edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	SA5_completed,
356edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron};
357edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
358303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Bracestatic struct access_method SA5_performant_access = {
359303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	SA5_submit_command,
360303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	SA5_performant_intr_mask,
361303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	SA5_fifo_full,
362303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	SA5_performant_intr_pending,
363303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace	SA5_performant_completed,
364303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace};
365303932fd4ff63e8650d5d5da6cc286a8b5f8318dDon Brace
366edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameronstruct board_type {
36701a02ffcd55b74e3459bb7358140970e126d4731Stephen M. Cameron	u32	board_id;
368edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	char	*product_name;
369edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron	struct access_method *access;
370edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron};
371edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
372edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron#endif /* HPSA_H */
373edd163687ea59f01d6b43c9e1fdaa0126fa30191Stephen M. Cameron
374