diff options
Diffstat (limited to 'drivers/scsi/hpsa.h')
-rw-r--r-- | drivers/scsi/hpsa.h | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h new file mode 100644 index 000000000000..1bb5233b09a0 --- /dev/null +++ b/drivers/scsi/hpsa.h | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Disk Array driver for HP Smart Array SAS controllers | ||
3 | * Copyright 2000, 2009 Hewlett-Packard Development Company, L.P. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
12 | * NON INFRINGEMENT. See the GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | * | ||
18 | * Questions/Comments/Bugfixes to iss_storagedev@hp.com | ||
19 | * | ||
20 | */ | ||
21 | #ifndef HPSA_H | ||
22 | #define HPSA_H | ||
23 | |||
24 | #include <scsi/scsicam.h> | ||
25 | |||
26 | #define IO_OK 0 | ||
27 | #define IO_ERROR 1 | ||
28 | |||
29 | struct ctlr_info; | ||
30 | |||
31 | struct access_method { | ||
32 | void (*submit_command)(struct ctlr_info *h, | ||
33 | struct CommandList *c); | ||
34 | void (*set_intr_mask)(struct ctlr_info *h, unsigned long val); | ||
35 | unsigned long (*fifo_full)(struct ctlr_info *h); | ||
36 | bool (*intr_pending)(struct ctlr_info *h); | ||
37 | unsigned long (*command_completed)(struct ctlr_info *h); | ||
38 | }; | ||
39 | |||
40 | struct hpsa_scsi_dev_t { | ||
41 | int devtype; | ||
42 | int bus, target, lun; /* as presented to the OS */ | ||
43 | unsigned char scsi3addr[8]; /* as presented to the HW */ | ||
44 | #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0" | ||
45 | unsigned char device_id[16]; /* from inquiry pg. 0x83 */ | ||
46 | unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ | ||
47 | unsigned char model[16]; /* bytes 16-31 of inquiry data */ | ||
48 | unsigned char revision[4]; /* bytes 32-35 of inquiry data */ | ||
49 | unsigned char raid_level; /* from inquiry page 0xC1 */ | ||
50 | }; | ||
51 | |||
52 | struct ctlr_info { | ||
53 | int ctlr; | ||
54 | char devname[8]; | ||
55 | char *product_name; | ||
56 | char firm_ver[4]; /* Firmware version */ | ||
57 | struct pci_dev *pdev; | ||
58 | u32 board_id; | ||
59 | void __iomem *vaddr; | ||
60 | unsigned long paddr; | ||
61 | int nr_cmds; /* Number of commands allowed on this controller */ | ||
62 | struct CfgTable __iomem *cfgtable; | ||
63 | int max_sg_entries; | ||
64 | int interrupts_enabled; | ||
65 | int major; | ||
66 | int max_commands; | ||
67 | int commands_outstanding; | ||
68 | int max_outstanding; /* Debug */ | ||
69 | int usage_count; /* number of opens all all minor devices */ | ||
70 | # define PERF_MODE_INT 0 | ||
71 | # define DOORBELL_INT 1 | ||
72 | # define SIMPLE_MODE_INT 2 | ||
73 | # define MEMQ_MODE_INT 3 | ||
74 | unsigned int intr[4]; | ||
75 | unsigned int msix_vector; | ||
76 | unsigned int msi_vector; | ||
77 | struct access_method access; | ||
78 | |||
79 | /* queue and queue Info */ | ||
80 | struct hlist_head reqQ; | ||
81 | struct hlist_head cmpQ; | ||
82 | unsigned int Qdepth; | ||
83 | unsigned int maxQsinceinit; | ||
84 | unsigned int maxSG; | ||
85 | spinlock_t lock; | ||
86 | int maxsgentries; | ||
87 | u8 max_cmd_sg_entries; | ||
88 | int chainsize; | ||
89 | struct SGDescriptor **cmd_sg_list; | ||
90 | |||
91 | /* pointers to command and error info pool */ | ||
92 | struct CommandList *cmd_pool; | ||
93 | dma_addr_t cmd_pool_dhandle; | ||
94 | struct ErrorInfo *errinfo_pool; | ||
95 | dma_addr_t errinfo_pool_dhandle; | ||
96 | unsigned long *cmd_pool_bits; | ||
97 | int nr_allocs; | ||
98 | int nr_frees; | ||
99 | int busy_initializing; | ||
100 | int busy_scanning; | ||
101 | int scan_finished; | ||
102 | spinlock_t scan_lock; | ||
103 | wait_queue_head_t scan_wait_queue; | ||
104 | |||
105 | struct Scsi_Host *scsi_host; | ||
106 | spinlock_t devlock; /* to protect hba[ctlr]->dev[]; */ | ||
107 | int ndevices; /* number of used elements in .dev[] array. */ | ||
108 | #define HPSA_MAX_SCSI_DEVS_PER_HBA 256 | ||
109 | struct hpsa_scsi_dev_t *dev[HPSA_MAX_SCSI_DEVS_PER_HBA]; | ||
110 | /* | ||
111 | * Performant mode tables. | ||
112 | */ | ||
113 | u32 trans_support; | ||
114 | u32 trans_offset; | ||
115 | struct TransTable_struct *transtable; | ||
116 | unsigned long transMethod; | ||
117 | |||
118 | /* | ||
119 | * Performant mode completion buffer | ||
120 | */ | ||
121 | u64 *reply_pool; | ||
122 | dma_addr_t reply_pool_dhandle; | ||
123 | u64 *reply_pool_head; | ||
124 | size_t reply_pool_size; | ||
125 | unsigned char reply_pool_wraparound; | ||
126 | u32 *blockFetchTable; | ||
127 | unsigned char *hba_inquiry_data; | ||
128 | }; | ||
129 | #define HPSA_ABORT_MSG 0 | ||
130 | #define HPSA_DEVICE_RESET_MSG 1 | ||
131 | #define HPSA_BUS_RESET_MSG 2 | ||
132 | #define HPSA_HOST_RESET_MSG 3 | ||
133 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 | ||
134 | #define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS 1000 | ||
135 | |||
136 | /* Maximum time in seconds driver will wait for command completions | ||
137 | * when polling before giving up. | ||
138 | */ | ||
139 | #define HPSA_MAX_POLL_TIME_SECS (20) | ||
140 | |||
141 | /* During SCSI error recovery, HPSA_TUR_RETRY_LIMIT defines | ||
142 | * how many times to retry TEST UNIT READY on a device | ||
143 | * while waiting for it to become ready before giving up. | ||
144 | * HPSA_MAX_WAIT_INTERVAL_SECS is the max wait interval | ||
145 | * between sending TURs while waiting for a device | ||
146 | * to become ready. | ||
147 | */ | ||
148 | #define HPSA_TUR_RETRY_LIMIT (20) | ||
149 | #define HPSA_MAX_WAIT_INTERVAL_SECS (30) | ||
150 | |||
151 | /* HPSA_BOARD_READY_WAIT_SECS is how long to wait for a board | ||
152 | * to become ready, in seconds, before giving up on it. | ||
153 | * HPSA_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait | ||
154 | * between polling the board to see if it is ready, in | ||
155 | * milliseconds. HPSA_BOARD_READY_POLL_INTERVAL and | ||
156 | * HPSA_BOARD_READY_ITERATIONS are derived from those. | ||
157 | */ | ||
158 | #define HPSA_BOARD_READY_WAIT_SECS (120) | ||
159 | #define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100) | ||
160 | #define HPSA_BOARD_READY_POLL_INTERVAL \ | ||
161 | ((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000) | ||
162 | #define HPSA_BOARD_READY_ITERATIONS \ | ||
163 | ((HPSA_BOARD_READY_WAIT_SECS * 1000) / \ | ||
164 | HPSA_BOARD_READY_POLL_INTERVAL_MSECS) | ||
165 | #define HPSA_POST_RESET_PAUSE_MSECS (3000) | ||
166 | #define HPSA_POST_RESET_NOOP_RETRIES (12) | ||
167 | |||
168 | /* Defining the diffent access_menthods */ | ||
169 | /* | ||
170 | * Memory mapped FIFO interface (SMART 53xx cards) | ||
171 | */ | ||
172 | #define SA5_DOORBELL 0x20 | ||
173 | #define SA5_REQUEST_PORT_OFFSET 0x40 | ||
174 | #define SA5_REPLY_INTR_MASK_OFFSET 0x34 | ||
175 | #define SA5_REPLY_PORT_OFFSET 0x44 | ||
176 | #define SA5_INTR_STATUS 0x30 | ||
177 | #define SA5_SCRATCHPAD_OFFSET 0xB0 | ||
178 | |||
179 | #define SA5_CTCFG_OFFSET 0xB4 | ||
180 | #define SA5_CTMEM_OFFSET 0xB8 | ||
181 | |||
182 | #define SA5_INTR_OFF 0x08 | ||
183 | #define SA5B_INTR_OFF 0x04 | ||
184 | #define SA5_INTR_PENDING 0x08 | ||
185 | #define SA5B_INTR_PENDING 0x04 | ||
186 | #define FIFO_EMPTY 0xffffffff | ||
187 | #define HPSA_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ | ||
188 | |||
189 | #define HPSA_ERROR_BIT 0x02 | ||
190 | |||
191 | /* Performant mode flags */ | ||
192 | #define SA5_PERF_INTR_PENDING 0x04 | ||
193 | #define SA5_PERF_INTR_OFF 0x05 | ||
194 | #define SA5_OUTDB_STATUS_PERF_BIT 0x01 | ||
195 | #define SA5_OUTDB_CLEAR_PERF_BIT 0x01 | ||
196 | #define SA5_OUTDB_CLEAR 0xA0 | ||
197 | #define SA5_OUTDB_CLEAR_PERF_BIT 0x01 | ||
198 | #define SA5_OUTDB_STATUS 0x9C | ||
199 | |||
200 | |||
201 | #define HPSA_INTR_ON 1 | ||
202 | #define HPSA_INTR_OFF 0 | ||
203 | /* | ||
204 | Send the command to the hardware | ||
205 | */ | ||
206 | static void SA5_submit_command(struct ctlr_info *h, | ||
207 | struct CommandList *c) | ||
208 | { | ||
209 | dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr, | ||
210 | c->Header.Tag.lower); | ||
211 | writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); | ||
212 | h->commands_outstanding++; | ||
213 | if (h->commands_outstanding > h->max_outstanding) | ||
214 | h->max_outstanding = h->commands_outstanding; | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * This card is the opposite of the other cards. | ||
219 | * 0 turns interrupts on... | ||
220 | * 0x08 turns them off... | ||
221 | */ | ||
222 | static void SA5_intr_mask(struct ctlr_info *h, unsigned long val) | ||
223 | { | ||
224 | if (val) { /* Turn interrupts on */ | ||
225 | h->interrupts_enabled = 1; | ||
226 | writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); | ||
227 | } else { /* Turn them off */ | ||
228 | h->interrupts_enabled = 0; | ||
229 | writel(SA5_INTR_OFF, | ||
230 | h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val) | ||
235 | { | ||
236 | if (val) { /* turn on interrupts */ | ||
237 | h->interrupts_enabled = 1; | ||
238 | writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); | ||
239 | } else { | ||
240 | h->interrupts_enabled = 0; | ||
241 | writel(SA5_PERF_INTR_OFF, | ||
242 | h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | static unsigned long SA5_performant_completed(struct ctlr_info *h) | ||
247 | { | ||
248 | unsigned long register_value = FIFO_EMPTY; | ||
249 | |||
250 | /* flush the controller write of the reply queue by reading | ||
251 | * outbound doorbell status register. | ||
252 | */ | ||
253 | register_value = readl(h->vaddr + SA5_OUTDB_STATUS); | ||
254 | /* msi auto clears the interrupt pending bit. */ | ||
255 | if (!(h->msi_vector || h->msix_vector)) { | ||
256 | writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR); | ||
257 | /* Do a read in order to flush the write to the controller | ||
258 | * (as per spec.) | ||
259 | */ | ||
260 | register_value = readl(h->vaddr + SA5_OUTDB_STATUS); | ||
261 | } | ||
262 | |||
263 | if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { | ||
264 | register_value = *(h->reply_pool_head); | ||
265 | (h->reply_pool_head)++; | ||
266 | h->commands_outstanding--; | ||
267 | } else { | ||
268 | register_value = FIFO_EMPTY; | ||
269 | } | ||
270 | /* Check for wraparound */ | ||
271 | if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { | ||
272 | h->reply_pool_head = h->reply_pool; | ||
273 | h->reply_pool_wraparound ^= 1; | ||
274 | } | ||
275 | |||
276 | return register_value; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Returns true if fifo is full. | ||
281 | * | ||
282 | */ | ||
283 | static unsigned long SA5_fifo_full(struct ctlr_info *h) | ||
284 | { | ||
285 | if (h->commands_outstanding >= h->max_commands) | ||
286 | return 1; | ||
287 | else | ||
288 | return 0; | ||
289 | |||
290 | } | ||
291 | /* | ||
292 | * returns value read from hardware. | ||
293 | * returns FIFO_EMPTY if there is nothing to read | ||
294 | */ | ||
295 | static unsigned long SA5_completed(struct ctlr_info *h) | ||
296 | { | ||
297 | unsigned long register_value | ||
298 | = readl(h->vaddr + SA5_REPLY_PORT_OFFSET); | ||
299 | |||
300 | if (register_value != FIFO_EMPTY) | ||
301 | h->commands_outstanding--; | ||
302 | |||
303 | #ifdef HPSA_DEBUG | ||
304 | if (register_value != FIFO_EMPTY) | ||
305 | dev_dbg(&h->pdev->dev, "Read %lx back from board\n", | ||
306 | register_value); | ||
307 | else | ||
308 | dev_dbg(&h->pdev->dev, "hpsa: FIFO Empty read\n"); | ||
309 | #endif | ||
310 | |||
311 | return register_value; | ||
312 | } | ||
313 | /* | ||
314 | * Returns true if an interrupt is pending.. | ||
315 | */ | ||
316 | static bool SA5_intr_pending(struct ctlr_info *h) | ||
317 | { | ||
318 | unsigned long register_value = | ||
319 | readl(h->vaddr + SA5_INTR_STATUS); | ||
320 | dev_dbg(&h->pdev->dev, "intr_pending %lx\n", register_value); | ||
321 | return register_value & SA5_INTR_PENDING; | ||
322 | } | ||
323 | |||
324 | static bool SA5_performant_intr_pending(struct ctlr_info *h) | ||
325 | { | ||
326 | unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); | ||
327 | |||
328 | if (!register_value) | ||
329 | return false; | ||
330 | |||
331 | if (h->msi_vector || h->msix_vector) | ||
332 | return true; | ||
333 | |||
334 | /* Read outbound doorbell to flush */ | ||
335 | register_value = readl(h->vaddr + SA5_OUTDB_STATUS); | ||
336 | return register_value & SA5_OUTDB_STATUS_PERF_BIT; | ||
337 | } | ||
338 | |||
339 | static struct access_method SA5_access = { | ||
340 | SA5_submit_command, | ||
341 | SA5_intr_mask, | ||
342 | SA5_fifo_full, | ||
343 | SA5_intr_pending, | ||
344 | SA5_completed, | ||
345 | }; | ||
346 | |||
347 | static struct access_method SA5_performant_access = { | ||
348 | SA5_submit_command, | ||
349 | SA5_performant_intr_mask, | ||
350 | SA5_fifo_full, | ||
351 | SA5_performant_intr_pending, | ||
352 | SA5_performant_completed, | ||
353 | }; | ||
354 | |||
355 | struct board_type { | ||
356 | u32 board_id; | ||
357 | char *product_name; | ||
358 | struct access_method *access; | ||
359 | }; | ||
360 | |||
361 | #endif /* HPSA_H */ | ||
362 | |||