Print this page
space aac_key_strings initialiser in aac.c
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/aac/aac.c
+++ new/usr/src/uts/common/io/aac/aac.c
1 1 /*
2 2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 3 */
4 4
5 5 /*
6 6 * Copyright 2005-08 Adaptec, Inc.
7 7 * Copyright (c) 2005-08 Adaptec Inc., Achim Leubner
8 8 * Copyright (c) 2000 Michael Smith
9 9 * Copyright (c) 2001 Scott Long
10 10 * Copyright (c) 2000 BSDi
11 11 * All rights reserved.
12 12 *
13 13 * Redistribution and use in source and binary forms, with or without
14 14 * modification, are permitted provided that the following conditions
15 15 * are met:
16 16 * 1. Redistributions of source code must retain the above copyright
17 17 * notice, this list of conditions and the following disclaimer.
18 18 * 2. Redistributions in binary form must reproduce the above copyright
19 19 * notice, this list of conditions and the following disclaimer in the
20 20 * documentation and/or other materials provided with the distribution.
21 21 *
22 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 32 * SUCH DAMAGE.
33 33 */
34 34 #include <sys/modctl.h>
35 35 #include <sys/conf.h>
36 36 #include <sys/cmn_err.h>
37 37 #include <sys/ddi.h>
38 38 #include <sys/devops.h>
39 39 #include <sys/pci.h>
40 40 #include <sys/types.h>
41 41 #include <sys/ddidmareq.h>
42 42 #include <sys/scsi/scsi.h>
43 43 #include <sys/ksynch.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/byteorder.h>
46 46 #include "aac_regs.h"
47 47 #include "aac.h"
48 48
49 49 /*
50 50 * FMA header files
51 51 */
52 52 #include <sys/ddifm.h>
53 53 #include <sys/fm/protocol.h>
54 54 #include <sys/fm/util.h>
55 55 #include <sys/fm/io/ddi.h>
56 56
57 57 /*
58 58 * For minor nodes created by the SCSA framework, minor numbers are
59 59 * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a
60 60 * number less than 64.
61 61 *
62 62 * To support cfgadm, need to confirm the SCSA framework by creating
63 63 * devctl/scsi and driver specific minor nodes under SCSA format,
64 64 * and calling scsi_hba_xxx() functions aacordingly.
65 65 */
66 66
67 67 #define AAC_MINOR 32
68 68 #define INST2AAC(x) (((x) << INST_MINOR_SHIFT) | AAC_MINOR)
69 69 #define AAC_SCSA_MINOR(x) ((x) & TRAN_MINOR_MASK)
70 70 #define AAC_IS_SCSA_NODE(x) ((x) == DEVCTL_MINOR || (x) == SCSI_MINOR)
71 71
72 72 #define SD2TRAN(sd) ((sd)->sd_address.a_hba_tran)
73 73 #define AAC_TRAN2SOFTS(tran) ((struct aac_softstate *)(tran)->tran_hba_private)
74 74 #define AAC_DIP2TRAN(dip) ((scsi_hba_tran_t *)ddi_get_driver_private(dip))
75 75 #define AAC_DIP2SOFTS(dip) (AAC_TRAN2SOFTS(AAC_DIP2TRAN(dip)))
76 76 #define SD2AAC(sd) (AAC_TRAN2SOFTS(SD2TRAN(sd)))
77 77 #define AAC_PD(t) ((t) - AAC_MAX_LD)
78 78 #define AAC_DEV(softs, t) (((t) < AAC_MAX_LD) ? \
79 79 &(softs)->containers[(t)].dev : \
80 80 ((t) < AAC_MAX_DEV(softs)) ? \
81 81 &(softs)->nondasds[AAC_PD(t)].dev : NULL)
82 82 #define AAC_DEVCFG_BEGIN(softs, tgt) \
83 83 aac_devcfg((softs), (tgt), 1)
84 84 #define AAC_DEVCFG_END(softs, tgt) \
85 85 aac_devcfg((softs), (tgt), 0)
86 86 #define PKT2AC(pkt) ((struct aac_cmd *)(pkt)->pkt_ha_private)
87 87 #define AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \
88 88 if (!(cond)) { \
89 89 int count = (timeout) * 10; \
90 90 while (count) { \
91 91 drv_usecwait(100); \
92 92 if (cond) \
93 93 break; \
94 94 count--; \
95 95 } \
96 96 (timeout) = (count + 9) / 10; \
97 97 } \
98 98 }
99 99
100 100 #define AAC_SENSE_DATA_DESCR_LEN \
101 101 (sizeof (struct scsi_descr_sense_hdr) + \
102 102 sizeof (struct scsi_information_sense_descr))
103 103 #define AAC_ARQ64_LENGTH \
104 104 (sizeof (struct scsi_arq_status) + \
105 105 AAC_SENSE_DATA_DESCR_LEN - SENSE_LENGTH)
106 106
107 107 /* NOTE: GETG4ADDRTL(cdbp) is int32_t */
108 108 #define AAC_GETGXADDR(cmdlen, cdbp) \
109 109 ((cmdlen == 6) ? GETG0ADDR(cdbp) : \
110 110 (cmdlen == 10) ? (uint32_t)GETG1ADDR(cdbp) : \
111 111 ((uint64_t)GETG4ADDR(cdbp) << 32) | (uint32_t)GETG4ADDRTL(cdbp))
112 112
113 113 #define AAC_CDB_INQUIRY_CMDDT 0x02
114 114 #define AAC_CDB_INQUIRY_EVPD 0x01
115 115 #define AAC_VPD_PAGE_CODE 1
116 116 #define AAC_VPD_PAGE_LENGTH 3
117 117 #define AAC_VPD_PAGE_DATA 4
118 118 #define AAC_VPD_ID_CODESET 0
119 119 #define AAC_VPD_ID_TYPE 1
120 120 #define AAC_VPD_ID_LENGTH 3
121 121 #define AAC_VPD_ID_DATA 4
122 122
123 123 #define AAC_SCSI_RPTLUNS_HEAD_SIZE 0x08
124 124 #define AAC_SCSI_RPTLUNS_ADDR_SIZE 0x08
125 125 #define AAC_SCSI_RPTLUNS_ADDR_MASK 0xC0
126 126 /* 00b - peripheral device addressing method */
127 127 #define AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL 0x00
128 128 /* 01b - flat space addressing method */
129 129 #define AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE 0x40
130 130 /* 10b - logical unit addressing method */
131 131 #define AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT 0x80
132 132
133 133 /* Return the size of FIB with data part type data_type */
134 134 #define AAC_FIB_SIZEOF(data_type) \
135 135 (sizeof (struct aac_fib_header) + sizeof (data_type))
136 136 /* Return the container size defined in mir */
137 137 #define AAC_MIR_SIZE(softs, acc, mir) \
138 138 (((softs)->flags & AAC_FLAGS_LBA_64BIT) ? \
139 139 (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity) + \
140 140 ((uint64_t)ddi_get32((acc), &(mir)->MntObj.CapacityHigh) << 32) : \
141 141 (uint64_t)ddi_get32((acc), &(mir)->MntObj.Capacity))
142 142
143 143 /* The last entry of aac_cards[] is for unknown cards */
144 144 #define AAC_UNKNOWN_CARD \
145 145 (sizeof (aac_cards) / sizeof (struct aac_card_type) - 1)
146 146 #define CARD_IS_UNKNOWN(i) (i == AAC_UNKNOWN_CARD)
147 147 #define BUF_IS_READ(bp) ((bp)->b_flags & B_READ)
148 148 #define AAC_IS_Q_EMPTY(q) ((q)->q_head == NULL)
149 149 #define AAC_CMDQ(acp) (!((acp)->flags & AAC_CMD_SYNC))
150 150
151 151 #define PCI_MEM_GET32(softs, off) \
152 152 ddi_get32((softs)->pci_mem_handle, \
153 153 (void *)((softs)->pci_mem_base_vaddr + (off)))
154 154 #define PCI_MEM_PUT32(softs, off, val) \
155 155 ddi_put32((softs)->pci_mem_handle, \
156 156 (void *)((softs)->pci_mem_base_vaddr + (off)), \
157 157 (uint32_t)(val))
158 158 #define PCI_MEM_GET16(softs, off) \
159 159 ddi_get16((softs)->pci_mem_handle, \
160 160 (void *)((softs)->pci_mem_base_vaddr + (off)))
161 161 #define PCI_MEM_PUT16(softs, off, val) \
162 162 ddi_put16((softs)->pci_mem_handle, \
163 163 (void *)((softs)->pci_mem_base_vaddr + (off)), (uint16_t)(val))
164 164 /* Write host data at valp to device mem[off] repeatedly count times */
165 165 #define PCI_MEM_REP_PUT8(softs, off, valp, count) \
166 166 ddi_rep_put8((softs)->pci_mem_handle, (uint8_t *)(valp), \
167 167 (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
168 168 count, DDI_DEV_AUTOINCR)
169 169 /* Read device data at mem[off] to host addr valp repeatedly count times */
170 170 #define PCI_MEM_REP_GET8(softs, off, valp, count) \
171 171 ddi_rep_get8((softs)->pci_mem_handle, (uint8_t *)(valp), \
172 172 (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \
173 173 count, DDI_DEV_AUTOINCR)
174 174 #define AAC_GET_FIELD8(acc, d, s, field) \
175 175 (d)->field = ddi_get8(acc, (uint8_t *)&(s)->field)
176 176 #define AAC_GET_FIELD32(acc, d, s, field) \
177 177 (d)->field = ddi_get32(acc, (uint32_t *)&(s)->field)
178 178 #define AAC_GET_FIELD64(acc, d, s, field) \
179 179 (d)->field = ddi_get64(acc, (uint64_t *)&(s)->field)
180 180 #define AAC_REP_GET_FIELD8(acc, d, s, field, r) \
181 181 ddi_rep_get8((acc), (uint8_t *)&(d)->field, \
182 182 (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
183 183 #define AAC_REP_GET_FIELD32(acc, d, s, field, r) \
184 184 ddi_rep_get32((acc), (uint32_t *)&(d)->field, \
185 185 (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR)
186 186
187 187 #define AAC_ENABLE_INTR(softs) { \
188 188 if (softs->flags & AAC_FLAGS_NEW_COMM) \
189 189 PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_NEW); \
190 190 else \
191 191 PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_BITS); \
192 192 softs->state |= AAC_STATE_INTR; \
193 193 }
194 194
195 195 #define AAC_DISABLE_INTR(softs) { \
196 196 PCI_MEM_PUT32(softs, AAC_OIMR, ~0); \
197 197 softs->state &= ~AAC_STATE_INTR; \
198 198 }
199 199 #define AAC_STATUS_CLR(softs, mask) PCI_MEM_PUT32(softs, AAC_ODBR, mask)
200 200 #define AAC_STATUS_GET(softs) PCI_MEM_GET32(softs, AAC_ODBR)
201 201 #define AAC_NOTIFY(softs, val) PCI_MEM_PUT32(softs, AAC_IDBR, val)
202 202 #define AAC_OUTB_GET(softs) PCI_MEM_GET32(softs, AAC_OQUE)
203 203 #define AAC_OUTB_SET(softs, val) PCI_MEM_PUT32(softs, AAC_OQUE, val)
204 204 #define AAC_FWSTATUS_GET(softs) \
205 205 ((softs)->aac_if.aif_get_fwstatus(softs))
206 206 #define AAC_MAILBOX_GET(softs, mb) \
207 207 ((softs)->aac_if.aif_get_mailbox((softs), (mb)))
208 208 #define AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \
209 209 ((softs)->aac_if.aif_set_mailbox((softs), (cmd), \
210 210 (arg0), (arg1), (arg2), (arg3)))
211 211
212 212 #define AAC_MGT_SLOT_NUM 2
213 213 #define AAC_THROTTLE_DRAIN -1
214 214
215 215 #define AAC_QUIESCE_TICK 1 /* 1 second */
216 216 #define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */
217 217 #define AAC_DEFAULT_TICK 10 /* 10 seconds */
218 218 #define AAC_SYNC_TICK (30*60) /* 30 minutes */
219 219
220 220 /* Poll time for aac_do_poll_io() */
221 221 #define AAC_POLL_TIME 60 /* 60 seconds */
222 222
223 223 /* IOP reset */
224 224 #define AAC_IOP_RESET_SUCCEED 0 /* IOP reset succeed */
225 225 #define AAC_IOP_RESET_FAILED -1 /* IOP reset failed */
226 226 #define AAC_IOP_RESET_ABNORMAL -2 /* Reset operation abnormal */
227 227
228 228 /*
229 229 * Hardware access functions
230 230 */
231 231 static int aac_rx_get_fwstatus(struct aac_softstate *);
232 232 static int aac_rx_get_mailbox(struct aac_softstate *, int);
233 233 static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
234 234 uint32_t, uint32_t, uint32_t);
235 235 static int aac_rkt_get_fwstatus(struct aac_softstate *);
236 236 static int aac_rkt_get_mailbox(struct aac_softstate *, int);
237 237 static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t,
238 238 uint32_t, uint32_t, uint32_t);
239 239
240 240 /*
241 241 * SCSA function prototypes
242 242 */
243 243 static int aac_attach(dev_info_t *, ddi_attach_cmd_t);
244 244 static int aac_detach(dev_info_t *, ddi_detach_cmd_t);
245 245 static int aac_reset(dev_info_t *, ddi_reset_cmd_t);
246 246 static int aac_quiesce(dev_info_t *);
247 247 static int aac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
248 248
249 249 /*
250 250 * Interrupt handler functions
251 251 */
252 252 static int aac_query_intrs(struct aac_softstate *, int);
253 253 static int aac_add_intrs(struct aac_softstate *);
254 254 static void aac_remove_intrs(struct aac_softstate *);
255 255 static int aac_enable_intrs(struct aac_softstate *);
256 256 static int aac_disable_intrs(struct aac_softstate *);
257 257 static uint_t aac_intr_old(caddr_t);
258 258 static uint_t aac_intr_new(caddr_t);
259 259 static uint_t aac_softintr(caddr_t);
260 260
261 261 /*
262 262 * Internal functions in attach
263 263 */
264 264 static int aac_check_card_type(struct aac_softstate *);
265 265 static int aac_check_firmware(struct aac_softstate *);
266 266 static int aac_common_attach(struct aac_softstate *);
267 267 static void aac_common_detach(struct aac_softstate *);
268 268 static int aac_probe_containers(struct aac_softstate *);
269 269 static int aac_alloc_comm_space(struct aac_softstate *);
270 270 static int aac_setup_comm_space(struct aac_softstate *);
271 271 static void aac_free_comm_space(struct aac_softstate *);
272 272 static int aac_hba_setup(struct aac_softstate *);
273 273
274 274 /*
275 275 * Sync FIB operation functions
276 276 */
277 277 int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t,
278 278 uint32_t, uint32_t, uint32_t, uint32_t *);
279 279 static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t);
280 280
281 281 /*
282 282 * Command queue operation functions
283 283 */
284 284 static void aac_cmd_initq(struct aac_cmd_queue *);
285 285 static void aac_cmd_enqueue(struct aac_cmd_queue *, struct aac_cmd *);
286 286 static struct aac_cmd *aac_cmd_dequeue(struct aac_cmd_queue *);
287 287 static void aac_cmd_delete(struct aac_cmd_queue *, struct aac_cmd *);
288 288
289 289 /*
290 290 * FIB queue operation functions
291 291 */
292 292 static int aac_fib_enqueue(struct aac_softstate *, int, uint32_t, uint32_t);
293 293 static int aac_fib_dequeue(struct aac_softstate *, int, int *);
294 294
295 295 /*
296 296 * Slot operation functions
297 297 */
298 298 static int aac_create_slots(struct aac_softstate *);
299 299 static void aac_destroy_slots(struct aac_softstate *);
300 300 static void aac_alloc_fibs(struct aac_softstate *);
301 301 static void aac_destroy_fibs(struct aac_softstate *);
302 302 static struct aac_slot *aac_get_slot(struct aac_softstate *);
303 303 static void aac_release_slot(struct aac_softstate *, struct aac_slot *);
304 304 static int aac_alloc_fib(struct aac_softstate *, struct aac_slot *);
305 305 static void aac_free_fib(struct aac_slot *);
306 306
307 307 /*
308 308 * Internal functions
309 309 */
310 310 static void aac_cmd_fib_header(struct aac_softstate *, struct aac_cmd *,
311 311 uint16_t);
312 312 static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *);
313 313 static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *);
314 314 static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *);
315 315 static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *);
316 316 static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *);
317 317 static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *);
318 318 static void aac_cmd_fib_startstop(struct aac_softstate *, struct aac_cmd *);
319 319 static void aac_start_waiting_io(struct aac_softstate *);
320 320 static void aac_drain_comp_q(struct aac_softstate *);
321 321 int aac_do_io(struct aac_softstate *, struct aac_cmd *);
322 322 static int aac_sync_fib_slot_bind(struct aac_softstate *, struct aac_cmd *);
323 323 static void aac_sync_fib_slot_release(struct aac_softstate *, struct aac_cmd *);
324 324 static void aac_start_io(struct aac_softstate *, struct aac_cmd *);
325 325 static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *);
326 326 static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *);
327 327 static int aac_send_command(struct aac_softstate *, struct aac_slot *);
328 328 static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *);
329 329 static int aac_dma_sync_ac(struct aac_cmd *);
330 330 static int aac_shutdown(struct aac_softstate *);
331 331 static int aac_reset_adapter(struct aac_softstate *);
332 332 static int aac_do_quiesce(struct aac_softstate *softs);
333 333 static int aac_do_unquiesce(struct aac_softstate *softs);
334 334 static void aac_unhold_bus(struct aac_softstate *, int);
335 335 static void aac_set_throttle(struct aac_softstate *, struct aac_device *,
336 336 int, int);
337 337
338 338 /*
339 339 * Adapter Initiated FIB handling function
340 340 */
341 341 static void aac_save_aif(struct aac_softstate *, ddi_acc_handle_t,
342 342 struct aac_fib *, int);
343 343 static int aac_handle_aif(struct aac_softstate *, struct aac_aif_command *);
344 344
345 345 /*
346 346 * Event handling related functions
347 347 */
348 348 static void aac_timer(void *);
349 349 static void aac_event_thread(struct aac_softstate *);
350 350 static void aac_event_disp(struct aac_softstate *, int);
351 351
352 352 /*
353 353 * IOCTL interface related functions
354 354 */
355 355 static int aac_open(dev_t *, int, int, cred_t *);
356 356 static int aac_close(dev_t, int, int, cred_t *);
357 357 static int aac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
358 358 extern int aac_do_ioctl(struct aac_softstate *, dev_t, int, intptr_t, int);
359 359
360 360 /*
361 361 * FMA Prototypes
362 362 */
363 363 static void aac_fm_init(struct aac_softstate *);
364 364 static void aac_fm_fini(struct aac_softstate *);
365 365 static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
366 366 int aac_check_acc_handle(ddi_acc_handle_t);
367 367 int aac_check_dma_handle(ddi_dma_handle_t);
368 368 void aac_fm_ereport(struct aac_softstate *, char *);
369 369
370 370 /*
371 371 * Auto enumeration functions
372 372 */
373 373 static dev_info_t *aac_find_child(struct aac_softstate *, uint16_t, uint8_t);
374 374 static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
375 375 void *, dev_info_t **);
376 376 static int aac_handle_dr(struct aac_softstate *, int, int, int);
377 377
378 378 extern pri_t minclsyspri;
379 379
380 380 #ifdef DEBUG
381 381 /*
382 382 * UART debug output support
383 383 */
384 384
385 385 #define AAC_PRINT_BUFFER_SIZE 512
386 386 #define AAC_PRINT_TIMEOUT 250 /* 1/4 sec. = 250 msec. */
387 387
388 388 #define AAC_FW_DBG_STRLEN_OFFSET 0x00
389 389 #define AAC_FW_DBG_FLAGS_OFFSET 0x04
390 390 #define AAC_FW_DBG_BLED_OFFSET 0x08
391 391
392 392 static int aac_get_fw_debug_buffer(struct aac_softstate *);
393 393 static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *);
394 394 static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *);
395 395
396 396 static char aac_prt_buf[AAC_PRINT_BUFFER_SIZE];
397 397 static char aac_fmt[] = " %s";
398 398 static char aac_fmt_header[] = " %s.%d: %s";
399 399 static kmutex_t aac_prt_mutex;
400 400
401 401 /*
402 402 * Debug flags to be put into the softstate flags field
403 403 * when initialized
404 404 */
405 405 uint32_t aac_debug_flags =
406 406 /* AACDB_FLAGS_KERNEL_PRINT | */
407 407 /* AACDB_FLAGS_FW_PRINT | */
408 408 /* AACDB_FLAGS_MISC | */
409 409 /* AACDB_FLAGS_FUNC1 | */
410 410 /* AACDB_FLAGS_FUNC2 | */
411 411 /* AACDB_FLAGS_SCMD | */
412 412 /* AACDB_FLAGS_AIF | */
413 413 /* AACDB_FLAGS_FIB | */
414 414 /* AACDB_FLAGS_IOCTL | */
415 415 0;
416 416 uint32_t aac_debug_fib_flags =
417 417 /* AACDB_FLAGS_FIB_RW | */
418 418 /* AACDB_FLAGS_FIB_IOCTL | */
419 419 /* AACDB_FLAGS_FIB_SRB | */
420 420 /* AACDB_FLAGS_FIB_SYNC | */
421 421 /* AACDB_FLAGS_FIB_HEADER | */
422 422 /* AACDB_FLAGS_FIB_TIMEOUT | */
423 423 0;
424 424
425 425 #endif /* DEBUG */
426 426
427 427 static struct cb_ops aac_cb_ops = {
428 428 aac_open, /* open */
429 429 aac_close, /* close */
430 430 nodev, /* strategy */
431 431 nodev, /* print */
432 432 nodev, /* dump */
433 433 nodev, /* read */
434 434 nodev, /* write */
435 435 aac_ioctl, /* ioctl */
436 436 nodev, /* devmap */
437 437 nodev, /* mmap */
438 438 nodev, /* segmap */
439 439 nochpoll, /* poll */
440 440 ddi_prop_op, /* cb_prop_op */
441 441 NULL, /* streamtab */
442 442 D_64BIT | D_NEW | D_MP | D_HOTPLUG, /* cb_flag */
443 443 CB_REV, /* cb_rev */
444 444 nodev, /* async I/O read entry point */
445 445 nodev /* async I/O write entry point */
446 446 };
447 447
448 448 static struct dev_ops aac_dev_ops = {
449 449 DEVO_REV,
450 450 0,
451 451 aac_getinfo,
452 452 nulldev,
453 453 nulldev,
454 454 aac_attach,
455 455 aac_detach,
456 456 aac_reset,
457 457 &aac_cb_ops,
458 458 NULL,
459 459 NULL,
460 460 aac_quiesce,
↓ open down ↓ |
460 lines elided |
↑ open up ↑ |
461 461 };
462 462
463 463 static struct modldrv aac_modldrv = {
464 464 &mod_driverops,
465 465 "AAC Driver " AAC_DRIVER_VERSION,
466 466 &aac_dev_ops,
467 467 };
468 468
469 469 static struct modlinkage aac_modlinkage = {
470 470 MODREV_1,
471 - &aac_modldrv,
472 - NULL
471 + { &aac_modldrv, NULL }
473 472 };
474 473
475 474 static struct aac_softstate *aac_softstatep;
476 475
477 476 /*
478 477 * Supported card list
479 478 * ordered in vendor id, subvendor id, subdevice id, and device id
480 479 */
481 480 static struct aac_card_type aac_cards[] = {
482 481 {0x1028, 0x1, 0x1028, 0x1, AAC_HWIF_I960RX,
483 482 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
484 483 "Dell", "PERC 3/Di"},
485 484 {0x1028, 0x2, 0x1028, 0x2, AAC_HWIF_I960RX,
486 485 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
487 486 "Dell", "PERC 3/Di"},
488 487 {0x1028, 0x3, 0x1028, 0x3, AAC_HWIF_I960RX,
489 488 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
490 489 "Dell", "PERC 3/Si"},
491 490 {0x1028, 0x8, 0x1028, 0xcf, AAC_HWIF_I960RX,
492 491 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
493 492 "Dell", "PERC 3/Di"},
494 493 {0x1028, 0x4, 0x1028, 0xd0, AAC_HWIF_I960RX,
495 494 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
496 495 "Dell", "PERC 3/Si"},
497 496 {0x1028, 0x2, 0x1028, 0xd1, AAC_HWIF_I960RX,
498 497 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
499 498 "Dell", "PERC 3/Di"},
500 499 {0x1028, 0x2, 0x1028, 0xd9, AAC_HWIF_I960RX,
501 500 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
502 501 "Dell", "PERC 3/Di"},
503 502 {0x1028, 0xa, 0x1028, 0x106, AAC_HWIF_I960RX,
504 503 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
505 504 "Dell", "PERC 3/Di"},
506 505 {0x1028, 0xa, 0x1028, 0x11b, AAC_HWIF_I960RX,
507 506 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
508 507 "Dell", "PERC 3/Di"},
509 508 {0x1028, 0xa, 0x1028, 0x121, AAC_HWIF_I960RX,
510 509 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG, AAC_TYPE_SCSI,
511 510 "Dell", "PERC 3/Di"},
512 511 {0x9005, 0x285, 0x1028, 0x287, AAC_HWIF_I960RX,
513 512 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
514 513 "Dell", "PERC 320/DC"},
515 514 {0x9005, 0x285, 0x1028, 0x291, AAC_HWIF_I960RX,
516 515 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Dell", "CERC SR2"},
517 516
518 517 {0x9005, 0x285, 0x1014, 0x2f2, AAC_HWIF_I960RX,
519 518 0, AAC_TYPE_SCSI, "IBM", "ServeRAID 8i"},
520 519 {0x9005, 0x285, 0x1014, 0x34d, AAC_HWIF_I960RX,
521 520 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8s"},
522 521 {0x9005, 0x286, 0x1014, 0x9580, AAC_HWIF_RKT,
523 522 0, AAC_TYPE_SAS, "IBM", "ServeRAID 8k"},
524 523
525 524 {0x9005, 0x285, 0x103c, 0x3227, AAC_HWIF_I960RX,
526 525 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
527 526 {0x9005, 0x285, 0xe11, 0x295, AAC_HWIF_I960RX,
528 527 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2610SA"},
529 528
530 529 {0x9005, 0x285, 0x9005, 0x285, AAC_HWIF_I960RX,
531 530 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
532 531 "Adaptec", "2200S"},
533 532 {0x9005, 0x285, 0x9005, 0x286, AAC_HWIF_I960RX,
534 533 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
535 534 "Adaptec", "2120S"},
536 535 {0x9005, 0x285, 0x9005, 0x287, AAC_HWIF_I960RX,
537 536 AAC_FLAGS_NO4GB | AAC_FLAGS_34SG | AAC_FLAGS_256FIBS, AAC_TYPE_SCSI,
538 537 "Adaptec", "2200S"},
539 538 {0x9005, 0x285, 0x9005, 0x288, AAC_HWIF_I960RX,
540 539 0, AAC_TYPE_SCSI, "Adaptec", "3230S"},
541 540 {0x9005, 0x285, 0x9005, 0x289, AAC_HWIF_I960RX,
542 541 0, AAC_TYPE_SCSI, "Adaptec", "3240S"},
543 542 {0x9005, 0x285, 0x9005, 0x28a, AAC_HWIF_I960RX,
544 543 0, AAC_TYPE_SCSI, "Adaptec", "2020ZCR"},
545 544 {0x9005, 0x285, 0x9005, 0x28b, AAC_HWIF_I960RX,
546 545 0, AAC_TYPE_SCSI, "Adaptec", "2025ZCR"},
547 546 {0x9005, 0x286, 0x9005, 0x28c, AAC_HWIF_RKT,
548 547 0, AAC_TYPE_SCSI, "Adaptec", "2230S"},
549 548 {0x9005, 0x286, 0x9005, 0x28d, AAC_HWIF_RKT,
550 549 0, AAC_TYPE_SCSI, "Adaptec", "2130S"},
551 550 {0x9005, 0x285, 0x9005, 0x28e, AAC_HWIF_I960RX,
552 551 0, AAC_TYPE_SATA, "Adaptec", "2020SA"},
553 552 {0x9005, 0x285, 0x9005, 0x28f, AAC_HWIF_I960RX,
554 553 0, AAC_TYPE_SATA, "Adaptec", "2025SA"},
555 554 {0x9005, 0x285, 0x9005, 0x290, AAC_HWIF_I960RX,
556 555 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2410SA"},
557 556 {0x9005, 0x285, 0x9005, 0x292, AAC_HWIF_I960RX,
558 557 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "2810SA"},
559 558 {0x9005, 0x285, 0x9005, 0x293, AAC_HWIF_I960RX,
560 559 AAC_FLAGS_17SG, AAC_TYPE_SATA, "Adaptec", "21610SA"},
561 560 {0x9005, 0x285, 0x9005, 0x294, AAC_HWIF_I960RX,
562 561 0, AAC_TYPE_SATA, "Adaptec", "2026ZCR"},
563 562 {0x9005, 0x285, 0x9005, 0x296, AAC_HWIF_I960RX,
564 563 0, AAC_TYPE_SCSI, "Adaptec", "2240S"},
565 564 {0x9005, 0x285, 0x9005, 0x297, AAC_HWIF_I960RX,
566 565 0, AAC_TYPE_SAS, "Adaptec", "4005SAS"},
567 566 {0x9005, 0x285, 0x9005, 0x298, AAC_HWIF_I960RX,
568 567 0, AAC_TYPE_SAS, "Adaptec", "RAID 4000"},
569 568 {0x9005, 0x285, 0x9005, 0x299, AAC_HWIF_I960RX,
570 569 0, AAC_TYPE_SAS, "Adaptec", "4800SAS"},
571 570 {0x9005, 0x285, 0x9005, 0x29a, AAC_HWIF_I960RX,
572 571 0, AAC_TYPE_SAS, "Adaptec", "4805SAS"},
573 572 {0x9005, 0x286, 0x9005, 0x29b, AAC_HWIF_RKT,
574 573 0, AAC_TYPE_SATA, "Adaptec", "2820SA"},
575 574 {0x9005, 0x286, 0x9005, 0x29c, AAC_HWIF_RKT,
576 575 0, AAC_TYPE_SATA, "Adaptec", "2620SA"},
577 576 {0x9005, 0x286, 0x9005, 0x29d, AAC_HWIF_RKT,
578 577 0, AAC_TYPE_SATA, "Adaptec", "2420SA"},
579 578 {0x9005, 0x286, 0x9005, 0x29e, AAC_HWIF_RKT,
580 579 0, AAC_TYPE_SATA, "ICP", "9024RO"},
581 580 {0x9005, 0x286, 0x9005, 0x29f, AAC_HWIF_RKT,
582 581 0, AAC_TYPE_SATA, "ICP", "9014RO"},
583 582 {0x9005, 0x286, 0x9005, 0x2a0, AAC_HWIF_RKT,
584 583 0, AAC_TYPE_SATA, "ICP", "9047MA"},
585 584 {0x9005, 0x286, 0x9005, 0x2a1, AAC_HWIF_RKT,
586 585 0, AAC_TYPE_SATA, "ICP", "9087MA"},
587 586 {0x9005, 0x285, 0x9005, 0x2a4, AAC_HWIF_I960RX,
588 587 0, AAC_TYPE_SAS, "ICP", "9085LI"},
589 588 {0x9005, 0x285, 0x9005, 0x2a5, AAC_HWIF_I960RX,
590 589 0, AAC_TYPE_SAS, "ICP", "5085BR"},
591 590 {0x9005, 0x286, 0x9005, 0x2a6, AAC_HWIF_RKT,
592 591 0, AAC_TYPE_SATA, "ICP", "9067MA"},
593 592 {0x9005, 0x285, 0x9005, 0x2b5, AAC_HWIF_I960RX,
594 593 0, AAC_TYPE_SAS, "Adaptec", "RAID 5445"},
595 594 {0x9005, 0x285, 0x9005, 0x2b6, AAC_HWIF_I960RX,
596 595 0, AAC_TYPE_SAS, "Adaptec", "RAID 5805"},
597 596 {0x9005, 0x285, 0x9005, 0x2b7, AAC_HWIF_I960RX,
598 597 0, AAC_TYPE_SAS, "Adaptec", "RAID 5085"},
599 598 {0x9005, 0x285, 0x9005, 0x2b8, AAC_HWIF_I960RX,
600 599 0, AAC_TYPE_SAS, "ICP", "RAID ICP5445SL"},
601 600 {0x9005, 0x285, 0x9005, 0x2b9, AAC_HWIF_I960RX,
602 601 0, AAC_TYPE_SAS, "ICP", "RAID ICP5085SL"},
603 602 {0x9005, 0x285, 0x9005, 0x2ba, AAC_HWIF_I960RX,
604 603 0, AAC_TYPE_SAS, "ICP", "RAID ICP5805SL"},
605 604
606 605 {0, 0, 0, 0, AAC_HWIF_UNKNOWN,
607 606 0, AAC_TYPE_UNKNOWN, "Unknown", "AAC card"},
608 607 };
609 608
610 609 /*
611 610 * Hardware access functions for i960 based cards
612 611 */
613 612 static struct aac_interface aac_rx_interface = {
614 613 aac_rx_get_fwstatus,
615 614 aac_rx_get_mailbox,
616 615 aac_rx_set_mailbox
617 616 };
618 617
619 618 /*
620 619 * Hardware access functions for Rocket based cards
621 620 */
622 621 static struct aac_interface aac_rkt_interface = {
623 622 aac_rkt_get_fwstatus,
624 623 aac_rkt_get_mailbox,
625 624 aac_rkt_set_mailbox
626 625 };
627 626
628 627 ddi_device_acc_attr_t aac_acc_attr = {
629 628 DDI_DEVICE_ATTR_V1,
630 629 DDI_STRUCTURE_LE_ACC,
631 630 DDI_STRICTORDER_ACC,
632 631 DDI_DEFAULT_ACC
633 632 };
634 633
635 634 static struct {
636 635 int size;
637 636 int notify;
638 637 } aac_qinfo[] = {
639 638 {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
640 639 {AAC_HOST_HIGH_CMD_ENTRIES, 0},
641 640 {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
642 641 {AAC_ADAP_HIGH_CMD_ENTRIES, 0},
643 642 {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
644 643 {AAC_HOST_HIGH_RESP_ENTRIES, 0},
645 644 {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
646 645 {AAC_ADAP_HIGH_RESP_ENTRIES, 0}
647 646 };
648 647
649 648 /*
650 649 * Default aac dma attributes
651 650 */
652 651 static ddi_dma_attr_t aac_dma_attr = {
653 652 DMA_ATTR_V0,
654 653 0, /* lowest usable address */
655 654 0xffffffffull, /* high DMA address range */
656 655 0xffffffffull, /* DMA counter register */
657 656 AAC_DMA_ALIGN, /* DMA address alignment */
658 657 1, /* DMA burstsizes */
659 658 1, /* min effective DMA size */
660 659 0xffffffffull, /* max DMA xfer size */
661 660 0xffffffffull, /* segment boundary */
662 661 1, /* s/g list length */
663 662 AAC_BLK_SIZE, /* granularity of device */
664 663 0 /* DMA transfer flags */
665 664 };
666 665
667 666 static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */
668 667 static uint32_t aac_timebase = 0; /* internal timer in seconds */
669 668
670 669 /*
671 670 * Warlock directives
672 671 *
673 672 * Different variables with the same types have to be protected by the
674 673 * same mutex; otherwise, warlock will complain with "variables don't
675 674 * seem to be protected consistently". For example,
676 675 * aac_softstate::{q_wait, q_comp} are type of aac_cmd_queue, and protected
677 676 * by aac_softstate::{io_lock, q_comp_mutex} respectively. We have to
678 677 * declare them as protected explictly at aac_cmd_dequeue().
679 678 */
680 679 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt scsi_cdb scsi_status \
681 680 scsi_arq_status scsi_descr_sense_hdr scsi_information_sense_descr \
682 681 mode_format mode_geometry mode_header aac_cmd))
683 682 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_cmd", aac_fib ddi_dma_cookie_t \
684 683 aac_sge))
685 684 _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \
686 685 aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \
687 686 aac_sg_table aac_srb))
688 687 _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry))
689 688 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
690 689 _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf))
691 690
692 691 int
693 692 _init(void)
694 693 {
695 694 int rval = 0;
696 695
697 696 #ifdef DEBUG
698 697 mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL);
699 698 #endif
700 699 DBCALLED(NULL, 1);
701 700
702 701 if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
703 702 sizeof (struct aac_softstate), 0)) != 0)
704 703 goto error;
705 704
706 705 if ((rval = scsi_hba_init(&aac_modlinkage)) != 0) {
707 706 ddi_soft_state_fini((void *)&aac_softstatep);
708 707 goto error;
709 708 }
710 709
711 710 if ((rval = mod_install(&aac_modlinkage)) != 0) {
712 711 ddi_soft_state_fini((void *)&aac_softstatep);
713 712 scsi_hba_fini(&aac_modlinkage);
714 713 goto error;
715 714 }
716 715 return (rval);
717 716
718 717 error:
719 718 AACDB_PRINT(NULL, CE_WARN, "Mod init error!");
720 719 #ifdef DEBUG
721 720 mutex_destroy(&aac_prt_mutex);
722 721 #endif
723 722 return (rval);
724 723 }
725 724
726 725 int
727 726 _info(struct modinfo *modinfop)
728 727 {
729 728 DBCALLED(NULL, 1);
730 729 return (mod_info(&aac_modlinkage, modinfop));
731 730 }
732 731
733 732 /*
734 733 * An HBA driver cannot be unload unless you reboot,
735 734 * so this function will be of no use.
736 735 */
737 736 int
738 737 _fini(void)
739 738 {
740 739 int rval;
741 740
742 741 DBCALLED(NULL, 1);
743 742
744 743 if ((rval = mod_remove(&aac_modlinkage)) != 0)
745 744 goto error;
746 745
747 746 scsi_hba_fini(&aac_modlinkage);
748 747 ddi_soft_state_fini((void *)&aac_softstatep);
749 748 #ifdef DEBUG
750 749 mutex_destroy(&aac_prt_mutex);
751 750 #endif
752 751 return (0);
753 752
754 753 error:
755 754 AACDB_PRINT(NULL, CE_WARN, "AAC is busy, cannot unload!");
756 755 return (rval);
757 756 }
758 757
759 758 static int
760 759 aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
761 760 {
762 761 int instance, i;
763 762 struct aac_softstate *softs = NULL;
764 763 int attach_state = 0;
765 764 char *data;
766 765
767 766 DBCALLED(NULL, 1);
768 767
769 768 switch (cmd) {
770 769 case DDI_ATTACH:
771 770 break;
772 771 case DDI_RESUME:
773 772 return (DDI_FAILURE);
774 773 default:
775 774 return (DDI_FAILURE);
776 775 }
777 776
778 777 instance = ddi_get_instance(dip);
779 778
780 779 /* Get soft state */
781 780 if (ddi_soft_state_zalloc(aac_softstatep, instance) != DDI_SUCCESS) {
782 781 AACDB_PRINT(softs, CE_WARN, "Cannot alloc soft state");
783 782 goto error;
784 783 }
785 784 softs = ddi_get_soft_state(aac_softstatep, instance);
786 785 attach_state |= AAC_ATTACH_SOFTSTATE_ALLOCED;
787 786
788 787 softs->instance = instance;
789 788 softs->devinfo_p = dip;
790 789 softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr;
791 790 softs->addr_dma_attr.dma_attr_granular = 1;
792 791 softs->acc_attr = aac_acc_attr;
793 792 softs->reg_attr = aac_acc_attr;
794 793 softs->card = AAC_UNKNOWN_CARD;
795 794 #ifdef DEBUG
796 795 softs->debug_flags = aac_debug_flags;
797 796 softs->debug_fib_flags = aac_debug_fib_flags;
798 797 #endif
799 798
800 799 /* Initialize FMA */
801 800 aac_fm_init(softs);
802 801
803 802 /* Check the card type */
804 803 if (aac_check_card_type(softs) == AACERR) {
805 804 AACDB_PRINT(softs, CE_WARN, "Card not supported");
806 805 goto error;
807 806 }
808 807 /* We have found the right card and everything is OK */
809 808 attach_state |= AAC_ATTACH_CARD_DETECTED;
810 809
811 810 /* Map PCI mem space */
812 811 if (ddi_regs_map_setup(dip, 1,
813 812 (caddr_t *)&softs->pci_mem_base_vaddr, 0,
814 813 softs->map_size_min, &softs->reg_attr,
815 814 &softs->pci_mem_handle) != DDI_SUCCESS)
816 815 goto error;
817 816
818 817 softs->map_size = softs->map_size_min;
819 818 attach_state |= AAC_ATTACH_PCI_MEM_MAPPED;
820 819
821 820 AAC_DISABLE_INTR(softs);
822 821
823 822 /* Init mutexes and condvars */
824 823 mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER,
825 824 DDI_INTR_PRI(softs->intr_pri));
826 825 mutex_init(&softs->q_comp_mutex, NULL, MUTEX_DRIVER,
827 826 DDI_INTR_PRI(softs->intr_pri));
828 827 mutex_init(&softs->time_mutex, NULL, MUTEX_DRIVER,
829 828 DDI_INTR_PRI(softs->intr_pri));
830 829 mutex_init(&softs->ev_lock, NULL, MUTEX_DRIVER,
831 830 DDI_INTR_PRI(softs->intr_pri));
832 831 mutex_init(&softs->aifq_mutex, NULL,
833 832 MUTEX_DRIVER, DDI_INTR_PRI(softs->intr_pri));
834 833 cv_init(&softs->event, NULL, CV_DRIVER, NULL);
835 834 cv_init(&softs->sync_fib_cv, NULL, CV_DRIVER, NULL);
836 835 cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL);
837 836 cv_init(&softs->event_wait_cv, NULL, CV_DRIVER, NULL);
838 837 cv_init(&softs->event_disp_cv, NULL, CV_DRIVER, NULL);
839 838 cv_init(&softs->aifq_cv, NULL, CV_DRIVER, NULL);
840 839 attach_state |= AAC_ATTACH_KMUTEX_INITED;
841 840
842 841 /* Init the cmd queues */
843 842 for (i = 0; i < AAC_CMDQ_NUM; i++)
844 843 aac_cmd_initq(&softs->q_wait[i]);
845 844 aac_cmd_initq(&softs->q_busy);
846 845 aac_cmd_initq(&softs->q_comp);
847 846
848 847 /* Check for legacy device naming support */
849 848 softs->legacy = 1; /* default to use legacy name */
850 849 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
851 850 "legacy-name-enable", &data) == DDI_SUCCESS)) {
852 851 if (strcmp(data, "no") == 0) {
853 852 AACDB_PRINT(softs, CE_NOTE, "legacy-name disabled");
854 853 softs->legacy = 0;
855 854 }
856 855 ddi_prop_free(data);
857 856 }
858 857
859 858 /*
860 859 * Everything has been set up till now,
861 860 * we will do some common attach.
862 861 */
863 862 mutex_enter(&softs->io_lock);
864 863 if (aac_common_attach(softs) == AACERR) {
865 864 mutex_exit(&softs->io_lock);
866 865 goto error;
867 866 }
868 867 mutex_exit(&softs->io_lock);
869 868 attach_state |= AAC_ATTACH_COMM_SPACE_SETUP;
870 869
871 870 /* Check for buf breakup support */
872 871 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
873 872 "breakup-enable", &data) == DDI_SUCCESS)) {
874 873 if (strcmp(data, "yes") == 0) {
875 874 AACDB_PRINT(softs, CE_NOTE, "buf breakup enabled");
876 875 softs->flags |= AAC_FLAGS_BRKUP;
877 876 }
878 877 ddi_prop_free(data);
879 878 }
880 879 softs->dma_max = softs->buf_dma_attr.dma_attr_maxxfer;
881 880 if (softs->flags & AAC_FLAGS_BRKUP) {
882 881 softs->dma_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
883 882 DDI_PROP_DONTPASS, "dma-max", softs->dma_max);
884 883 }
885 884
886 885 if (aac_hba_setup(softs) != AACOK)
887 886 goto error;
888 887 attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP;
889 888
890 889 /* Create devctl/scsi nodes for cfgadm */
891 890 if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
892 891 INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
893 892 AACDB_PRINT(softs, CE_WARN, "failed to create devctl node");
894 893 goto error;
895 894 }
896 895 attach_state |= AAC_ATTACH_CREATE_DEVCTL;
897 896
898 897 if (ddi_create_minor_node(dip, "scsi", S_IFCHR, INST2SCSI(instance),
899 898 DDI_NT_SCSI_ATTACHMENT_POINT, 0) != DDI_SUCCESS) {
900 899 AACDB_PRINT(softs, CE_WARN, "failed to create scsi node");
901 900 goto error;
902 901 }
903 902 attach_state |= AAC_ATTACH_CREATE_SCSI;
904 903
905 904 /* Create aac node for app. to issue ioctls */
906 905 if (ddi_create_minor_node(dip, "aac", S_IFCHR, INST2AAC(instance),
907 906 DDI_PSEUDO, 0) != DDI_SUCCESS) {
908 907 AACDB_PRINT(softs, CE_WARN, "failed to create aac node");
909 908 goto error;
910 909 }
911 910
912 911 /* Common attach is OK, so we are attached! */
913 912 softs->state |= AAC_STATE_RUN;
914 913
915 914 /* Create event thread */
916 915 softs->fibctx_p = &softs->aifctx;
917 916 if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread,
918 917 softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) {
919 918 AACDB_PRINT(softs, CE_WARN, "aif thread create failed");
920 919 softs->state &= ~AAC_STATE_RUN;
921 920 goto error;
922 921 }
923 922
924 923 aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
925 924
926 925 /* Create a thread for command timeout */
927 926 softs->timeout_id = timeout(aac_timer, (void *)softs,
928 927 (aac_tick * drv_usectohz(1000000)));
929 928
930 929 /* Common attach is OK, so we are attached! */
931 930 ddi_report_dev(dip);
932 931 AACDB_PRINT(softs, CE_NOTE, "aac attached ok");
933 932 return (DDI_SUCCESS);
934 933
935 934 error:
936 935 if (attach_state & AAC_ATTACH_CREATE_SCSI)
937 936 ddi_remove_minor_node(dip, "scsi");
938 937 if (attach_state & AAC_ATTACH_CREATE_DEVCTL)
939 938 ddi_remove_minor_node(dip, "devctl");
940 939 if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
941 940 aac_common_detach(softs);
942 941 if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) {
943 942 (void) scsi_hba_detach(dip);
944 943 scsi_hba_tran_free(AAC_DIP2TRAN(dip));
945 944 }
946 945 if (attach_state & AAC_ATTACH_KMUTEX_INITED) {
947 946 mutex_destroy(&softs->io_lock);
948 947 mutex_destroy(&softs->q_comp_mutex);
949 948 mutex_destroy(&softs->time_mutex);
950 949 mutex_destroy(&softs->ev_lock);
951 950 mutex_destroy(&softs->aifq_mutex);
952 951 cv_destroy(&softs->event);
953 952 cv_destroy(&softs->sync_fib_cv);
954 953 cv_destroy(&softs->drain_cv);
955 954 cv_destroy(&softs->event_wait_cv);
956 955 cv_destroy(&softs->event_disp_cv);
957 956 cv_destroy(&softs->aifq_cv);
958 957 }
959 958 if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED)
960 959 ddi_regs_map_free(&softs->pci_mem_handle);
961 960 aac_fm_fini(softs);
962 961 if (attach_state & AAC_ATTACH_CARD_DETECTED)
963 962 softs->card = AACERR;
964 963 if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED)
965 964 ddi_soft_state_free(aac_softstatep, instance);
966 965 return (DDI_FAILURE);
967 966 }
968 967
969 968 static int
970 969 aac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
971 970 {
972 971 scsi_hba_tran_t *tran = AAC_DIP2TRAN(dip);
973 972 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
974 973
975 974 DBCALLED(softs, 1);
976 975
977 976 switch (cmd) {
978 977 case DDI_DETACH:
979 978 break;
980 979 case DDI_SUSPEND:
981 980 return (DDI_FAILURE);
982 981 default:
983 982 return (DDI_FAILURE);
984 983 }
985 984
986 985 mutex_enter(&softs->io_lock);
987 986 AAC_DISABLE_INTR(softs);
988 987 softs->state = AAC_STATE_STOPPED;
989 988
990 989 ddi_remove_minor_node(dip, "aac");
991 990 ddi_remove_minor_node(dip, "scsi");
992 991 ddi_remove_minor_node(dip, "devctl");
993 992 mutex_exit(&softs->io_lock);
994 993
995 994 aac_common_detach(softs);
996 995
997 996 mutex_enter(&softs->io_lock);
998 997 (void) scsi_hba_detach(dip);
999 998 scsi_hba_tran_free(tran);
1000 999 mutex_exit(&softs->io_lock);
1001 1000
1002 1001 /* Stop timer */
1003 1002 mutex_enter(&softs->time_mutex);
1004 1003 if (softs->timeout_id) {
1005 1004 timeout_id_t tid = softs->timeout_id;
1006 1005 softs->timeout_id = 0;
1007 1006
1008 1007 mutex_exit(&softs->time_mutex);
1009 1008 (void) untimeout(tid);
1010 1009 mutex_enter(&softs->time_mutex);
1011 1010 }
1012 1011 mutex_exit(&softs->time_mutex);
1013 1012
1014 1013 /* Destroy event thread */
1015 1014 mutex_enter(&softs->ev_lock);
1016 1015 cv_signal(&softs->event_disp_cv);
1017 1016 cv_wait(&softs->event_wait_cv, &softs->ev_lock);
1018 1017 mutex_exit(&softs->ev_lock);
1019 1018
1020 1019 cv_destroy(&softs->aifq_cv);
1021 1020 cv_destroy(&softs->event_disp_cv);
1022 1021 cv_destroy(&softs->event_wait_cv);
1023 1022 cv_destroy(&softs->drain_cv);
1024 1023 cv_destroy(&softs->sync_fib_cv);
1025 1024 cv_destroy(&softs->event);
1026 1025 mutex_destroy(&softs->aifq_mutex);
1027 1026 mutex_destroy(&softs->ev_lock);
1028 1027 mutex_destroy(&softs->time_mutex);
1029 1028 mutex_destroy(&softs->q_comp_mutex);
1030 1029 mutex_destroy(&softs->io_lock);
1031 1030
1032 1031 ddi_regs_map_free(&softs->pci_mem_handle);
1033 1032 aac_fm_fini(softs);
1034 1033 softs->hwif = AAC_HWIF_UNKNOWN;
1035 1034 softs->card = AAC_UNKNOWN_CARD;
1036 1035 ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip));
1037 1036
1038 1037 return (DDI_SUCCESS);
1039 1038 }
1040 1039
1041 1040 /*ARGSUSED*/
1042 1041 static int
1043 1042 aac_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
1044 1043 {
1045 1044 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
1046 1045
1047 1046 DBCALLED(softs, 1);
1048 1047
1049 1048 mutex_enter(&softs->io_lock);
1050 1049 AAC_DISABLE_INTR(softs);
1051 1050 (void) aac_shutdown(softs);
1052 1051 mutex_exit(&softs->io_lock);
1053 1052
1054 1053 return (DDI_SUCCESS);
1055 1054 }
1056 1055
1057 1056 /*
1058 1057 * quiesce(9E) entry point.
1059 1058 *
1060 1059 * This function is called when the system is single-threaded at high
1061 1060 * PIL with preemption disabled. Therefore, this function must not be
1062 1061 * blocked.
1063 1062 *
1064 1063 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1065 1064 * DDI_FAILURE indicates an error condition and should almost never happen.
1066 1065 */
1067 1066 static int
1068 1067 aac_quiesce(dev_info_t *dip)
1069 1068 {
1070 1069 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
1071 1070
1072 1071 if (softs == NULL)
1073 1072 return (DDI_FAILURE);
1074 1073
1075 1074 _NOTE(ASSUMING_PROTECTED(softs->state))
1076 1075 AAC_DISABLE_INTR(softs);
1077 1076
1078 1077 return (DDI_SUCCESS);
1079 1078 }
1080 1079
1081 1080 /* ARGSUSED */
1082 1081 static int
1083 1082 aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg,
1084 1083 void **result)
1085 1084 {
1086 1085 int error = DDI_SUCCESS;
1087 1086
1088 1087 switch (infocmd) {
1089 1088 case DDI_INFO_DEVT2INSTANCE:
1090 1089 *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg)));
1091 1090 break;
1092 1091 default:
1093 1092 error = DDI_FAILURE;
1094 1093 }
1095 1094 return (error);
1096 1095 }
1097 1096
1098 1097 /*
1099 1098 * Bring the controller down to a dormant state and detach all child devices.
1100 1099 * This function is called before detach or system shutdown.
1101 1100 * Note: we can assume that the q_wait on the controller is empty, as we
1102 1101 * won't allow shutdown if any device is open.
1103 1102 */
1104 1103 static int
1105 1104 aac_shutdown(struct aac_softstate *softs)
1106 1105 {
1107 1106 ddi_acc_handle_t acc;
1108 1107 struct aac_close_command *cc;
1109 1108 int rval;
1110 1109
1111 1110 (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
1112 1111 acc = softs->sync_ac.slotp->fib_acc_handle;
1113 1112
1114 1113 cc = (struct aac_close_command *)&softs->sync_ac.slotp->fibp->data[0];
1115 1114
1116 1115 ddi_put32(acc, &cc->Command, VM_CloseAll);
1117 1116 ddi_put32(acc, &cc->ContainerId, 0xfffffffful);
1118 1117
1119 1118 /* Flush all caches, set FW to write through mode */
1120 1119 rval = aac_sync_fib(softs, ContainerCommand,
1121 1120 AAC_FIB_SIZEOF(struct aac_close_command));
1122 1121 aac_sync_fib_slot_release(softs, &softs->sync_ac);
1123 1122
1124 1123 AACDB_PRINT(softs, CE_NOTE,
1125 1124 "shutting down aac %s", (rval == AACOK) ? "ok" : "fail");
1126 1125 return (rval);
1127 1126 }
1128 1127
1129 1128 static uint_t
1130 1129 aac_softintr(caddr_t arg)
1131 1130 {
1132 1131 struct aac_softstate *softs = (void *)arg;
1133 1132
1134 1133 if (!AAC_IS_Q_EMPTY(&softs->q_comp)) {
1135 1134 aac_drain_comp_q(softs);
1136 1135 }
1137 1136 return (DDI_INTR_CLAIMED);
1138 1137 }
1139 1138
1140 1139 /*
1141 1140 * Setup auto sense data for pkt
1142 1141 */
1143 1142 static void
1144 1143 aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key,
1145 1144 uchar_t add_code, uchar_t qual_code, uint64_t info)
1146 1145 {
1147 1146 struct scsi_arq_status *arqstat = (void *)(pkt->pkt_scbp);
1148 1147
1149 1148 *pkt->pkt_scbp = STATUS_CHECK; /* CHECK CONDITION */
1150 1149 pkt->pkt_state |= STATE_ARQ_DONE;
1151 1150
1152 1151 *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
1153 1152 arqstat->sts_rqpkt_reason = CMD_CMPLT;
1154 1153 arqstat->sts_rqpkt_resid = 0;
1155 1154 arqstat->sts_rqpkt_state =
1156 1155 STATE_GOT_BUS |
1157 1156 STATE_GOT_TARGET |
1158 1157 STATE_SENT_CMD |
1159 1158 STATE_XFERRED_DATA;
1160 1159 arqstat->sts_rqpkt_statistics = 0;
1161 1160
1162 1161 if (info <= 0xfffffffful) {
1163 1162 arqstat->sts_sensedata.es_valid = 1;
1164 1163 arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
1165 1164 arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT;
1166 1165 arqstat->sts_sensedata.es_key = key;
1167 1166 arqstat->sts_sensedata.es_add_code = add_code;
1168 1167 arqstat->sts_sensedata.es_qual_code = qual_code;
1169 1168
1170 1169 arqstat->sts_sensedata.es_info_1 = (info >> 24) & 0xFF;
1171 1170 arqstat->sts_sensedata.es_info_2 = (info >> 16) & 0xFF;
1172 1171 arqstat->sts_sensedata.es_info_3 = (info >> 8) & 0xFF;
1173 1172 arqstat->sts_sensedata.es_info_4 = info & 0xFF;
1174 1173 } else { /* 64-bit LBA */
1175 1174 struct scsi_descr_sense_hdr *dsp;
1176 1175 struct scsi_information_sense_descr *isd;
1177 1176
1178 1177 dsp = (struct scsi_descr_sense_hdr *)&arqstat->sts_sensedata;
1179 1178 dsp->ds_class = CLASS_EXTENDED_SENSE;
1180 1179 dsp->ds_code = CODE_FMT_DESCR_CURRENT;
1181 1180 dsp->ds_key = key;
1182 1181 dsp->ds_add_code = add_code;
1183 1182 dsp->ds_qual_code = qual_code;
1184 1183 dsp->ds_addl_sense_length =
1185 1184 sizeof (struct scsi_information_sense_descr);
1186 1185
1187 1186 isd = (struct scsi_information_sense_descr *)(dsp+1);
1188 1187 isd->isd_descr_type = DESCR_INFORMATION;
1189 1188 isd->isd_valid = 1;
1190 1189 isd->isd_information[0] = (info >> 56) & 0xFF;
1191 1190 isd->isd_information[1] = (info >> 48) & 0xFF;
1192 1191 isd->isd_information[2] = (info >> 40) & 0xFF;
1193 1192 isd->isd_information[3] = (info >> 32) & 0xFF;
1194 1193 isd->isd_information[4] = (info >> 24) & 0xFF;
1195 1194 isd->isd_information[5] = (info >> 16) & 0xFF;
1196 1195 isd->isd_information[6] = (info >> 8) & 0xFF;
1197 1196 isd->isd_information[7] = (info) & 0xFF;
1198 1197 }
1199 1198 }
1200 1199
1201 1200 /*
1202 1201 * Setup auto sense data for HARDWARE ERROR
1203 1202 */
1204 1203 static void
1205 1204 aac_set_arq_data_hwerr(struct aac_cmd *acp)
1206 1205 {
1207 1206 union scsi_cdb *cdbp;
1208 1207 uint64_t err_blkno;
1209 1208
1210 1209 cdbp = (void *)acp->pkt->pkt_cdbp;
1211 1210 err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp);
1212 1211 aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno);
1213 1212 }
1214 1213
1215 1214 /*
1216 1215 * Send a command to the adapter in New Comm. interface
1217 1216 */
1218 1217 static int
1219 1218 aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp)
1220 1219 {
1221 1220 uint32_t index, device;
1222 1221
1223 1222 index = PCI_MEM_GET32(softs, AAC_IQUE);
1224 1223 if (index == 0xffffffffUL) {
1225 1224 index = PCI_MEM_GET32(softs, AAC_IQUE);
1226 1225 if (index == 0xffffffffUL)
1227 1226 return (AACERR);
1228 1227 }
1229 1228
1230 1229 device = index;
1231 1230 PCI_MEM_PUT32(softs, device,
1232 1231 (uint32_t)(slotp->fib_phyaddr & 0xfffffffful));
1233 1232 device += 4;
1234 1233 PCI_MEM_PUT32(softs, device, (uint32_t)(slotp->fib_phyaddr >> 32));
1235 1234 device += 4;
1236 1235 PCI_MEM_PUT32(softs, device, slotp->acp->fib_size);
1237 1236 PCI_MEM_PUT32(softs, AAC_IQUE, index);
1238 1237 return (AACOK);
1239 1238 }
1240 1239
1241 1240 static void
1242 1241 aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp)
1243 1242 {
1244 1243 struct aac_device *dvp = acp->dvp;
1245 1244 int q = AAC_CMDQ(acp);
1246 1245
1247 1246 if (acp->slotp) { /* outstanding cmd */
1248 1247 if (!(acp->flags & AAC_CMD_IN_SYNC_SLOT)) {
1249 1248 aac_release_slot(softs, acp->slotp);
1250 1249 acp->slotp = NULL;
1251 1250 }
1252 1251 if (dvp) {
1253 1252 dvp->ncmds[q]--;
1254 1253 if (dvp->throttle[q] == AAC_THROTTLE_DRAIN &&
1255 1254 dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC)
1256 1255 aac_set_throttle(softs, dvp, q,
1257 1256 softs->total_slots);
1258 1257 /*
1259 1258 * Setup auto sense data for UNIT ATTENTION
1260 1259 * Each lun should generate a unit attention
1261 1260 * condition when reset.
1262 1261 * Phys. drives are treated as logical ones
1263 1262 * during error recovery.
1264 1263 */
1265 1264 if (dvp->type == AAC_DEV_LD) {
1266 1265 struct aac_container *ctp =
1267 1266 (struct aac_container *)dvp;
1268 1267 if (ctp->reset == 0)
1269 1268 goto noreset;
1270 1269
1271 1270 AACDB_PRINT(softs, CE_NOTE,
1272 1271 "Unit attention: reset");
1273 1272 ctp->reset = 0;
1274 1273 aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION,
1275 1274 0x29, 0x02, 0);
1276 1275 }
1277 1276 }
1278 1277 noreset:
1279 1278 softs->bus_ncmds[q]--;
1280 1279 aac_cmd_delete(&softs->q_busy, acp);
1281 1280 } else { /* cmd in waiting queue */
1282 1281 aac_cmd_delete(&softs->q_wait[q], acp);
1283 1282 }
1284 1283
1285 1284 if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) { /* async IO */
1286 1285 mutex_enter(&softs->q_comp_mutex);
1287 1286 aac_cmd_enqueue(&softs->q_comp, acp);
1288 1287 mutex_exit(&softs->q_comp_mutex);
1289 1288 } else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */
1290 1289 cv_broadcast(&softs->event);
1291 1290 }
1292 1291 }
1293 1292
1294 1293 static void
1295 1294 aac_handle_io(struct aac_softstate *softs, int index)
1296 1295 {
1297 1296 struct aac_slot *slotp;
1298 1297 struct aac_cmd *acp;
1299 1298 uint32_t fast;
1300 1299
1301 1300 fast = index & AAC_SENDERADDR_MASK_FAST_RESPONSE;
1302 1301 index >>= 2;
1303 1302
1304 1303 /* Make sure firmware reported index is valid */
1305 1304 ASSERT(index >= 0 && index < softs->total_slots);
1306 1305 slotp = &softs->io_slot[index];
1307 1306 ASSERT(slotp->index == index);
1308 1307 acp = slotp->acp;
1309 1308
1310 1309 if (acp == NULL || acp->slotp != slotp) {
1311 1310 cmn_err(CE_WARN,
1312 1311 "Firmware error: invalid slot index received from FW");
1313 1312 return;
1314 1313 }
1315 1314
1316 1315 acp->flags |= AAC_CMD_CMPLT;
1317 1316 (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
1318 1317
1319 1318 if (aac_check_dma_handle(slotp->fib_dma_handle) == DDI_SUCCESS) {
1320 1319 /*
1321 1320 * For fast response IO, the firmware do not return any FIB
1322 1321 * data, so we need to fill in the FIB status and state so that
1323 1322 * FIB users can handle it correctly.
1324 1323 */
1325 1324 if (fast) {
1326 1325 uint32_t state;
1327 1326
1328 1327 state = ddi_get32(slotp->fib_acc_handle,
1329 1328 &slotp->fibp->Header.XferState);
1330 1329 /*
1331 1330 * Update state for CPU not for device, no DMA sync
1332 1331 * needed
1333 1332 */
1334 1333 ddi_put32(slotp->fib_acc_handle,
1335 1334 &slotp->fibp->Header.XferState,
1336 1335 state | AAC_FIBSTATE_DONEADAP);
1337 1336 ddi_put32(slotp->fib_acc_handle,
1338 1337 (void *)&slotp->fibp->data[0], ST_OK);
1339 1338 }
1340 1339
1341 1340 /* Handle completed ac */
1342 1341 acp->ac_comp(softs, acp);
1343 1342 } else {
1344 1343 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1345 1344 acp->flags |= AAC_CMD_ERR;
1346 1345 if (acp->pkt) {
1347 1346 acp->pkt->pkt_reason = CMD_TRAN_ERR;
1348 1347 acp->pkt->pkt_statistics = 0;
1349 1348 }
1350 1349 }
1351 1350 aac_end_io(softs, acp);
1352 1351 }
1353 1352
1354 1353 /*
1355 1354 * Interrupt handler for New Comm. interface
1356 1355 * New Comm. interface use a different mechanism for interrupt. No explict
1357 1356 * message queues, and driver need only accesses the mapped PCI mem space to
1358 1357 * find the completed FIB or AIF.
1359 1358 */
1360 1359 static int
1361 1360 aac_process_intr_new(struct aac_softstate *softs)
1362 1361 {
1363 1362 uint32_t index;
1364 1363
1365 1364 index = AAC_OUTB_GET(softs);
1366 1365 if (index == 0xfffffffful)
1367 1366 index = AAC_OUTB_GET(softs);
1368 1367 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
1369 1368 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1370 1369 return (0);
1371 1370 }
1372 1371 if (index != 0xfffffffful) {
1373 1372 do {
1374 1373 if ((index & AAC_SENDERADDR_MASK_AIF) == 0) {
1375 1374 aac_handle_io(softs, index);
1376 1375 } else if (index != 0xfffffffeul) {
1377 1376 struct aac_fib *fibp; /* FIB in AIF queue */
1378 1377 uint16_t fib_size;
1379 1378
1380 1379 /*
1381 1380 * 0xfffffffe means that the controller wants
1382 1381 * more work, ignore it for now. Otherwise,
1383 1382 * AIF received.
1384 1383 */
1385 1384 index &= ~2;
1386 1385
1387 1386 fibp = (struct aac_fib *)(softs-> \
1388 1387 pci_mem_base_vaddr + index);
1389 1388 fib_size = PCI_MEM_GET16(softs, index + \
1390 1389 offsetof(struct aac_fib, Header.Size));
1391 1390
1392 1391 aac_save_aif(softs, softs->pci_mem_handle,
1393 1392 fibp, fib_size);
1394 1393
1395 1394 /*
1396 1395 * AIF memory is owned by the adapter, so let it
1397 1396 * know that we are done with it.
1398 1397 */
1399 1398 AAC_OUTB_SET(softs, index);
1400 1399 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
1401 1400 }
1402 1401
1403 1402 index = AAC_OUTB_GET(softs);
1404 1403 } while (index != 0xfffffffful);
1405 1404
1406 1405 /*
1407 1406 * Process waiting cmds before start new ones to
1408 1407 * ensure first IOs are serviced first.
1409 1408 */
1410 1409 aac_start_waiting_io(softs);
1411 1410 return (AAC_DB_COMMAND_READY);
1412 1411 } else {
1413 1412 return (0);
1414 1413 }
1415 1414 }
1416 1415
1417 1416 static uint_t
1418 1417 aac_intr_new(caddr_t arg)
1419 1418 {
1420 1419 struct aac_softstate *softs = (void *)arg;
1421 1420 uint_t rval;
1422 1421
1423 1422 mutex_enter(&softs->io_lock);
1424 1423 if (aac_process_intr_new(softs))
1425 1424 rval = DDI_INTR_CLAIMED;
1426 1425 else
1427 1426 rval = DDI_INTR_UNCLAIMED;
1428 1427 mutex_exit(&softs->io_lock);
1429 1428
1430 1429 aac_drain_comp_q(softs);
1431 1430 return (rval);
1432 1431 }
1433 1432
1434 1433 /*
1435 1434 * Interrupt handler for old interface
1436 1435 * Explicit message queues are used to send FIB to and get completed FIB from
1437 1436 * the adapter. Driver and adapter maitain the queues in the producer/consumer
1438 1437 * manner. The driver has to query the queues to find the completed FIB.
1439 1438 */
1440 1439 static int
1441 1440 aac_process_intr_old(struct aac_softstate *softs)
1442 1441 {
1443 1442 uint16_t status;
1444 1443
1445 1444 status = AAC_STATUS_GET(softs);
1446 1445 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
1447 1446 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
1448 1447 return (DDI_INTR_UNCLAIMED);
1449 1448 }
1450 1449 if (status & AAC_DB_RESPONSE_READY) {
1451 1450 int slot_idx;
1452 1451
1453 1452 /* ACK the intr */
1454 1453 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY);
1455 1454 (void) AAC_STATUS_GET(softs);
1456 1455 while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q,
1457 1456 &slot_idx) == AACOK)
1458 1457 aac_handle_io(softs, slot_idx);
1459 1458
1460 1459 /*
1461 1460 * Process waiting cmds before start new ones to
1462 1461 * ensure first IOs are serviced first.
1463 1462 */
1464 1463 aac_start_waiting_io(softs);
1465 1464 return (AAC_DB_RESPONSE_READY);
1466 1465 } else if (status & AAC_DB_COMMAND_READY) {
1467 1466 int aif_idx;
1468 1467
1469 1468 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY);
1470 1469 (void) AAC_STATUS_GET(softs);
1471 1470 if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) ==
1472 1471 AACOK) {
1473 1472 ddi_acc_handle_t acc = softs->comm_space_acc_handle;
1474 1473 struct aac_fib *fibp; /* FIB in communication space */
1475 1474 uint16_t fib_size;
1476 1475 uint32_t fib_xfer_state;
1477 1476 uint32_t addr, size;
1478 1477
1479 1478 ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS));
1480 1479
1481 1480 #define AAC_SYNC_AIF(softs, aif_idx, type) \
1482 1481 { (void) ddi_dma_sync((softs)->comm_space_dma_handle, \
1483 1482 offsetof(struct aac_comm_space, \
1484 1483 adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \
1485 1484 (type)); }
1486 1485
1487 1486 /* Copy AIF from adapter to the empty AIF slot */
1488 1487 AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU);
1489 1488 fibp = &softs->comm_space->adapter_fibs[aif_idx];
1490 1489 fib_size = ddi_get16(acc, &fibp->Header.Size);
1491 1490
1492 1491 aac_save_aif(softs, acc, fibp, fib_size);
1493 1492
1494 1493 /* Complete AIF back to adapter with good status */
1495 1494 fib_xfer_state = LE_32(fibp->Header.XferState);
1496 1495 if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) {
1497 1496 ddi_put32(acc, &fibp->Header.XferState,
1498 1497 fib_xfer_state | AAC_FIBSTATE_DONEHOST);
1499 1498 ddi_put32(acc, (void *)&fibp->data[0], ST_OK);
1500 1499 if (fib_size > AAC_FIB_SIZE)
1501 1500 ddi_put16(acc, &fibp->Header.Size,
1502 1501 AAC_FIB_SIZE);
1503 1502 AAC_SYNC_AIF(softs, aif_idx,
1504 1503 DDI_DMA_SYNC_FORDEV);
1505 1504 }
1506 1505
1507 1506 /* Put the AIF response on the response queue */
1508 1507 addr = ddi_get32(acc,
1509 1508 &softs->comm_space->adapter_fibs[aif_idx]. \
1510 1509 Header.SenderFibAddress);
1511 1510 size = (uint32_t)ddi_get16(acc,
1512 1511 &softs->comm_space->adapter_fibs[aif_idx]. \
1513 1512 Header.Size);
1514 1513 ddi_put32(acc,
1515 1514 &softs->comm_space->adapter_fibs[aif_idx]. \
1516 1515 Header.ReceiverFibAddress, addr);
1517 1516 if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q,
1518 1517 addr, size) == AACERR)
1519 1518 cmn_err(CE_NOTE, "!AIF ack failed");
1520 1519 }
1521 1520 return (AAC_DB_COMMAND_READY);
1522 1521 } else if (status & AAC_DB_PRINTF_READY) {
1523 1522 /* ACK the intr */
1524 1523 AAC_STATUS_CLR(softs, AAC_DB_PRINTF_READY);
1525 1524 (void) AAC_STATUS_GET(softs);
1526 1525 (void) ddi_dma_sync(softs->comm_space_dma_handle,
1527 1526 offsetof(struct aac_comm_space, adapter_print_buf),
1528 1527 AAC_ADAPTER_PRINT_BUFSIZE, DDI_DMA_SYNC_FORCPU);
1529 1528 if (aac_check_dma_handle(softs->comm_space_dma_handle) ==
1530 1529 DDI_SUCCESS)
1531 1530 cmn_err(CE_NOTE, "MSG From Adapter: %s",
1532 1531 softs->comm_space->adapter_print_buf);
1533 1532 else
1534 1533 ddi_fm_service_impact(softs->devinfo_p,
1535 1534 DDI_SERVICE_UNAFFECTED);
1536 1535 AAC_NOTIFY(softs, AAC_DB_PRINTF_READY);
1537 1536 return (AAC_DB_PRINTF_READY);
1538 1537 } else if (status & AAC_DB_COMMAND_NOT_FULL) {
1539 1538 /*
1540 1539 * Without these two condition statements, the OS could hang
1541 1540 * after a while, especially if there are a lot of AIF's to
1542 1541 * handle, for instance if a drive is pulled from an array
1543 1542 * under heavy load.
1544 1543 */
1545 1544 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1546 1545 return (AAC_DB_COMMAND_NOT_FULL);
1547 1546 } else if (status & AAC_DB_RESPONSE_NOT_FULL) {
1548 1547 AAC_STATUS_CLR(softs, AAC_DB_COMMAND_NOT_FULL);
1549 1548 AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_NOT_FULL);
1550 1549 return (AAC_DB_RESPONSE_NOT_FULL);
1551 1550 } else {
1552 1551 return (0);
1553 1552 }
1554 1553 }
1555 1554
1556 1555 static uint_t
1557 1556 aac_intr_old(caddr_t arg)
1558 1557 {
1559 1558 struct aac_softstate *softs = (void *)arg;
1560 1559 int rval;
1561 1560
1562 1561 mutex_enter(&softs->io_lock);
1563 1562 if (aac_process_intr_old(softs))
1564 1563 rval = DDI_INTR_CLAIMED;
1565 1564 else
1566 1565 rval = DDI_INTR_UNCLAIMED;
1567 1566 mutex_exit(&softs->io_lock);
1568 1567
1569 1568 aac_drain_comp_q(softs);
1570 1569 return (rval);
1571 1570 }
1572 1571
1573 1572 /*
1574 1573 * Query FIXED or MSI interrupts
1575 1574 */
1576 1575 static int
1577 1576 aac_query_intrs(struct aac_softstate *softs, int intr_type)
1578 1577 {
1579 1578 dev_info_t *dip = softs->devinfo_p;
1580 1579 int avail, actual, count;
1581 1580 int i, flag, ret;
1582 1581
1583 1582 AACDB_PRINT(softs, CE_NOTE,
1584 1583 "aac_query_intrs:interrupt type 0x%x", intr_type);
1585 1584
1586 1585 /* Get number of interrupts */
1587 1586 ret = ddi_intr_get_nintrs(dip, intr_type, &count);
1588 1587 if ((ret != DDI_SUCCESS) || (count == 0)) {
1589 1588 AACDB_PRINT(softs, CE_WARN,
1590 1589 "ddi_intr_get_nintrs() failed, ret %d count %d",
1591 1590 ret, count);
1592 1591 return (DDI_FAILURE);
1593 1592 }
1594 1593
1595 1594 /* Get number of available interrupts */
1596 1595 ret = ddi_intr_get_navail(dip, intr_type, &avail);
1597 1596 if ((ret != DDI_SUCCESS) || (avail == 0)) {
1598 1597 AACDB_PRINT(softs, CE_WARN,
1599 1598 "ddi_intr_get_navail() failed, ret %d avail %d",
1600 1599 ret, avail);
1601 1600 return (DDI_FAILURE);
1602 1601 }
1603 1602
1604 1603 AACDB_PRINT(softs, CE_NOTE,
1605 1604 "ddi_intr_get_nvail returned %d, navail() returned %d",
1606 1605 count, avail);
1607 1606
1608 1607 /* Allocate an array of interrupt handles */
1609 1608 softs->intr_size = count * sizeof (ddi_intr_handle_t);
1610 1609 softs->htable = kmem_alloc(softs->intr_size, KM_SLEEP);
1611 1610
1612 1611 if (intr_type == DDI_INTR_TYPE_MSI) {
1613 1612 count = 1; /* only one vector needed by now */
1614 1613 flag = DDI_INTR_ALLOC_STRICT;
1615 1614 } else { /* must be DDI_INTR_TYPE_FIXED */
1616 1615 flag = DDI_INTR_ALLOC_NORMAL;
1617 1616 }
1618 1617
1619 1618 /* Call ddi_intr_alloc() */
1620 1619 ret = ddi_intr_alloc(dip, softs->htable, intr_type, 0,
1621 1620 count, &actual, flag);
1622 1621
1623 1622 if ((ret != DDI_SUCCESS) || (actual == 0)) {
1624 1623 AACDB_PRINT(softs, CE_WARN,
1625 1624 "ddi_intr_alloc() failed, ret = %d", ret);
1626 1625 actual = 0;
1627 1626 goto error;
1628 1627 }
1629 1628
1630 1629 if (actual < count) {
1631 1630 AACDB_PRINT(softs, CE_NOTE,
1632 1631 "Requested: %d, Received: %d", count, actual);
1633 1632 goto error;
1634 1633 }
1635 1634
1636 1635 softs->intr_cnt = actual;
1637 1636
1638 1637 /* Get priority for first msi, assume remaining are all the same */
1639 1638 if ((ret = ddi_intr_get_pri(softs->htable[0],
1640 1639 &softs->intr_pri)) != DDI_SUCCESS) {
1641 1640 AACDB_PRINT(softs, CE_WARN,
1642 1641 "ddi_intr_get_pri() failed, ret = %d", ret);
1643 1642 goto error;
1644 1643 }
1645 1644
1646 1645 /* Test for high level mutex */
1647 1646 if (softs->intr_pri >= ddi_intr_get_hilevel_pri()) {
1648 1647 AACDB_PRINT(softs, CE_WARN,
1649 1648 "aac_query_intrs: Hi level interrupt not supported");
1650 1649 goto error;
1651 1650 }
1652 1651
1653 1652 return (DDI_SUCCESS);
1654 1653
1655 1654 error:
1656 1655 /* Free already allocated intr */
1657 1656 for (i = 0; i < actual; i++)
1658 1657 (void) ddi_intr_free(softs->htable[i]);
1659 1658
1660 1659 kmem_free(softs->htable, softs->intr_size);
1661 1660 return (DDI_FAILURE);
1662 1661 }
1663 1662
1664 1663
1665 1664 /*
1666 1665 * Register FIXED or MSI interrupts, and enable them
1667 1666 */
1668 1667 static int
1669 1668 aac_add_intrs(struct aac_softstate *softs)
1670 1669 {
1671 1670 int i, ret;
1672 1671 int actual;
1673 1672 ddi_intr_handler_t *aac_intr;
1674 1673
1675 1674 actual = softs->intr_cnt;
1676 1675 aac_intr = (ddi_intr_handler_t *)((softs->flags & AAC_FLAGS_NEW_COMM) ?
1677 1676 aac_intr_new : aac_intr_old);
1678 1677
1679 1678 /* Call ddi_intr_add_handler() */
1680 1679 for (i = 0; i < actual; i++) {
1681 1680 if ((ret = ddi_intr_add_handler(softs->htable[i],
1682 1681 aac_intr, (caddr_t)softs, NULL)) != DDI_SUCCESS) {
1683 1682 cmn_err(CE_WARN,
1684 1683 "ddi_intr_add_handler() failed ret = %d", ret);
1685 1684
1686 1685 /* Free already allocated intr */
1687 1686 for (i = 0; i < actual; i++)
1688 1687 (void) ddi_intr_free(softs->htable[i]);
1689 1688
1690 1689 kmem_free(softs->htable, softs->intr_size);
1691 1690 return (DDI_FAILURE);
1692 1691 }
1693 1692 }
1694 1693
1695 1694 if ((ret = ddi_intr_get_cap(softs->htable[0], &softs->intr_cap))
1696 1695 != DDI_SUCCESS) {
1697 1696 cmn_err(CE_WARN, "ddi_intr_get_cap() failed, ret = %d", ret);
1698 1697
1699 1698 /* Free already allocated intr */
1700 1699 for (i = 0; i < actual; i++)
1701 1700 (void) ddi_intr_free(softs->htable[i]);
1702 1701
1703 1702 kmem_free(softs->htable, softs->intr_size);
1704 1703 return (DDI_FAILURE);
1705 1704 }
1706 1705
1707 1706 return (DDI_SUCCESS);
1708 1707 }
1709 1708
1710 1709 /*
1711 1710 * Unregister FIXED or MSI interrupts
1712 1711 */
1713 1712 static void
1714 1713 aac_remove_intrs(struct aac_softstate *softs)
1715 1714 {
1716 1715 int i;
1717 1716
1718 1717 /* Disable all interrupts */
1719 1718 (void) aac_disable_intrs(softs);
1720 1719 /* Call ddi_intr_remove_handler() */
1721 1720 for (i = 0; i < softs->intr_cnt; i++) {
1722 1721 (void) ddi_intr_remove_handler(softs->htable[i]);
1723 1722 (void) ddi_intr_free(softs->htable[i]);
1724 1723 }
1725 1724
1726 1725 kmem_free(softs->htable, softs->intr_size);
1727 1726 }
1728 1727
1729 1728 static int
1730 1729 aac_enable_intrs(struct aac_softstate *softs)
1731 1730 {
1732 1731 int rval = AACOK;
1733 1732
1734 1733 if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) {
1735 1734 /* for MSI block enable */
1736 1735 if (ddi_intr_block_enable(softs->htable, softs->intr_cnt) !=
1737 1736 DDI_SUCCESS)
1738 1737 rval = AACERR;
1739 1738 } else {
1740 1739 int i;
1741 1740
1742 1741 /* Call ddi_intr_enable() for legacy/MSI non block enable */
1743 1742 for (i = 0; i < softs->intr_cnt; i++) {
1744 1743 if (ddi_intr_enable(softs->htable[i]) != DDI_SUCCESS)
1745 1744 rval = AACERR;
1746 1745 }
1747 1746 }
1748 1747 return (rval);
1749 1748 }
1750 1749
1751 1750 static int
1752 1751 aac_disable_intrs(struct aac_softstate *softs)
1753 1752 {
1754 1753 int rval = AACOK;
1755 1754
1756 1755 if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) {
1757 1756 /* Call ddi_intr_block_disable() */
1758 1757 if (ddi_intr_block_disable(softs->htable, softs->intr_cnt) !=
1759 1758 DDI_SUCCESS)
1760 1759 rval = AACERR;
1761 1760 } else {
1762 1761 int i;
1763 1762
1764 1763 for (i = 0; i < softs->intr_cnt; i++) {
1765 1764 if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS)
1766 1765 rval = AACERR;
1767 1766 }
1768 1767 }
1769 1768 return (rval);
1770 1769 }
1771 1770
1772 1771 /*
1773 1772 * Set pkt_reason and OR in pkt_statistics flag
1774 1773 */
1775 1774 static void
1776 1775 aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp,
1777 1776 uchar_t reason, uint_t stat)
1778 1777 {
1779 1778 #ifndef __lock_lint
1780 1779 _NOTE(ARGUNUSED(softs))
1781 1780 #endif
1782 1781 if (acp->pkt->pkt_reason == CMD_CMPLT)
1783 1782 acp->pkt->pkt_reason = reason;
1784 1783 acp->pkt->pkt_statistics |= stat;
1785 1784 }
1786 1785
1787 1786 /*
1788 1787 * Handle a finished pkt of soft SCMD
1789 1788 */
1790 1789 static void
1791 1790 aac_soft_callback(struct aac_softstate *softs, struct aac_cmd *acp)
1792 1791 {
1793 1792 ASSERT(acp->pkt);
1794 1793
1795 1794 acp->flags |= AAC_CMD_CMPLT;
1796 1795
1797 1796 acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \
1798 1797 STATE_SENT_CMD | STATE_GOT_STATUS;
1799 1798 if (acp->pkt->pkt_state & STATE_XFERRED_DATA)
1800 1799 acp->pkt->pkt_resid = 0;
1801 1800
1802 1801 /* AAC_CMD_NO_INTR means no complete callback */
1803 1802 if (!(acp->flags & AAC_CMD_NO_INTR)) {
1804 1803 mutex_enter(&softs->q_comp_mutex);
1805 1804 aac_cmd_enqueue(&softs->q_comp, acp);
1806 1805 mutex_exit(&softs->q_comp_mutex);
1807 1806 ddi_trigger_softintr(softs->softint_id);
1808 1807 }
1809 1808 }
1810 1809
1811 1810 /*
1812 1811 * Handlers for completed IOs, common to aac_intr_new() and aac_intr_old()
1813 1812 */
1814 1813
1815 1814 /*
1816 1815 * Handle completed logical device IO command
1817 1816 */
1818 1817 /*ARGSUSED*/
1819 1818 static void
1820 1819 aac_ld_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1821 1820 {
1822 1821 struct aac_slot *slotp = acp->slotp;
1823 1822 struct aac_blockread_response *resp;
1824 1823 uint32_t status;
1825 1824
1826 1825 ASSERT(!(acp->flags & AAC_CMD_SYNC));
1827 1826 ASSERT(!(acp->flags & AAC_CMD_NO_CB));
1828 1827
1829 1828 acp->pkt->pkt_state |= STATE_GOT_STATUS;
1830 1829
1831 1830 /*
1832 1831 * block_read/write has a similar response header, use blockread
1833 1832 * response for both.
1834 1833 */
1835 1834 resp = (struct aac_blockread_response *)&slotp->fibp->data[0];
1836 1835 status = ddi_get32(slotp->fib_acc_handle, &resp->Status);
1837 1836 if (status == ST_OK) {
1838 1837 acp->pkt->pkt_resid = 0;
1839 1838 acp->pkt->pkt_state |= STATE_XFERRED_DATA;
1840 1839 } else {
1841 1840 aac_set_arq_data_hwerr(acp);
1842 1841 }
1843 1842 }
1844 1843
1845 1844 /*
1846 1845 * Handle completed phys. device IO command
1847 1846 */
1848 1847 static void
1849 1848 aac_pd_complete(struct aac_softstate *softs, struct aac_cmd *acp)
1850 1849 {
1851 1850 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
1852 1851 struct aac_fib *fibp = acp->slotp->fibp;
1853 1852 struct scsi_pkt *pkt = acp->pkt;
1854 1853 struct aac_srb_reply *resp;
1855 1854 uint32_t resp_status;
1856 1855
1857 1856 ASSERT(!(acp->flags & AAC_CMD_SYNC));
1858 1857 ASSERT(!(acp->flags & AAC_CMD_NO_CB));
1859 1858
1860 1859 resp = (struct aac_srb_reply *)&fibp->data[0];
1861 1860 resp_status = ddi_get32(acc, &resp->status);
1862 1861
1863 1862 /* First check FIB status */
1864 1863 if (resp_status == ST_OK) {
1865 1864 uint32_t scsi_status;
1866 1865 uint32_t srb_status;
1867 1866 uint32_t data_xfer_length;
1868 1867
1869 1868 scsi_status = ddi_get32(acc, &resp->scsi_status);
1870 1869 srb_status = ddi_get32(acc, &resp->srb_status);
1871 1870 data_xfer_length = ddi_get32(acc, &resp->data_xfer_length);
1872 1871
1873 1872 *pkt->pkt_scbp = (uint8_t)scsi_status;
1874 1873 pkt->pkt_state |= STATE_GOT_STATUS;
1875 1874 if (scsi_status == STATUS_GOOD) {
1876 1875 uchar_t cmd = ((union scsi_cdb *)(void *)
1877 1876 (pkt->pkt_cdbp))->scc_cmd;
1878 1877
1879 1878 /* Next check SRB status */
1880 1879 switch (srb_status & 0x3f) {
1881 1880 case SRB_STATUS_DATA_OVERRUN:
1882 1881 AACDB_PRINT(softs, CE_NOTE, "DATA_OVERRUN: " \
1883 1882 "scmd=%d, xfer=%d, buflen=%d",
1884 1883 (uint32_t)cmd, data_xfer_length,
1885 1884 acp->bcount);
1886 1885
1887 1886 switch (cmd) {
1888 1887 case SCMD_READ:
1889 1888 case SCMD_WRITE:
1890 1889 case SCMD_READ_G1:
1891 1890 case SCMD_WRITE_G1:
1892 1891 case SCMD_READ_G4:
1893 1892 case SCMD_WRITE_G4:
1894 1893 case SCMD_READ_G5:
1895 1894 case SCMD_WRITE_G5:
1896 1895 aac_set_pkt_reason(softs, acp,
1897 1896 CMD_DATA_OVR, 0);
1898 1897 break;
1899 1898 }
1900 1899 /*FALLTHRU*/
1901 1900 case SRB_STATUS_ERROR_RECOVERY:
1902 1901 case SRB_STATUS_PENDING:
1903 1902 case SRB_STATUS_SUCCESS:
1904 1903 /*
1905 1904 * pkt_resid should only be calculated if the
1906 1905 * status is ERROR_RECOVERY/PENDING/SUCCESS/
1907 1906 * OVERRUN/UNDERRUN
1908 1907 */
1909 1908 if (data_xfer_length) {
1910 1909 pkt->pkt_state |= STATE_XFERRED_DATA;
1911 1910 pkt->pkt_resid = acp->bcount - \
1912 1911 data_xfer_length;
1913 1912 ASSERT(pkt->pkt_resid >= 0);
1914 1913 }
1915 1914 break;
1916 1915 case SRB_STATUS_ABORTED:
1917 1916 AACDB_PRINT(softs, CE_NOTE,
1918 1917 "SRB_STATUS_ABORTED, xfer=%d, resid=%d",
1919 1918 data_xfer_length, pkt->pkt_resid);
1920 1919 aac_set_pkt_reason(softs, acp, CMD_ABORTED,
1921 1920 STAT_ABORTED);
1922 1921 break;
1923 1922 case SRB_STATUS_ABORT_FAILED:
1924 1923 AACDB_PRINT(softs, CE_NOTE,
1925 1924 "SRB_STATUS_ABORT_FAILED, xfer=%d, " \
1926 1925 "resid=%d", data_xfer_length,
1927 1926 pkt->pkt_resid);
1928 1927 aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL,
1929 1928 0);
1930 1929 break;
1931 1930 case SRB_STATUS_PARITY_ERROR:
1932 1931 AACDB_PRINT(softs, CE_NOTE,
1933 1932 "SRB_STATUS_PARITY_ERROR, xfer=%d, " \
1934 1933 "resid=%d", data_xfer_length,
1935 1934 pkt->pkt_resid);
1936 1935 aac_set_pkt_reason(softs, acp, CMD_PER_FAIL, 0);
1937 1936 break;
1938 1937 case SRB_STATUS_NO_DEVICE:
1939 1938 case SRB_STATUS_INVALID_PATH_ID:
1940 1939 case SRB_STATUS_INVALID_TARGET_ID:
1941 1940 case SRB_STATUS_INVALID_LUN:
1942 1941 case SRB_STATUS_SELECTION_TIMEOUT:
1943 1942 #ifdef DEBUG
1944 1943 if (AAC_DEV_IS_VALID(acp->dvp)) {
1945 1944 AACDB_PRINT(softs, CE_NOTE,
1946 1945 "SRB_STATUS_NO_DEVICE(%d), " \
1947 1946 "xfer=%d, resid=%d ",
1948 1947 srb_status & 0x3f,
1949 1948 data_xfer_length, pkt->pkt_resid);
1950 1949 }
1951 1950 #endif
1952 1951 aac_set_pkt_reason(softs, acp, CMD_DEV_GONE, 0);
1953 1952 break;
1954 1953 case SRB_STATUS_COMMAND_TIMEOUT:
1955 1954 case SRB_STATUS_TIMEOUT:
1956 1955 AACDB_PRINT(softs, CE_NOTE,
1957 1956 "SRB_STATUS_COMMAND_TIMEOUT, xfer=%d, " \
1958 1957 "resid=%d", data_xfer_length,
1959 1958 pkt->pkt_resid);
1960 1959 aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
1961 1960 STAT_TIMEOUT);
1962 1961 break;
1963 1962 case SRB_STATUS_BUS_RESET:
1964 1963 AACDB_PRINT(softs, CE_NOTE,
1965 1964 "SRB_STATUS_BUS_RESET, xfer=%d, " \
1966 1965 "resid=%d", data_xfer_length,
1967 1966 pkt->pkt_resid);
1968 1967 aac_set_pkt_reason(softs, acp, CMD_RESET,
1969 1968 STAT_BUS_RESET);
1970 1969 break;
1971 1970 default:
1972 1971 AACDB_PRINT(softs, CE_NOTE, "srb_status=%d, " \
1973 1972 "xfer=%d, resid=%d", srb_status & 0x3f,
1974 1973 data_xfer_length, pkt->pkt_resid);
1975 1974 aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
1976 1975 break;
1977 1976 }
1978 1977 } else if (scsi_status == STATUS_CHECK) {
1979 1978 /* CHECK CONDITION */
1980 1979 struct scsi_arq_status *arqstat =
1981 1980 (void *)(pkt->pkt_scbp);
1982 1981 uint32_t sense_data_size;
1983 1982
1984 1983 pkt->pkt_state |= STATE_ARQ_DONE;
1985 1984
1986 1985 *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
1987 1986 arqstat->sts_rqpkt_reason = CMD_CMPLT;
1988 1987 arqstat->sts_rqpkt_resid = 0;
1989 1988 arqstat->sts_rqpkt_state =
1990 1989 STATE_GOT_BUS |
1991 1990 STATE_GOT_TARGET |
1992 1991 STATE_SENT_CMD |
1993 1992 STATE_XFERRED_DATA;
1994 1993 arqstat->sts_rqpkt_statistics = 0;
1995 1994
1996 1995 sense_data_size = ddi_get32(acc,
1997 1996 &resp->sense_data_size);
1998 1997 ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE);
1999 1998 AACDB_PRINT(softs, CE_NOTE,
2000 1999 "CHECK CONDITION: sense len=%d, xfer len=%d",
2001 2000 sense_data_size, data_xfer_length);
2002 2001
2003 2002 if (sense_data_size > SENSE_LENGTH)
2004 2003 sense_data_size = SENSE_LENGTH;
2005 2004 ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata,
2006 2005 (uint8_t *)resp->sense_data, sense_data_size,
2007 2006 DDI_DEV_AUTOINCR);
2008 2007 } else {
2009 2008 AACDB_PRINT(softs, CE_WARN, "invaild scsi status: " \
2010 2009 "scsi_status=%d, srb_status=%d",
2011 2010 scsi_status, srb_status);
2012 2011 aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
2013 2012 }
2014 2013 } else {
2015 2014 AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d",
2016 2015 resp_status);
2017 2016 aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0);
2018 2017 }
2019 2018 }
2020 2019
2021 2020 /*
2022 2021 * Handle completed IOCTL command
2023 2022 */
2024 2023 /*ARGSUSED*/
2025 2024 void
2026 2025 aac_ioctl_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2027 2026 {
2028 2027 struct aac_slot *slotp = acp->slotp;
2029 2028
2030 2029 /*
2031 2030 * NOTE: Both aac_ioctl_send_fib() and aac_send_raw_srb()
2032 2031 * may wait on softs->event, so use cv_broadcast() instead
2033 2032 * of cv_signal().
2034 2033 */
2035 2034 ASSERT(acp->flags & AAC_CMD_SYNC);
2036 2035 ASSERT(acp->flags & AAC_CMD_NO_CB);
2037 2036
2038 2037 /* Get the size of the response FIB from its FIB.Header.Size field */
2039 2038 acp->fib_size = ddi_get16(slotp->fib_acc_handle,
2040 2039 &slotp->fibp->Header.Size);
2041 2040
2042 2041 ASSERT(acp->fib_size <= softs->aac_max_fib_size);
2043 2042 ddi_rep_get8(slotp->fib_acc_handle, (uint8_t *)acp->fibp,
2044 2043 (uint8_t *)slotp->fibp, acp->fib_size, DDI_DEV_AUTOINCR);
2045 2044 }
2046 2045
2047 2046 /*
2048 2047 * Handle completed sync fib command
2049 2048 */
2050 2049 /*ARGSUSED*/
2051 2050 void
2052 2051 aac_sync_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2053 2052 {
2054 2053 }
2055 2054
2056 2055 /*
2057 2056 * Handle completed Flush command
2058 2057 */
2059 2058 /*ARGSUSED*/
2060 2059 static void
2061 2060 aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2062 2061 {
2063 2062 struct aac_slot *slotp = acp->slotp;
2064 2063 ddi_acc_handle_t acc = slotp->fib_acc_handle;
2065 2064 struct aac_synchronize_reply *resp;
2066 2065 uint32_t status;
2067 2066
2068 2067 ASSERT(!(acp->flags & AAC_CMD_SYNC));
2069 2068
2070 2069 acp->pkt->pkt_state |= STATE_GOT_STATUS;
2071 2070
2072 2071 resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0];
2073 2072 status = ddi_get32(acc, &resp->Status);
2074 2073 if (status != CT_OK)
2075 2074 aac_set_arq_data_hwerr(acp);
2076 2075 }
2077 2076
2078 2077 /*ARGSUSED*/
2079 2078 static void
2080 2079 aac_startstop_complete(struct aac_softstate *softs, struct aac_cmd *acp)
2081 2080 {
2082 2081 struct aac_slot *slotp = acp->slotp;
2083 2082 ddi_acc_handle_t acc = slotp->fib_acc_handle;
2084 2083 struct aac_Container_resp *resp;
2085 2084 uint32_t status;
2086 2085
2087 2086 ASSERT(!(acp->flags & AAC_CMD_SYNC));
2088 2087
2089 2088 acp->pkt->pkt_state |= STATE_GOT_STATUS;
2090 2089
2091 2090 resp = (struct aac_Container_resp *)&slotp->fibp->data[0];
2092 2091 status = ddi_get32(acc, &resp->Status);
2093 2092 if (status != 0) {
2094 2093 AACDB_PRINT(softs, CE_WARN, "Cannot start/stop a unit");
2095 2094 aac_set_arq_data_hwerr(acp);
2096 2095 }
2097 2096 }
2098 2097
2099 2098 /*
2100 2099 * Access PCI space to see if the driver can support the card
2101 2100 */
2102 2101 static int
2103 2102 aac_check_card_type(struct aac_softstate *softs)
2104 2103 {
2105 2104 ddi_acc_handle_t pci_config_handle;
2106 2105 int card_index;
2107 2106 uint32_t pci_cmd;
2108 2107
2109 2108 /* Map pci configuration space */
2110 2109 if ((pci_config_setup(softs->devinfo_p, &pci_config_handle)) !=
2111 2110 DDI_SUCCESS) {
2112 2111 AACDB_PRINT(softs, CE_WARN, "Cannot setup pci config space");
2113 2112 return (AACERR);
2114 2113 }
2115 2114
2116 2115 softs->vendid = pci_config_get16(pci_config_handle, PCI_CONF_VENID);
2117 2116 softs->devid = pci_config_get16(pci_config_handle, PCI_CONF_DEVID);
2118 2117 softs->subvendid = pci_config_get16(pci_config_handle,
2119 2118 PCI_CONF_SUBVENID);
2120 2119 softs->subsysid = pci_config_get16(pci_config_handle,
2121 2120 PCI_CONF_SUBSYSID);
2122 2121
2123 2122 card_index = 0;
2124 2123 while (!CARD_IS_UNKNOWN(card_index)) {
2125 2124 if ((aac_cards[card_index].vendor == softs->vendid) &&
2126 2125 (aac_cards[card_index].device == softs->devid) &&
2127 2126 (aac_cards[card_index].subvendor == softs->subvendid) &&
2128 2127 (aac_cards[card_index].subsys == softs->subsysid)) {
2129 2128 break;
2130 2129 }
2131 2130 card_index++;
2132 2131 }
2133 2132
2134 2133 softs->card = card_index;
2135 2134 softs->hwif = aac_cards[card_index].hwif;
2136 2135
2137 2136 /*
2138 2137 * Unknown aac card
2139 2138 * do a generic match based on the VendorID and DeviceID to
2140 2139 * support the new cards in the aac family
2141 2140 */
2142 2141 if (CARD_IS_UNKNOWN(card_index)) {
2143 2142 if (softs->vendid != 0x9005) {
2144 2143 AACDB_PRINT(softs, CE_WARN,
2145 2144 "Unknown vendor 0x%x", softs->vendid);
2146 2145 goto error;
2147 2146 }
2148 2147 switch (softs->devid) {
2149 2148 case 0x285:
2150 2149 softs->hwif = AAC_HWIF_I960RX;
2151 2150 break;
2152 2151 case 0x286:
2153 2152 softs->hwif = AAC_HWIF_RKT;
2154 2153 break;
2155 2154 default:
2156 2155 AACDB_PRINT(softs, CE_WARN,
2157 2156 "Unknown device \"pci9005,%x\"", softs->devid);
2158 2157 goto error;
2159 2158 }
2160 2159 }
2161 2160
2162 2161 /* Set hardware dependent interface */
2163 2162 switch (softs->hwif) {
2164 2163 case AAC_HWIF_I960RX:
2165 2164 softs->aac_if = aac_rx_interface;
2166 2165 softs->map_size_min = AAC_MAP_SIZE_MIN_RX;
2167 2166 break;
2168 2167 case AAC_HWIF_RKT:
2169 2168 softs->aac_if = aac_rkt_interface;
2170 2169 softs->map_size_min = AAC_MAP_SIZE_MIN_RKT;
2171 2170 break;
2172 2171 default:
2173 2172 AACDB_PRINT(softs, CE_WARN,
2174 2173 "Unknown hardware interface %d", softs->hwif);
2175 2174 goto error;
2176 2175 }
2177 2176
2178 2177 /* Set card names */
2179 2178 (void *)strncpy(softs->vendor_name, aac_cards[card_index].vid,
2180 2179 AAC_VENDOR_LEN);
2181 2180 (void *)strncpy(softs->product_name, aac_cards[card_index].desc,
2182 2181 AAC_PRODUCT_LEN);
2183 2182
2184 2183 /* Set up quirks */
2185 2184 softs->flags = aac_cards[card_index].quirks;
2186 2185
2187 2186 /* Force the busmaster enable bit on */
2188 2187 pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
2189 2188 if ((pci_cmd & PCI_COMM_ME) == 0) {
2190 2189 pci_cmd |= PCI_COMM_ME;
2191 2190 pci_config_put16(pci_config_handle, PCI_CONF_COMM, pci_cmd);
2192 2191 pci_cmd = pci_config_get16(pci_config_handle, PCI_CONF_COMM);
2193 2192 if ((pci_cmd & PCI_COMM_ME) == 0) {
2194 2193 cmn_err(CE_CONT, "?Cannot enable busmaster bit");
2195 2194 goto error;
2196 2195 }
2197 2196 }
2198 2197
2199 2198 /* Set memory base to map */
2200 2199 softs->pci_mem_base_paddr = 0xfffffff0UL & \
2201 2200 pci_config_get32(pci_config_handle, PCI_CONF_BASE0);
2202 2201
2203 2202 pci_config_teardown(&pci_config_handle);
2204 2203
2205 2204 return (AACOK); /* card type detected */
2206 2205 error:
2207 2206 pci_config_teardown(&pci_config_handle);
2208 2207 return (AACERR); /* no matched card found */
2209 2208 }
2210 2209
2211 2210 /*
2212 2211 * Do the usual interrupt handler setup stuff.
2213 2212 */
2214 2213 static int
2215 2214 aac_register_intrs(struct aac_softstate *softs)
2216 2215 {
2217 2216 dev_info_t *dip;
2218 2217 int intr_types;
2219 2218
2220 2219 ASSERT(softs->devinfo_p);
2221 2220 dip = softs->devinfo_p;
2222 2221
2223 2222 /* Get the type of device intrrupts */
2224 2223 if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
2225 2224 AACDB_PRINT(softs, CE_WARN,
2226 2225 "ddi_intr_get_supported_types() failed");
2227 2226 return (AACERR);
2228 2227 }
2229 2228 AACDB_PRINT(softs, CE_NOTE,
2230 2229 "ddi_intr_get_supported_types() ret: 0x%x", intr_types);
2231 2230
2232 2231 /* Query interrupt, and alloc/init all needed struct */
2233 2232 if (intr_types & DDI_INTR_TYPE_MSI) {
2234 2233 if (aac_query_intrs(softs, DDI_INTR_TYPE_MSI)
2235 2234 != DDI_SUCCESS) {
2236 2235 AACDB_PRINT(softs, CE_WARN,
2237 2236 "MSI interrupt query failed");
2238 2237 return (AACERR);
2239 2238 }
2240 2239 softs->intr_type = DDI_INTR_TYPE_MSI;
2241 2240 } else if (intr_types & DDI_INTR_TYPE_FIXED) {
2242 2241 if (aac_query_intrs(softs, DDI_INTR_TYPE_FIXED)
2243 2242 != DDI_SUCCESS) {
2244 2243 AACDB_PRINT(softs, CE_WARN,
2245 2244 "FIXED interrupt query failed");
2246 2245 return (AACERR);
2247 2246 }
2248 2247 softs->intr_type = DDI_INTR_TYPE_FIXED;
2249 2248 } else {
2250 2249 AACDB_PRINT(softs, CE_WARN,
2251 2250 "Device cannot suppport both FIXED and MSI interrupts");
2252 2251 return (AACERR);
2253 2252 }
2254 2253
2255 2254 /* Connect interrupt handlers */
2256 2255 if (aac_add_intrs(softs) != DDI_SUCCESS) {
2257 2256 AACDB_PRINT(softs, CE_WARN,
2258 2257 "Interrupt registration failed, intr type: %s",
2259 2258 softs->intr_type == DDI_INTR_TYPE_MSI ? "MSI" : "FIXED");
2260 2259 return (AACERR);
2261 2260 }
2262 2261 (void) aac_enable_intrs(softs);
2263 2262
2264 2263 if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id,
2265 2264 NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) {
2266 2265 AACDB_PRINT(softs, CE_WARN,
2267 2266 "Can not setup soft interrupt handler!");
2268 2267 aac_remove_intrs(softs);
2269 2268 return (AACERR);
2270 2269 }
2271 2270
2272 2271 return (AACOK);
2273 2272 }
2274 2273
2275 2274 static void
2276 2275 aac_unregister_intrs(struct aac_softstate *softs)
2277 2276 {
2278 2277 aac_remove_intrs(softs);
2279 2278 ddi_remove_softintr(softs->softint_id);
2280 2279 }
2281 2280
2282 2281 /*
2283 2282 * Check the firmware to determine the features to support and the FIB
2284 2283 * parameters to use.
2285 2284 */
2286 2285 static int
2287 2286 aac_check_firmware(struct aac_softstate *softs)
2288 2287 {
2289 2288 uint32_t options;
2290 2289 uint32_t atu_size;
2291 2290 ddi_acc_handle_t pci_handle;
2292 2291 uint8_t *data;
2293 2292 uint32_t max_fibs;
2294 2293 uint32_t max_fib_size;
2295 2294 uint32_t sg_tablesize;
2296 2295 uint32_t max_sectors;
2297 2296 uint32_t status;
2298 2297
2299 2298 /* Get supported options */
2300 2299 if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0,
2301 2300 &status)) != AACOK) {
2302 2301 if (status != SRB_STATUS_INVALID_REQUEST) {
2303 2302 cmn_err(CE_CONT,
2304 2303 "?Fatal error: request adapter info error");
2305 2304 return (AACERR);
2306 2305 }
2307 2306 options = 0;
2308 2307 atu_size = 0;
2309 2308 } else {
2310 2309 options = AAC_MAILBOX_GET(softs, 1);
2311 2310 atu_size = AAC_MAILBOX_GET(softs, 2);
2312 2311 }
2313 2312
2314 2313 if (softs->state & AAC_STATE_RESET) {
2315 2314 if ((softs->support_opt == options) &&
2316 2315 (softs->atu_size == atu_size))
2317 2316 return (AACOK);
2318 2317
2319 2318 cmn_err(CE_WARN,
2320 2319 "?Fatal error: firmware changed, system needs reboot");
2321 2320 return (AACERR);
2322 2321 }
2323 2322
2324 2323 /*
2325 2324 * The following critical settings are initialized only once during
2326 2325 * driver attachment.
2327 2326 */
2328 2327 softs->support_opt = options;
2329 2328 softs->atu_size = atu_size;
2330 2329
2331 2330 /* Process supported options */
2332 2331 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
2333 2332 (softs->flags & AAC_FLAGS_NO4GB) == 0) {
2334 2333 AACDB_PRINT(softs, CE_NOTE, "!Enable FIB map 4GB window");
2335 2334 softs->flags |= AAC_FLAGS_4GB_WINDOW;
2336 2335 } else {
2337 2336 /*
2338 2337 * Quirk AAC_FLAGS_NO4GB is for FIB address and thus comm space
2339 2338 * only. IO is handled by the DMA engine which does not suffer
2340 2339 * from the ATU window programming workarounds necessary for
2341 2340 * CPU copy operations.
2342 2341 */
2343 2342 softs->addr_dma_attr.dma_attr_addr_lo = 0x2000ull;
2344 2343 softs->addr_dma_attr.dma_attr_addr_hi = 0x7fffffffull;
2345 2344 }
2346 2345
2347 2346 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0) {
2348 2347 AACDB_PRINT(softs, CE_NOTE, "!Enable SG map 64-bit address");
2349 2348 softs->buf_dma_attr.dma_attr_addr_hi = 0xffffffffffffffffull;
2350 2349 softs->buf_dma_attr.dma_attr_seg = 0xffffffffffffffffull;
2351 2350 softs->flags |= AAC_FLAGS_SG_64BIT;
2352 2351 }
2353 2352
2354 2353 if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE) {
2355 2354 softs->flags |= AAC_FLAGS_ARRAY_64BIT;
2356 2355 AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size");
2357 2356 }
2358 2357
2359 2358 if (options & AAC_SUPPORTED_NONDASD) {
2360 2359 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 0,
2361 2360 "nondasd-enable", (char **)&data) == DDI_SUCCESS)) {
2362 2361 if (strcmp((char *)data, "yes") == 0) {
2363 2362 AACDB_PRINT(softs, CE_NOTE,
2364 2363 "!Enable Non-DASD access");
2365 2364 softs->flags |= AAC_FLAGS_NONDASD;
2366 2365 }
2367 2366 ddi_prop_free(data);
2368 2367 }
2369 2368 }
2370 2369
2371 2370 /* Read preferred settings */
2372 2371 max_fib_size = 0;
2373 2372 if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF,
2374 2373 0, 0, 0, 0, NULL)) == AACOK) {
2375 2374 options = AAC_MAILBOX_GET(softs, 1);
2376 2375 max_fib_size = (options & 0xffff);
2377 2376 max_sectors = (options >> 16) << 1;
2378 2377 options = AAC_MAILBOX_GET(softs, 2);
2379 2378 sg_tablesize = (options >> 16);
2380 2379 options = AAC_MAILBOX_GET(softs, 3);
2381 2380 max_fibs = (options & 0xffff);
2382 2381 }
2383 2382
2384 2383 /* Enable new comm. and rawio at the same time */
2385 2384 if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) &&
2386 2385 (max_fib_size != 0)) {
2387 2386 /* read out and save PCI MBR */
2388 2387 if ((atu_size > softs->map_size) &&
2389 2388 (ddi_regs_map_setup(softs->devinfo_p, 1,
2390 2389 (caddr_t *)&data, 0, atu_size, &softs->reg_attr,
2391 2390 &pci_handle) == DDI_SUCCESS)) {
2392 2391 ddi_regs_map_free(&softs->pci_mem_handle);
2393 2392 softs->pci_mem_handle = pci_handle;
2394 2393 softs->pci_mem_base_vaddr = data;
2395 2394 softs->map_size = atu_size;
2396 2395 }
2397 2396 if (atu_size == softs->map_size) {
2398 2397 softs->flags |= AAC_FLAGS_NEW_COMM;
2399 2398 AACDB_PRINT(softs, CE_NOTE,
2400 2399 "!Enable New Comm. interface");
2401 2400 }
2402 2401 }
2403 2402
2404 2403 /* Set FIB parameters */
2405 2404 if (softs->flags & AAC_FLAGS_NEW_COMM) {
2406 2405 softs->aac_max_fibs = max_fibs;
2407 2406 softs->aac_max_fib_size = max_fib_size;
2408 2407 softs->aac_max_sectors = max_sectors;
2409 2408 softs->aac_sg_tablesize = sg_tablesize;
2410 2409
2411 2410 softs->flags |= AAC_FLAGS_RAW_IO;
2412 2411 AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO");
2413 2412 } else {
2414 2413 softs->aac_max_fibs =
2415 2414 (softs->flags & AAC_FLAGS_256FIBS) ? 256 : 512;
2416 2415 softs->aac_max_fib_size = AAC_FIB_SIZE;
2417 2416 softs->aac_max_sectors = 128; /* 64K */
2418 2417 if (softs->flags & AAC_FLAGS_17SG)
2419 2418 softs->aac_sg_tablesize = 17;
2420 2419 else if (softs->flags & AAC_FLAGS_34SG)
2421 2420 softs->aac_sg_tablesize = 34;
2422 2421 else if (softs->flags & AAC_FLAGS_SG_64BIT)
2423 2422 softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
2424 2423 sizeof (struct aac_blockwrite64) +
2425 2424 sizeof (struct aac_sg_entry64)) /
2426 2425 sizeof (struct aac_sg_entry64);
2427 2426 else
2428 2427 softs->aac_sg_tablesize = (AAC_FIB_DATASIZE -
2429 2428 sizeof (struct aac_blockwrite) +
2430 2429 sizeof (struct aac_sg_entry)) /
2431 2430 sizeof (struct aac_sg_entry);
2432 2431 }
2433 2432
2434 2433 if ((softs->flags & AAC_FLAGS_RAW_IO) &&
2435 2434 (softs->flags & AAC_FLAGS_ARRAY_64BIT)) {
2436 2435 softs->flags |= AAC_FLAGS_LBA_64BIT;
2437 2436 AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array");
2438 2437 }
2439 2438 softs->buf_dma_attr.dma_attr_sgllen = softs->aac_sg_tablesize;
2440 2439 softs->buf_dma_attr.dma_attr_maxxfer = softs->aac_max_sectors << 9;
2441 2440 /*
2442 2441 * 64K maximum segment size in scatter gather list is controlled by
2443 2442 * the NEW_COMM bit in the adapter information. If not set, the card
2444 2443 * can only accept a maximum of 64K. It is not recommended to permit
2445 2444 * more than 128KB of total transfer size to the adapters because
2446 2445 * performance is negatively impacted.
2447 2446 *
2448 2447 * For new comm, segment size equals max xfer size. For old comm,
2449 2448 * we use 64K for both.
2450 2449 */
2451 2450 softs->buf_dma_attr.dma_attr_count_max =
2452 2451 softs->buf_dma_attr.dma_attr_maxxfer - 1;
2453 2452
2454 2453 /* Setup FIB operations */
2455 2454 if (softs->flags & AAC_FLAGS_RAW_IO)
2456 2455 softs->aac_cmd_fib = aac_cmd_fib_rawio;
2457 2456 else if (softs->flags & AAC_FLAGS_SG_64BIT)
2458 2457 softs->aac_cmd_fib = aac_cmd_fib_brw64;
2459 2458 else
2460 2459 softs->aac_cmd_fib = aac_cmd_fib_brw;
2461 2460 softs->aac_cmd_fib_scsi = (softs->flags & AAC_FLAGS_SG_64BIT) ? \
2462 2461 aac_cmd_fib_scsi64 : aac_cmd_fib_scsi32;
2463 2462
2464 2463 /* 64-bit LBA needs descriptor format sense data */
2465 2464 softs->slen = sizeof (struct scsi_arq_status);
2466 2465 if ((softs->flags & AAC_FLAGS_LBA_64BIT) &&
2467 2466 softs->slen < AAC_ARQ64_LENGTH)
2468 2467 softs->slen = AAC_ARQ64_LENGTH;
2469 2468
2470 2469 AACDB_PRINT(softs, CE_NOTE,
2471 2470 "!max_fibs %d max_fibsize 0x%x max_sectors %d max_sg %d",
2472 2471 softs->aac_max_fibs, softs->aac_max_fib_size,
2473 2472 softs->aac_max_sectors, softs->aac_sg_tablesize);
2474 2473
2475 2474 return (AACOK);
2476 2475 }
2477 2476
2478 2477 static void
2479 2478 aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0,
2480 2479 struct FsaRev *fsarev1)
2481 2480 {
2482 2481 ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
2483 2482
2484 2483 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash);
2485 2484 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type);
2486 2485 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor);
2487 2486 AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major);
2488 2487 AAC_GET_FIELD32(acc, fsarev1, fsarev0, buildNumber);
2489 2488 }
2490 2489
2491 2490 /*
2492 2491 * The following function comes from Adaptec:
2493 2492 *
2494 2493 * Query adapter information and supplement adapter information
2495 2494 */
2496 2495 static int
2497 2496 aac_get_adapter_info(struct aac_softstate *softs,
2498 2497 struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr)
2499 2498 {
2500 2499 struct aac_cmd *acp = &softs->sync_ac;
2501 2500 ddi_acc_handle_t acc;
2502 2501 struct aac_fib *fibp;
2503 2502 struct aac_adapter_info *ainfp;
2504 2503 struct aac_supplement_adapter_info *sinfp;
2505 2504 int rval;
2506 2505
2507 2506 (void) aac_sync_fib_slot_bind(softs, acp);
2508 2507 acc = acp->slotp->fib_acc_handle;
2509 2508 fibp = acp->slotp->fibp;
2510 2509
2511 2510 ddi_put8(acc, &fibp->data[0], 0);
2512 2511 if (aac_sync_fib(softs, RequestAdapterInfo,
2513 2512 AAC_FIB_SIZEOF(struct aac_adapter_info)) != AACOK) {
2514 2513 AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed");
2515 2514 rval = AACERR;
2516 2515 goto finish;
2517 2516 }
2518 2517 ainfp = (struct aac_adapter_info *)fibp->data;
2519 2518 if (ainfr) {
2520 2519 AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
2521 2520 AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase);
2522 2521 AAC_GET_FIELD32(acc, ainfr, ainfp, CpuArchitecture);
2523 2522 AAC_GET_FIELD32(acc, ainfr, ainfp, CpuVariant);
2524 2523 AAC_GET_FIELD32(acc, ainfr, ainfp, ClockSpeed);
2525 2524 AAC_GET_FIELD32(acc, ainfr, ainfp, ExecutionMem);
2526 2525 AAC_GET_FIELD32(acc, ainfr, ainfp, BufferMem);
2527 2526 AAC_GET_FIELD32(acc, ainfr, ainfp, TotalMem);
2528 2527 aac_fsa_rev(softs, &ainfp->KernelRevision,
2529 2528 &ainfr->KernelRevision);
2530 2529 aac_fsa_rev(softs, &ainfp->MonitorRevision,
2531 2530 &ainfr->MonitorRevision);
2532 2531 aac_fsa_rev(softs, &ainfp->HardwareRevision,
2533 2532 &ainfr->HardwareRevision);
2534 2533 aac_fsa_rev(softs, &ainfp->BIOSRevision,
2535 2534 &ainfr->BIOSRevision);
2536 2535 AAC_GET_FIELD32(acc, ainfr, ainfp, ClusteringEnabled);
2537 2536 AAC_GET_FIELD32(acc, ainfr, ainfp, ClusterChannelMask);
2538 2537 AAC_GET_FIELD64(acc, ainfr, ainfp, SerialNumber);
2539 2538 AAC_GET_FIELD32(acc, ainfr, ainfp, batteryPlatform);
2540 2539 AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions);
2541 2540 AAC_GET_FIELD32(acc, ainfr, ainfp, OemVariant);
2542 2541 }
2543 2542 if (sinfr) {
2544 2543 if (!(softs->support_opt &
2545 2544 AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) {
2546 2545 AACDB_PRINT(softs, CE_WARN,
2547 2546 "SupplementAdapterInfo not supported");
2548 2547 rval = AACERR;
2549 2548 goto finish;
2550 2549 }
2551 2550 ddi_put8(acc, &fibp->data[0], 0);
2552 2551 if (aac_sync_fib(softs, RequestSupplementAdapterInfo,
2553 2552 AAC_FIB_SIZEOF(struct aac_supplement_adapter_info))
2554 2553 != AACOK) {
2555 2554 AACDB_PRINT(softs, CE_WARN,
2556 2555 "RequestSupplementAdapterInfo failed");
2557 2556 rval = AACERR;
2558 2557 goto finish;
2559 2558 }
2560 2559 sinfp = (struct aac_supplement_adapter_info *)fibp->data;
2561 2560 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1);
2562 2561 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2);
2563 2562 AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize);
2564 2563 AAC_GET_FIELD32(acc, sinfr, sinfp, FlashImageId);
2565 2564 AAC_GET_FIELD32(acc, sinfr, sinfp, MaxNumberPorts);
2566 2565 AAC_GET_FIELD32(acc, sinfr, sinfp, Version);
2567 2566 AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits);
2568 2567 AAC_GET_FIELD8(acc, sinfr, sinfp, SlotNumber);
2569 2568 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, ReservedPad0[0], 3);
2570 2569 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, BuildDate[0], 12);
2571 2570 AAC_GET_FIELD32(acc, sinfr, sinfp, CurrentNumberPorts);
2572 2571 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, VpdInfo,
2573 2572 sizeof (struct vpd_info));
2574 2573 aac_fsa_rev(softs, &sinfp->FlashFirmwareRevision,
2575 2574 &sinfr->FlashFirmwareRevision);
2576 2575 AAC_GET_FIELD32(acc, sinfr, sinfp, RaidTypeMorphOptions);
2577 2576 aac_fsa_rev(softs, &sinfp->FlashFirmwareBootRevision,
2578 2577 &sinfr->FlashFirmwareBootRevision);
2579 2578 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgPcbaSerialNo,
2580 2579 MFG_PCBA_SERIAL_NUMBER_WIDTH);
2581 2580 AAC_REP_GET_FIELD8(acc, sinfr, sinfp, MfgWWNName[0],
2582 2581 MFG_WWN_WIDTH);
2583 2582 AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedOptions2);
2584 2583 AAC_GET_FIELD32(acc, sinfr, sinfp, ExpansionFlag);
2585 2584 if (sinfr->ExpansionFlag == 1) {
2586 2585 AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits3);
2587 2586 AAC_GET_FIELD32(acc, sinfr, sinfp,
2588 2587 SupportedPerformanceMode);
2589 2588 AAC_REP_GET_FIELD32(acc, sinfr, sinfp,
2590 2589 ReservedGrowth[0], 80);
2591 2590 }
2592 2591 }
2593 2592 rval = AACOK;
2594 2593 finish:
2595 2594 aac_sync_fib_slot_release(softs, acp);
2596 2595 return (rval);
2597 2596 }
2598 2597
2599 2598 static int
2600 2599 aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max,
2601 2600 uint32_t *tgt_max)
2602 2601 {
2603 2602 struct aac_cmd *acp = &softs->sync_ac;
2604 2603 ddi_acc_handle_t acc;
2605 2604 struct aac_fib *fibp;
2606 2605 struct aac_ctcfg *c_cmd;
2607 2606 struct aac_ctcfg_resp *c_resp;
2608 2607 uint32_t scsi_method_id;
2609 2608 struct aac_bus_info *cmd;
2610 2609 struct aac_bus_info_response *resp;
2611 2610 int rval;
2612 2611
2613 2612 (void) aac_sync_fib_slot_bind(softs, acp);
2614 2613 acc = acp->slotp->fib_acc_handle;
2615 2614 fibp = acp->slotp->fibp;
2616 2615
2617 2616 /* Detect MethodId */
2618 2617 c_cmd = (struct aac_ctcfg *)&fibp->data[0];
2619 2618 ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig);
2620 2619 ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD);
2621 2620 ddi_put32(acc, &c_cmd->param, 0);
2622 2621 rval = aac_sync_fib(softs, ContainerCommand,
2623 2622 AAC_FIB_SIZEOF(struct aac_ctcfg));
2624 2623 c_resp = (struct aac_ctcfg_resp *)&fibp->data[0];
2625 2624 if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) {
2626 2625 AACDB_PRINT(softs, CE_WARN,
2627 2626 "VM_ContainerConfig command fail");
2628 2627 rval = AACERR;
2629 2628 goto finish;
2630 2629 }
2631 2630 scsi_method_id = ddi_get32(acc, &c_resp->param);
2632 2631
2633 2632 /* Detect phys. bus count and max. target id first */
2634 2633 cmd = (struct aac_bus_info *)&fibp->data[0];
2635 2634 ddi_put32(acc, &cmd->Command, VM_Ioctl);
2636 2635 ddi_put32(acc, &cmd->ObjType, FT_DRIVE); /* physical drive */
2637 2636 ddi_put32(acc, &cmd->MethodId, scsi_method_id);
2638 2637 ddi_put32(acc, &cmd->ObjectId, 0);
2639 2638 ddi_put32(acc, &cmd->CtlCmd, GetBusInfo);
2640 2639 /*
2641 2640 * For VM_Ioctl, the firmware uses the Header.Size filled from the
2642 2641 * driver as the size to be returned. Therefore the driver has to use
2643 2642 * sizeof (struct aac_bus_info_response) because it is greater than
2644 2643 * sizeof (struct aac_bus_info).
2645 2644 */
2646 2645 rval = aac_sync_fib(softs, ContainerCommand,
2647 2646 AAC_FIB_SIZEOF(struct aac_bus_info_response));
2648 2647 resp = (struct aac_bus_info_response *)cmd;
2649 2648
2650 2649 /* Scan all coordinates with INQUIRY */
2651 2650 if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) {
2652 2651 AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail");
2653 2652 rval = AACERR;
2654 2653 goto finish;
2655 2654 }
2656 2655 *bus_max = ddi_get32(acc, &resp->BusCount);
2657 2656 *tgt_max = ddi_get32(acc, &resp->TargetsPerBus);
2658 2657
2659 2658 finish:
2660 2659 aac_sync_fib_slot_release(softs, acp);
2661 2660 return (AACOK);
2662 2661 }
2663 2662
2664 2663 /*
2665 2664 * The following function comes from Adaptec:
2666 2665 *
2667 2666 * Routine to be called during initialization of communications with
2668 2667 * the adapter to handle possible adapter configuration issues. When
2669 2668 * the adapter first boots up, it examines attached drives, etc, and
2670 2669 * potentially comes up with a new or revised configuration (relative to
2671 2670 * what's stored in it's NVRAM). Additionally it may discover problems
2672 2671 * that make the current physical configuration unworkable (currently
2673 2672 * applicable only to cluster configuration issues).
2674 2673 *
2675 2674 * If there are no configuration issues or the issues are considered
2676 2675 * trival by the adapter, it will set it's configuration status to
2677 2676 * "FSACT_CONTINUE" and execute the "commit confiuguration" action
2678 2677 * automatically on it's own.
2679 2678 *
2680 2679 * However, if there are non-trivial issues, the adapter will set it's
2681 2680 * internal configuration status to "FSACT_PAUSE" or "FASCT_ABORT"
2682 2681 * and wait for some agent on the host to issue the "\ContainerCommand
2683 2682 * \VM_ContainerConfig\CT_COMMIT_CONFIG" FIB command to cause the
2684 2683 * adapter to commit the new/updated configuration and enable
2685 2684 * un-inhibited operation. The host agent should first issue the
2686 2685 * "\ContainerCommand\VM_ContainerConfig\CT_GET_CONFIG_STATUS" FIB
2687 2686 * command to obtain information about config issues detected by
2688 2687 * the adapter.
2689 2688 *
2690 2689 * Normally the adapter's PC BIOS will execute on the host following
2691 2690 * adapter poweron and reset and will be responsible for querring the
2692 2691 * adapter with CT_GET_CONFIG_STATUS and issuing the CT_COMMIT_CONFIG
2693 2692 * command if appropriate.
2694 2693 *
2695 2694 * However, with the introduction of IOP reset support, the adapter may
2696 2695 * boot up without the benefit of the adapter's PC BIOS host agent.
2697 2696 * This routine is intended to take care of these issues in situations
2698 2697 * where BIOS doesn't execute following adapter poweron or reset. The
2699 2698 * CT_COMMIT_CONFIG command is a no-op if it's already been issued, so
2700 2699 * there is no harm in doing this when it's already been done.
2701 2700 */
2702 2701 static int
2703 2702 aac_handle_adapter_config_issues(struct aac_softstate *softs)
2704 2703 {
2705 2704 struct aac_cmd *acp = &softs->sync_ac;
2706 2705 ddi_acc_handle_t acc;
2707 2706 struct aac_fib *fibp;
2708 2707 struct aac_Container *cmd;
2709 2708 struct aac_Container_resp *resp;
2710 2709 struct aac_cf_status_header *cfg_sts_hdr;
2711 2710 uint32_t resp_status;
2712 2711 uint32_t ct_status;
2713 2712 uint32_t cfg_stat_action;
2714 2713 int rval;
2715 2714
2716 2715 (void) aac_sync_fib_slot_bind(softs, acp);
2717 2716 acc = acp->slotp->fib_acc_handle;
2718 2717 fibp = acp->slotp->fibp;
2719 2718
2720 2719 /* Get adapter config status */
2721 2720 cmd = (struct aac_Container *)&fibp->data[0];
2722 2721
2723 2722 bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2724 2723 ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2725 2724 ddi_put32(acc, &cmd->CTCommand.command, CT_GET_CONFIG_STATUS);
2726 2725 ddi_put32(acc, &cmd->CTCommand.param[CNT_SIZE],
2727 2726 sizeof (struct aac_cf_status_header));
2728 2727 rval = aac_sync_fib(softs, ContainerCommand,
2729 2728 AAC_FIB_SIZEOF(struct aac_Container));
2730 2729 resp = (struct aac_Container_resp *)cmd;
2731 2730 cfg_sts_hdr = (struct aac_cf_status_header *)resp->CTResponse.data;
2732 2731
2733 2732 resp_status = ddi_get32(acc, &resp->Status);
2734 2733 ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2735 2734 if ((rval == AACOK) && (resp_status == 0) && (ct_status == CT_OK)) {
2736 2735 cfg_stat_action = ddi_get32(acc, &cfg_sts_hdr->action);
2737 2736
2738 2737 /* Commit configuration if it's reasonable to do so. */
2739 2738 if (cfg_stat_action <= CFACT_PAUSE) {
2740 2739 bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
2741 2740 ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
2742 2741 ddi_put32(acc, &cmd->CTCommand.command,
2743 2742 CT_COMMIT_CONFIG);
2744 2743 rval = aac_sync_fib(softs, ContainerCommand,
2745 2744 AAC_FIB_SIZEOF(struct aac_Container));
2746 2745
2747 2746 resp_status = ddi_get32(acc, &resp->Status);
2748 2747 ct_status = ddi_get32(acc, &resp->CTResponse.param[0]);
2749 2748 if ((rval == AACOK) && (resp_status == 0) &&
2750 2749 (ct_status == CT_OK))
2751 2750 /* Successful completion */
2752 2751 rval = AACMPE_OK;
2753 2752 else
2754 2753 /* Auto-commit aborted due to error(s). */
2755 2754 rval = AACMPE_COMMIT_CONFIG;
2756 2755 } else {
2757 2756 /*
2758 2757 * Auto-commit aborted due to adapter indicating
2759 2758 * configuration issue(s) too dangerous to auto-commit.
2760 2759 */
2761 2760 rval = AACMPE_CONFIG_STATUS;
2762 2761 }
2763 2762 } else {
2764 2763 cmn_err(CE_WARN, "!Configuration issue, auto-commit aborted");
2765 2764 rval = AACMPE_CONFIG_STATUS;
2766 2765 }
2767 2766
2768 2767 aac_sync_fib_slot_release(softs, acp);
2769 2768 return (rval);
2770 2769 }
2771 2770
2772 2771 /*
2773 2772 * Hardware initialization and resource allocation
2774 2773 */
2775 2774 static int
2776 2775 aac_common_attach(struct aac_softstate *softs)
2777 2776 {
2778 2777 uint32_t status;
2779 2778 int i;
2780 2779 struct aac_supplement_adapter_info sinf;
2781 2780
2782 2781 DBCALLED(softs, 1);
2783 2782
2784 2783 /*
2785 2784 * Do a little check here to make sure there aren't any outstanding
2786 2785 * FIBs in the message queue. At this point there should not be and
2787 2786 * if there are they are probably left over from another instance of
2788 2787 * the driver like when the system crashes and the crash dump driver
2789 2788 * gets loaded.
2790 2789 */
2791 2790 while (AAC_OUTB_GET(softs) != 0xfffffffful)
2792 2791 ;
2793 2792
2794 2793 /*
2795 2794 * Wait the card to complete booting up before do anything that
2796 2795 * attempts to communicate with it.
2797 2796 */
2798 2797 status = AAC_FWSTATUS_GET(softs);
2799 2798 if (status == AAC_SELF_TEST_FAILED || status == AAC_KERNEL_PANIC)
2800 2799 goto error;
2801 2800 i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */
2802 2801 AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i);
2803 2802 if (i == 0) {
2804 2803 cmn_err(CE_CONT, "?Fatal error: controller not ready");
2805 2804 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2806 2805 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2807 2806 goto error;
2808 2807 }
2809 2808
2810 2809 /* Read and set card supported options and settings */
2811 2810 if (aac_check_firmware(softs) == AACERR) {
2812 2811 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2813 2812 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2814 2813 goto error;
2815 2814 }
2816 2815
2817 2816 /* Add interrupt handlers */
2818 2817 if (aac_register_intrs(softs) == AACERR) {
2819 2818 cmn_err(CE_CONT,
2820 2819 "?Fatal error: interrupts register failed");
2821 2820 goto error;
2822 2821 }
2823 2822
2824 2823 /* Setup communication space with the card */
2825 2824 if (softs->comm_space_dma_handle == NULL) {
2826 2825 if (aac_alloc_comm_space(softs) != AACOK)
2827 2826 goto error;
2828 2827 }
2829 2828 if (aac_setup_comm_space(softs) != AACOK) {
2830 2829 cmn_err(CE_CONT, "?Setup communication space failed");
2831 2830 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2832 2831 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2833 2832 goto error;
2834 2833 }
2835 2834
2836 2835 #ifdef DEBUG
2837 2836 if (aac_get_fw_debug_buffer(softs) != AACOK)
2838 2837 cmn_err(CE_CONT, "?firmware UART trace not supported");
2839 2838 #endif
2840 2839
2841 2840 /* Allocate slots */
2842 2841 if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) {
2843 2842 cmn_err(CE_CONT, "?Fatal error: slots allocate failed");
2844 2843 goto error;
2845 2844 }
2846 2845 AACDB_PRINT(softs, CE_NOTE, "%d slots allocated", softs->total_slots);
2847 2846
2848 2847 /* Allocate FIBs */
2849 2848 if (softs->total_fibs < softs->total_slots) {
2850 2849 aac_alloc_fibs(softs);
2851 2850 if (softs->total_fibs == 0)
2852 2851 goto error;
2853 2852 AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated",
2854 2853 softs->total_fibs);
2855 2854 }
2856 2855
2857 2856 AAC_STATUS_CLR(softs, ~0); /* Clear out all interrupts */
2858 2857 AAC_ENABLE_INTR(softs); /* Enable the interrupts we can handle */
2859 2858
2860 2859 if (aac_get_adapter_info(softs, NULL, &sinf) == AACOK) {
2861 2860 softs->feature_bits = sinf.FeatureBits;
2862 2861 softs->support_opt2 = sinf.SupportedOptions2;
2863 2862
2864 2863 /* Get adapter names */
2865 2864 if (CARD_IS_UNKNOWN(softs->card)) {
2866 2865 char *p, *p0, *p1;
2867 2866
2868 2867 /*
2869 2868 * Now find the controller name in supp_adapter_info->
2870 2869 * AdapterTypeText. Use the first word as the vendor
2871 2870 * and the other words as the product name.
2872 2871 */
2873 2872 AACDB_PRINT(softs, CE_NOTE, "sinf.AdapterTypeText = "
2874 2873 "\"%s\"", sinf.AdapterTypeText);
2875 2874 p = sinf.AdapterTypeText;
2876 2875 p0 = p1 = NULL;
2877 2876 /* Skip heading spaces */
2878 2877 while (*p && (*p == ' ' || *p == '\t'))
2879 2878 p++;
2880 2879 p0 = p;
2881 2880 while (*p && (*p != ' ' && *p != '\t'))
2882 2881 p++;
2883 2882 /* Remove middle spaces */
2884 2883 while (*p && (*p == ' ' || *p == '\t'))
2885 2884 *p++ = 0;
2886 2885 p1 = p;
2887 2886 /* Remove trailing spaces */
2888 2887 p = p1 + strlen(p1) - 1;
2889 2888 while (p > p1 && (*p == ' ' || *p == '\t'))
2890 2889 *p-- = 0;
2891 2890 if (*p0 && *p1) {
2892 2891 (void *)strncpy(softs->vendor_name, p0,
2893 2892 AAC_VENDOR_LEN);
2894 2893 (void *)strncpy(softs->product_name, p1,
2895 2894 AAC_PRODUCT_LEN);
2896 2895 } else {
2897 2896 cmn_err(CE_WARN,
2898 2897 "?adapter name mis-formatted\n");
2899 2898 if (*p0)
2900 2899 (void *)strncpy(softs->product_name,
2901 2900 p0, AAC_PRODUCT_LEN);
2902 2901 }
2903 2902 }
2904 2903 } else {
2905 2904 cmn_err(CE_CONT, "?Query adapter information failed");
2906 2905 }
2907 2906
2908 2907
2909 2908 cmn_err(CE_NOTE,
2910 2909 "!aac driver %d.%02d.%02d-%d, found card: " \
2911 2910 "%s %s(pci0x%x.%x.%x.%x) at 0x%x",
2912 2911 AAC_DRIVER_MAJOR_VERSION,
2913 2912 AAC_DRIVER_MINOR_VERSION,
2914 2913 AAC_DRIVER_BUGFIX_LEVEL,
2915 2914 AAC_DRIVER_BUILD,
2916 2915 softs->vendor_name, softs->product_name,
2917 2916 softs->vendid, softs->devid, softs->subvendid, softs->subsysid,
2918 2917 softs->pci_mem_base_paddr);
2919 2918
2920 2919 /* Perform acceptance of adapter-detected config changes if possible */
2921 2920 if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) {
2922 2921 cmn_err(CE_CONT, "?Handle adapter config issues failed");
2923 2922 aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE);
2924 2923 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2925 2924 goto error;
2926 2925 }
2927 2926
2928 2927 /* Setup containers (logical devices) */
2929 2928 if (aac_probe_containers(softs) != AACOK) {
2930 2929 cmn_err(CE_CONT, "?Fatal error: get container info error");
2931 2930 goto error;
2932 2931 }
2933 2932
2934 2933 /* Check for JBOD support. Default disable */
2935 2934 char *data;
2936 2935 if (softs->feature_bits & AAC_FEATURE_SUPPORTED_JBOD) {
2937 2936 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p,
2938 2937 0, "jbod-enable", &data) == DDI_SUCCESS)) {
2939 2938 if (strcmp(data, "yes") == 0) {
2940 2939 AACDB_PRINT(softs, CE_NOTE,
2941 2940 "Enable JBOD access");
2942 2941 softs->flags |= AAC_FLAGS_JBOD;
2943 2942 }
2944 2943 ddi_prop_free(data);
2945 2944 }
2946 2945 }
2947 2946
2948 2947 /* Setup phys. devices */
2949 2948 if (softs->flags & (AAC_FLAGS_NONDASD | AAC_FLAGS_JBOD)) {
2950 2949 uint32_t bus_max, tgt_max;
2951 2950 uint32_t bus, tgt;
2952 2951 int index;
2953 2952
2954 2953 if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) {
2955 2954 cmn_err(CE_CONT, "?Fatal error: get bus info error");
2956 2955 goto error;
2957 2956 }
2958 2957 AACDB_PRINT(softs, CE_NOTE, "bus_max=%d, tgt_max=%d",
2959 2958 bus_max, tgt_max);
2960 2959 if (bus_max != softs->bus_max || tgt_max != softs->tgt_max) {
2961 2960 if (softs->state & AAC_STATE_RESET) {
2962 2961 cmn_err(CE_WARN,
2963 2962 "?Fatal error: bus map changed");
2964 2963 goto error;
2965 2964 }
2966 2965 softs->bus_max = bus_max;
2967 2966 softs->tgt_max = tgt_max;
2968 2967 if (softs->nondasds) {
2969 2968 kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
2970 2969 sizeof (struct aac_nondasd));
2971 2970 }
2972 2971 softs->nondasds = kmem_zalloc(AAC_MAX_PD(softs) * \
2973 2972 sizeof (struct aac_nondasd), KM_SLEEP);
2974 2973
2975 2974 index = 0;
2976 2975 for (bus = 0; bus < softs->bus_max; bus++) {
2977 2976 for (tgt = 0; tgt < softs->tgt_max; tgt++) {
2978 2977 struct aac_nondasd *dvp =
2979 2978 &softs->nondasds[index++];
2980 2979 dvp->dev.type = AAC_DEV_PD;
2981 2980 dvp->bus = bus;
2982 2981 dvp->tid = tgt;
2983 2982 }
2984 2983 }
2985 2984 }
2986 2985 }
2987 2986
2988 2987 /* Check dma & acc handles allocated in attach */
2989 2988 if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) {
2990 2989 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2991 2990 goto error;
2992 2991 }
2993 2992
2994 2993 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
2995 2994 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
2996 2995 goto error;
2997 2996 }
2998 2997
2999 2998 for (i = 0; i < softs->total_slots; i++) {
3000 2999 if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) !=
3001 3000 DDI_SUCCESS) {
3002 3001 ddi_fm_service_impact(softs->devinfo_p,
3003 3002 DDI_SERVICE_LOST);
3004 3003 goto error;
3005 3004 }
3006 3005 }
3007 3006
3008 3007 return (AACOK);
3009 3008 error:
3010 3009 if (softs->state & AAC_STATE_RESET)
3011 3010 return (AACERR);
3012 3011 if (softs->nondasds) {
3013 3012 kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
3014 3013 sizeof (struct aac_nondasd));
3015 3014 softs->nondasds = NULL;
3016 3015 }
3017 3016 if (softs->total_fibs > 0)
3018 3017 aac_destroy_fibs(softs);
3019 3018 if (softs->total_slots > 0)
3020 3019 aac_destroy_slots(softs);
3021 3020 if (softs->comm_space_dma_handle)
3022 3021 aac_free_comm_space(softs);
3023 3022 return (AACERR);
3024 3023 }
3025 3024
3026 3025 /*
3027 3026 * Hardware shutdown and resource release
3028 3027 */
3029 3028 static void
3030 3029 aac_common_detach(struct aac_softstate *softs)
3031 3030 {
3032 3031 DBCALLED(softs, 1);
3033 3032
3034 3033 aac_unregister_intrs(softs);
3035 3034
3036 3035 mutex_enter(&softs->io_lock);
3037 3036 (void) aac_shutdown(softs);
3038 3037
3039 3038 if (softs->nondasds) {
3040 3039 kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \
3041 3040 sizeof (struct aac_nondasd));
3042 3041 softs->nondasds = NULL;
3043 3042 }
3044 3043 aac_destroy_fibs(softs);
3045 3044 aac_destroy_slots(softs);
3046 3045 aac_free_comm_space(softs);
3047 3046 mutex_exit(&softs->io_lock);
3048 3047 }
3049 3048
3050 3049 /*
3051 3050 * Send a synchronous command to the controller and wait for a result.
3052 3051 * Indicate if the controller completed the command with an error status.
3053 3052 */
3054 3053 int
3055 3054 aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd,
3056 3055 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3,
3057 3056 uint32_t *statusp)
3058 3057 {
3059 3058 int timeout;
3060 3059 uint32_t status;
3061 3060
3062 3061 if (statusp != NULL)
3063 3062 *statusp = SRB_STATUS_SUCCESS;
3064 3063
3065 3064 /* Fill in mailbox */
3066 3065 AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3);
3067 3066
3068 3067 /* Ensure the sync command doorbell flag is cleared */
3069 3068 AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
3070 3069
3071 3070 /* Then set it to signal the adapter */
3072 3071 AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND);
3073 3072
3074 3073 /* Spin waiting for the command to complete */
3075 3074 timeout = AAC_IMMEDIATE_TIMEOUT * 1000;
3076 3075 AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout);
3077 3076 if (!timeout) {
3078 3077 AACDB_PRINT(softs, CE_WARN,
3079 3078 "Sync command timed out after %d seconds (0x%x)!",
3080 3079 AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs));
3081 3080 return (AACERR);
3082 3081 }
3083 3082
3084 3083 /* Clear the completion flag */
3085 3084 AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
3086 3085
3087 3086 /* Get the command status */
3088 3087 status = AAC_MAILBOX_GET(softs, 0);
3089 3088 if (statusp != NULL)
3090 3089 *statusp = status;
3091 3090 if (status != SRB_STATUS_SUCCESS) {
3092 3091 AACDB_PRINT(softs, CE_WARN,
3093 3092 "Sync command fail: status = 0x%x", status);
3094 3093 return (AACERR);
3095 3094 }
3096 3095
3097 3096 return (AACOK);
3098 3097 }
3099 3098
3100 3099 /*
3101 3100 * Send a synchronous FIB to the adapter and wait for its completion
3102 3101 */
3103 3102 static int
3104 3103 aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize)
3105 3104 {
3106 3105 struct aac_cmd *acp = &softs->sync_ac;
3107 3106
3108 3107 acp->flags = AAC_CMD_SYNC | AAC_CMD_IN_SYNC_SLOT;
3109 3108 if (softs->state & AAC_STATE_INTR)
3110 3109 acp->flags |= AAC_CMD_NO_CB;
3111 3110 else
3112 3111 acp->flags |= AAC_CMD_NO_INTR;
3113 3112
3114 3113 acp->ac_comp = aac_sync_complete;
3115 3114 acp->timeout = AAC_SYNC_TIMEOUT;
3116 3115 acp->fib_size = fibsize;
3117 3116
3118 3117 /*
3119 3118 * Only need to setup sync fib header, caller should have init
3120 3119 * fib data
3121 3120 */
3122 3121 aac_cmd_fib_header(softs, acp, cmd);
3123 3122
3124 3123 (void) ddi_dma_sync(acp->slotp->fib_dma_handle, 0, fibsize,
3125 3124 DDI_DMA_SYNC_FORDEV);
3126 3125
3127 3126 aac_start_io(softs, acp);
3128 3127
3129 3128 if (softs->state & AAC_STATE_INTR)
3130 3129 return (aac_do_sync_io(softs, acp));
3131 3130 else
3132 3131 return (aac_do_poll_io(softs, acp));
3133 3132 }
3134 3133
3135 3134 static void
3136 3135 aac_cmd_initq(struct aac_cmd_queue *q)
3137 3136 {
3138 3137 q->q_head = NULL;
3139 3138 q->q_tail = (struct aac_cmd *)&q->q_head;
3140 3139 }
3141 3140
3142 3141 /*
3143 3142 * Remove a cmd from the head of q
3144 3143 */
3145 3144 static struct aac_cmd *
3146 3145 aac_cmd_dequeue(struct aac_cmd_queue *q)
3147 3146 {
3148 3147 struct aac_cmd *acp;
3149 3148
3150 3149 _NOTE(ASSUMING_PROTECTED(*q))
3151 3150
3152 3151 if ((acp = q->q_head) != NULL) {
3153 3152 if ((q->q_head = acp->next) != NULL)
3154 3153 acp->next = NULL;
3155 3154 else
3156 3155 q->q_tail = (struct aac_cmd *)&q->q_head;
3157 3156 acp->prev = NULL;
3158 3157 }
3159 3158 return (acp);
3160 3159 }
3161 3160
3162 3161 /*
3163 3162 * Add a cmd to the tail of q
3164 3163 */
3165 3164 static void
3166 3165 aac_cmd_enqueue(struct aac_cmd_queue *q, struct aac_cmd *acp)
3167 3166 {
3168 3167 ASSERT(acp->next == NULL);
3169 3168 acp->prev = q->q_tail;
3170 3169 q->q_tail->next = acp;
3171 3170 q->q_tail = acp;
3172 3171 }
3173 3172
3174 3173 /*
3175 3174 * Remove the cmd ac from q
3176 3175 */
3177 3176 static void
3178 3177 aac_cmd_delete(struct aac_cmd_queue *q, struct aac_cmd *acp)
3179 3178 {
3180 3179 if (acp->prev) {
3181 3180 if ((acp->prev->next = acp->next) != NULL) {
3182 3181 acp->next->prev = acp->prev;
3183 3182 acp->next = NULL;
3184 3183 } else {
3185 3184 q->q_tail = acp->prev;
3186 3185 }
3187 3186 acp->prev = NULL;
3188 3187 }
3189 3188 /* ac is not in the queue */
3190 3189 }
3191 3190
3192 3191 /*
3193 3192 * Atomically insert an entry into the nominated queue, returns 0 on success or
3194 3193 * AACERR if the queue is full.
3195 3194 *
3196 3195 * Note: it would be more efficient to defer notifying the controller in
3197 3196 * the case where we may be inserting several entries in rapid succession,
3198 3197 * but implementing this usefully may be difficult (it would involve a
3199 3198 * separate queue/notify interface).
3200 3199 */
3201 3200 static int
3202 3201 aac_fib_enqueue(struct aac_softstate *softs, int queue, uint32_t fib_addr,
3203 3202 uint32_t fib_size)
3204 3203 {
3205 3204 ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3206 3205 ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3207 3206 uint32_t pi, ci;
3208 3207
3209 3208 DBCALLED(softs, 2);
3210 3209
3211 3210 ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q);
3212 3211
3213 3212 /* Get the producer/consumer indices */
3214 3213 (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \
3215 3214 (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2,
3216 3215 DDI_DMA_SYNC_FORCPU);
3217 3216 if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
3218 3217 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
3219 3218 return (AACERR);
3220 3219 }
3221 3220
3222 3221 pi = ddi_get32(acc,
3223 3222 &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
3224 3223 ci = ddi_get32(acc,
3225 3224 &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
3226 3225
3227 3226 /*
3228 3227 * Wrap the queue first before we check the queue to see
3229 3228 * if it is full
3230 3229 */
3231 3230 if (pi >= aac_qinfo[queue].size)
3232 3231 pi = 0;
3233 3232
3234 3233 /* XXX queue full */
3235 3234 if ((pi + 1) == ci)
3236 3235 return (AACERR);
3237 3236
3238 3237 /* Fill in queue entry */
3239 3238 ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size);
3240 3239 ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr);
3241 3240 (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \
3242 3241 (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry),
3243 3242 DDI_DMA_SYNC_FORDEV);
3244 3243
3245 3244 /* Update producer index */
3246 3245 ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX],
3247 3246 pi + 1);
3248 3247 (void) ddi_dma_sync(dma,
3249 3248 (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \
3250 3249 (uintptr_t)softs->comm_space, sizeof (uint32_t),
3251 3250 DDI_DMA_SYNC_FORDEV);
3252 3251
3253 3252 if (aac_qinfo[queue].notify != 0)
3254 3253 AAC_NOTIFY(softs, aac_qinfo[queue].notify);
3255 3254 return (AACOK);
3256 3255 }
3257 3256
3258 3257 /*
3259 3258 * Atomically remove one entry from the nominated queue, returns 0 on
3260 3259 * success or AACERR if the queue is empty.
3261 3260 */
3262 3261 static int
3263 3262 aac_fib_dequeue(struct aac_softstate *softs, int queue, int *idxp)
3264 3263 {
3265 3264 ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3266 3265 ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3267 3266 uint32_t pi, ci;
3268 3267 int unfull = 0;
3269 3268
3270 3269 DBCALLED(softs, 2);
3271 3270
3272 3271 ASSERT(idxp);
3273 3272
3274 3273 /* Get the producer/consumer indices */
3275 3274 (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \
3276 3275 (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2,
3277 3276 DDI_DMA_SYNC_FORCPU);
3278 3277 pi = ddi_get32(acc,
3279 3278 &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
3280 3279 ci = ddi_get32(acc,
3281 3280 &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
3282 3281
3283 3282 /* Check for queue empty */
3284 3283 if (ci == pi)
3285 3284 return (AACERR);
3286 3285
3287 3286 if (pi >= aac_qinfo[queue].size)
3288 3287 pi = 0;
3289 3288
3290 3289 /* Check for queue full */
3291 3290 if (ci == pi + 1)
3292 3291 unfull = 1;
3293 3292
3294 3293 /*
3295 3294 * The controller does not wrap the queue,
3296 3295 * so we have to do it by ourselves
3297 3296 */
3298 3297 if (ci >= aac_qinfo[queue].size)
3299 3298 ci = 0;
3300 3299
3301 3300 /* Fetch the entry */
3302 3301 (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \
3303 3302 (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry),
3304 3303 DDI_DMA_SYNC_FORCPU);
3305 3304 if (aac_check_dma_handle(dma) != DDI_SUCCESS) {
3306 3305 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
3307 3306 return (AACERR);
3308 3307 }
3309 3308
3310 3309 switch (queue) {
3311 3310 case AAC_HOST_NORM_RESP_Q:
3312 3311 case AAC_HOST_HIGH_RESP_Q:
3313 3312 *idxp = ddi_get32(acc,
3314 3313 &(softs->qentries[queue] + ci)->aq_fib_addr);
3315 3314 break;
3316 3315
3317 3316 case AAC_HOST_NORM_CMD_Q:
3318 3317 case AAC_HOST_HIGH_CMD_Q:
3319 3318 *idxp = ddi_get32(acc,
3320 3319 &(softs->qentries[queue] + ci)->aq_fib_addr) / AAC_FIB_SIZE;
3321 3320 break;
3322 3321
3323 3322 default:
3324 3323 cmn_err(CE_NOTE, "!Invalid queue in aac_fib_dequeue()");
3325 3324 return (AACERR);
3326 3325 }
3327 3326
3328 3327 /* Update consumer index */
3329 3328 ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX],
3330 3329 ci + 1);
3331 3330 (void) ddi_dma_sync(dma,
3332 3331 (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \
3333 3332 (uintptr_t)softs->comm_space, sizeof (uint32_t),
3334 3333 DDI_DMA_SYNC_FORDEV);
3335 3334
3336 3335 if (unfull && aac_qinfo[queue].notify != 0)
3337 3336 AAC_NOTIFY(softs, aac_qinfo[queue].notify);
3338 3337 return (AACOK);
3339 3338 }
3340 3339
3341 3340 static struct aac_mntinforesp *
3342 3341 aac_get_mntinfo(struct aac_softstate *softs, int cid)
3343 3342 {
3344 3343 ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3345 3344 struct aac_fib *fibp = softs->sync_ac.slotp->fibp;
3346 3345 struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0];
3347 3346 struct aac_mntinforesp *mir;
3348 3347
3349 3348 ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */
3350 3349 (softs->flags & AAC_FLAGS_LBA_64BIT) ?
3351 3350 VM_NameServe64 : VM_NameServe);
3352 3351 ddi_put32(acc, &mi->MntType, FT_FILESYS);
3353 3352 ddi_put32(acc, &mi->MntCount, cid);
3354 3353
3355 3354 if (aac_sync_fib(softs, ContainerCommand,
3356 3355 AAC_FIB_SIZEOF(struct aac_mntinfo)) == AACERR) {
3357 3356 AACDB_PRINT(softs, CE_WARN, "Error probe container %d", cid);
3358 3357 return (NULL);
3359 3358 }
3360 3359
3361 3360 mir = (struct aac_mntinforesp *)&fibp->data[0];
3362 3361 if (ddi_get32(acc, &mir->Status) == ST_OK)
3363 3362 return (mir);
3364 3363 return (NULL);
3365 3364 }
3366 3365
3367 3366 static int
3368 3367 aac_get_container_count(struct aac_softstate *softs, int *count)
3369 3368 {
3370 3369 ddi_acc_handle_t acc;
3371 3370 struct aac_mntinforesp *mir;
3372 3371 int rval;
3373 3372
3374 3373 (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
3375 3374 acc = softs->sync_ac.slotp->fib_acc_handle;
3376 3375
3377 3376 if ((mir = aac_get_mntinfo(softs, 0)) == NULL) {
3378 3377 rval = AACERR;
3379 3378 goto finish;
3380 3379 }
3381 3380 *count = ddi_get32(acc, &mir->MntRespCount);
3382 3381 if (*count > AAC_MAX_LD) {
3383 3382 AACDB_PRINT(softs, CE_CONT,
3384 3383 "container count(%d) > AAC_MAX_LD", *count);
3385 3384 rval = AACERR;
3386 3385 goto finish;
3387 3386 }
3388 3387 rval = AACOK;
3389 3388
3390 3389 finish:
3391 3390 aac_sync_fib_slot_release(softs, &softs->sync_ac);
3392 3391 return (rval);
3393 3392 }
3394 3393
3395 3394 static int
3396 3395 aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid)
3397 3396 {
3398 3397 ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3399 3398 struct aac_Container *ct = (struct aac_Container *) \
3400 3399 &softs->sync_ac.slotp->fibp->data[0];
3401 3400
3402 3401 bzero(ct, sizeof (*ct) - CT_PACKET_SIZE);
3403 3402 ddi_put32(acc, &ct->Command, VM_ContainerConfig);
3404 3403 ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID);
3405 3404 ddi_put32(acc, &ct->CTCommand.param[0], cid);
3406 3405
3407 3406 if (aac_sync_fib(softs, ContainerCommand,
3408 3407 AAC_FIB_SIZEOF(struct aac_Container)) == AACERR)
3409 3408 return (AACERR);
3410 3409 if (ddi_get32(acc, &ct->CTCommand.param[0]) != CT_OK)
3411 3410 return (AACERR);
3412 3411
3413 3412 *uid = ddi_get32(acc, &ct->CTCommand.param[1]);
3414 3413 return (AACOK);
3415 3414 }
3416 3415
3417 3416 /*
3418 3417 * Request information of the container cid
3419 3418 */
3420 3419 static struct aac_mntinforesp *
3421 3420 aac_get_container_info(struct aac_softstate *softs, int cid)
3422 3421 {
3423 3422 ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle;
3424 3423 struct aac_mntinforesp *mir;
3425 3424 int rval_uid;
3426 3425 uint32_t uid;
3427 3426
3428 3427 /* Get container UID first so that it will not overwrite mntinfo */
3429 3428 rval_uid = aac_get_container_uid(softs, cid, &uid);
3430 3429
3431 3430 /* Get container basic info */
3432 3431 if ((mir = aac_get_mntinfo(softs, cid)) == NULL) {
3433 3432 AACDB_PRINT(softs, CE_CONT,
3434 3433 "query container %d info failed", cid);
3435 3434 return (NULL);
3436 3435 }
3437 3436 if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE)
3438 3437 return (mir);
3439 3438 if (rval_uid != AACOK) {
3440 3439 AACDB_PRINT(softs, CE_CONT,
3441 3440 "query container %d uid failed", cid);
3442 3441 return (NULL);
3443 3442 }
3444 3443
3445 3444 ddi_put32(acc, &mir->Status, uid);
3446 3445 return (mir);
3447 3446 }
3448 3447
3449 3448 static enum aac_cfg_event
3450 3449 aac_probe_container(struct aac_softstate *softs, uint32_t cid)
3451 3450 {
3452 3451 enum aac_cfg_event event = AAC_CFG_NULL_NOEXIST;
3453 3452 struct aac_container *dvp = &softs->containers[cid];
3454 3453 struct aac_mntinforesp *mir;
3455 3454 ddi_acc_handle_t acc;
3456 3455
3457 3456 (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
3458 3457 acc = softs->sync_ac.slotp->fib_acc_handle;
3459 3458
3460 3459 /* Get container basic info */
3461 3460 if ((mir = aac_get_container_info(softs, cid)) == NULL) {
3462 3461 /* AAC_CFG_NULL_NOEXIST */
3463 3462 goto finish;
3464 3463 }
3465 3464
3466 3465 if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) {
3467 3466 if (AAC_DEV_IS_VALID(&dvp->dev)) {
3468 3467 AACDB_PRINT(softs, CE_NOTE,
3469 3468 ">>> Container %d deleted", cid);
3470 3469 dvp->dev.flags &= ~AAC_DFLAG_VALID;
3471 3470 event = AAC_CFG_DELETE;
3472 3471 }
3473 3472 /* AAC_CFG_NULL_NOEXIST */
3474 3473 } else {
3475 3474 uint64_t size;
3476 3475 uint32_t uid;
3477 3476
3478 3477 event = AAC_CFG_NULL_EXIST;
3479 3478
3480 3479 size = AAC_MIR_SIZE(softs, acc, mir);
3481 3480 uid = ddi_get32(acc, &mir->Status);
3482 3481 if (AAC_DEV_IS_VALID(&dvp->dev)) {
3483 3482 if (dvp->uid != uid) {
3484 3483 AACDB_PRINT(softs, CE_WARN,
3485 3484 ">>> Container %u uid changed to %d",
3486 3485 cid, uid);
3487 3486 dvp->uid = uid;
3488 3487 event = AAC_CFG_CHANGE;
3489 3488 }
3490 3489 if (dvp->size != size) {
3491 3490 AACDB_PRINT(softs, CE_NOTE,
3492 3491 ">>> Container %u size changed to %"PRIu64,
3493 3492 cid, size);
3494 3493 dvp->size = size;
3495 3494 event = AAC_CFG_CHANGE;
3496 3495 }
3497 3496 } else { /* Init new container */
3498 3497 AACDB_PRINT(softs, CE_NOTE,
3499 3498 ">>> Container %d added: " \
3500 3499 "size=0x%x.%08x, type=%d, name=%s",
3501 3500 cid,
3502 3501 ddi_get32(acc, &mir->MntObj.CapacityHigh),
3503 3502 ddi_get32(acc, &mir->MntObj.Capacity),
3504 3503 ddi_get32(acc, &mir->MntObj.VolType),
3505 3504 mir->MntObj.FileSystemName);
3506 3505 dvp->dev.flags |= AAC_DFLAG_VALID;
3507 3506 dvp->dev.type = AAC_DEV_LD;
3508 3507
3509 3508 dvp->cid = cid;
3510 3509 dvp->uid = uid;
3511 3510 dvp->size = size;
3512 3511 dvp->locked = 0;
3513 3512 dvp->deleted = 0;
3514 3513
3515 3514 event = AAC_CFG_ADD;
3516 3515 }
3517 3516 }
3518 3517
3519 3518 finish:
3520 3519 aac_sync_fib_slot_release(softs, &softs->sync_ac);
3521 3520 return (event);
3522 3521 }
3523 3522
3524 3523 /*
3525 3524 * Do a rescan of all the possible containers and update the container list
3526 3525 * with newly online/offline containers, and prepare for autoconfiguration.
3527 3526 */
3528 3527 static int
3529 3528 aac_probe_containers(struct aac_softstate *softs)
3530 3529 {
3531 3530 int i, count, total;
3532 3531
3533 3532 /* Loop over possible containers */
3534 3533 count = softs->container_count;
3535 3534 if (aac_get_container_count(softs, &count) == AACERR)
3536 3535 return (AACERR);
3537 3536
3538 3537 for (i = total = 0; i < count; i++) {
3539 3538 enum aac_cfg_event event = aac_probe_container(softs, i);
3540 3539 if ((event != AAC_CFG_NULL_NOEXIST) &&
3541 3540 (event != AAC_CFG_NULL_EXIST)) {
3542 3541 (void) aac_handle_dr(softs, i, -1, event);
3543 3542 total++;
3544 3543 }
3545 3544 }
3546 3545
3547 3546 if (count < softs->container_count) {
3548 3547 struct aac_container *dvp;
3549 3548
3550 3549 for (dvp = &softs->containers[count];
3551 3550 dvp < &softs->containers[softs->container_count]; dvp++) {
3552 3551 if (!AAC_DEV_IS_VALID(&dvp->dev))
3553 3552 continue;
3554 3553 AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted",
3555 3554 dvp->cid);
3556 3555 dvp->dev.flags &= ~AAC_DFLAG_VALID;
3557 3556 (void) aac_handle_dr(softs, dvp->cid, -1,
3558 3557 AAC_CFG_DELETE);
3559 3558 }
3560 3559 }
3561 3560
3562 3561 softs->container_count = count;
3563 3562 AACDB_PRINT(softs, CE_CONT, "?Total %d container(s) found", total);
3564 3563 return (AACOK);
3565 3564 }
3566 3565
3567 3566 static int
3568 3567 aac_probe_jbod(struct aac_softstate *softs, int tgt, int event)
3569 3568 {
3570 3569 ASSERT(AAC_MAX_LD <= tgt);
3571 3570 ASSERT(tgt < AAC_MAX_DEV(softs));
3572 3571 struct aac_device *dvp;
3573 3572 dvp = AAC_DEV(softs, tgt);
3574 3573
3575 3574 switch (event) {
3576 3575 case AAC_CFG_ADD:
3577 3576 AACDB_PRINT(softs, CE_NOTE,
3578 3577 ">>> Jbod %d added", tgt - AAC_MAX_LD);
3579 3578 dvp->flags |= AAC_DFLAG_VALID;
3580 3579 dvp->type = AAC_DEV_PD;
3581 3580 break;
3582 3581 case AAC_CFG_DELETE:
3583 3582 AACDB_PRINT(softs, CE_NOTE,
3584 3583 ">>> Jbod %d deleted", tgt - AAC_MAX_LD);
3585 3584 dvp->flags &= ~AAC_DFLAG_VALID;
3586 3585 break;
3587 3586 default:
3588 3587 return (AACERR);
3589 3588 }
3590 3589 (void) aac_handle_dr(softs, tgt, 0, event);
3591 3590 return (AACOK);
3592 3591 }
3593 3592
3594 3593 static int
3595 3594 aac_alloc_comm_space(struct aac_softstate *softs)
3596 3595 {
3597 3596 size_t rlen;
3598 3597 ddi_dma_cookie_t cookie;
3599 3598 uint_t cookien;
3600 3599
3601 3600 /* Allocate DMA for comm. space */
3602 3601 if (ddi_dma_alloc_handle(
3603 3602 softs->devinfo_p,
3604 3603 &softs->addr_dma_attr,
3605 3604 DDI_DMA_SLEEP,
3606 3605 NULL,
3607 3606 &softs->comm_space_dma_handle) != DDI_SUCCESS) {
3608 3607 AACDB_PRINT(softs, CE_WARN,
3609 3608 "Cannot alloc dma handle for communication area");
3610 3609 goto error;
3611 3610 }
3612 3611 if (ddi_dma_mem_alloc(
3613 3612 softs->comm_space_dma_handle,
3614 3613 sizeof (struct aac_comm_space),
3615 3614 &softs->acc_attr,
3616 3615 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3617 3616 DDI_DMA_SLEEP,
3618 3617 NULL,
3619 3618 (caddr_t *)&softs->comm_space,
3620 3619 &rlen,
3621 3620 &softs->comm_space_acc_handle) != DDI_SUCCESS) {
3622 3621 AACDB_PRINT(softs, CE_WARN,
3623 3622 "Cannot alloc mem for communication area");
3624 3623 goto error;
3625 3624 }
3626 3625 if (ddi_dma_addr_bind_handle(
3627 3626 softs->comm_space_dma_handle,
3628 3627 NULL,
3629 3628 (caddr_t)softs->comm_space,
3630 3629 sizeof (struct aac_comm_space),
3631 3630 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3632 3631 DDI_DMA_SLEEP,
3633 3632 NULL,
3634 3633 &cookie,
3635 3634 &cookien) != DDI_DMA_MAPPED) {
3636 3635 AACDB_PRINT(softs, CE_WARN,
3637 3636 "DMA bind failed for communication area");
3638 3637 goto error;
3639 3638 }
3640 3639 softs->comm_space_phyaddr = cookie.dmac_address;
3641 3640
3642 3641 return (AACOK);
3643 3642 error:
3644 3643 if (softs->comm_space_acc_handle) {
3645 3644 ddi_dma_mem_free(&softs->comm_space_acc_handle);
3646 3645 softs->comm_space_acc_handle = NULL;
3647 3646 }
3648 3647 if (softs->comm_space_dma_handle) {
3649 3648 ddi_dma_free_handle(&softs->comm_space_dma_handle);
3650 3649 softs->comm_space_dma_handle = NULL;
3651 3650 }
3652 3651 return (AACERR);
3653 3652 }
3654 3653
3655 3654 static void
3656 3655 aac_free_comm_space(struct aac_softstate *softs)
3657 3656 {
3658 3657
3659 3658 (void) ddi_dma_unbind_handle(softs->comm_space_dma_handle);
3660 3659 ddi_dma_mem_free(&softs->comm_space_acc_handle);
3661 3660 softs->comm_space_acc_handle = NULL;
3662 3661 ddi_dma_free_handle(&softs->comm_space_dma_handle);
3663 3662 softs->comm_space_dma_handle = NULL;
3664 3663 softs->comm_space_phyaddr = NULL;
3665 3664 }
3666 3665
3667 3666 /*
3668 3667 * Initialize the data structures that are required for the communication
3669 3668 * interface to operate
3670 3669 */
3671 3670 static int
3672 3671 aac_setup_comm_space(struct aac_softstate *softs)
3673 3672 {
3674 3673 ddi_dma_handle_t dma = softs->comm_space_dma_handle;
3675 3674 ddi_acc_handle_t acc = softs->comm_space_acc_handle;
3676 3675 uint32_t comm_space_phyaddr;
3677 3676 struct aac_adapter_init *initp;
3678 3677 int qoffset;
3679 3678
3680 3679 comm_space_phyaddr = softs->comm_space_phyaddr;
3681 3680
3682 3681 /* Setup adapter init struct */
3683 3682 initp = &softs->comm_space->init_data;
3684 3683 bzero(initp, sizeof (struct aac_adapter_init));
3685 3684
3686 3685 ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION);
3687 3686 ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time());
3688 3687
3689 3688 /* Setup new/old comm. specific data */
3690 3689 if (softs->flags & AAC_FLAGS_RAW_IO) {
3691 3690 uint32_t init_flags = 0;
3692 3691
3693 3692 if (softs->flags & AAC_FLAGS_NEW_COMM)
3694 3693 init_flags |= AAC_INIT_FLAGS_NEW_COMM_SUPPORTED;
3695 3694 /* AAC_SUPPORTED_POWER_MANAGEMENT */
3696 3695 init_flags |= AAC_INIT_FLAGS_DRIVER_SUPPORTS_PM;
3697 3696 init_flags |= AAC_INIT_FLAGS_DRIVER_USES_UTC_TIME;
3698 3697
3699 3698 ddi_put32(acc, &initp->InitStructRevision,
3700 3699 AAC_INIT_STRUCT_REVISION_4);
3701 3700 ddi_put32(acc, &initp->InitFlags, init_flags);
3702 3701 /* Setup the preferred settings */
3703 3702 ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs);
3704 3703 ddi_put32(acc, &initp->MaxIoSize,
3705 3704 (softs->aac_max_sectors << 9));
3706 3705 ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size);
3707 3706 } else {
3708 3707 /*
3709 3708 * Tells the adapter about the physical location of various
3710 3709 * important shared data structures
3711 3710 */
3712 3711 ddi_put32(acc, &initp->AdapterFibsPhysicalAddress,
3713 3712 comm_space_phyaddr + \
3714 3713 offsetof(struct aac_comm_space, adapter_fibs));
3715 3714 ddi_put32(acc, &initp->AdapterFibsVirtualAddress, 0);
3716 3715 ddi_put32(acc, &initp->AdapterFibAlign, AAC_FIB_SIZE);
3717 3716 ddi_put32(acc, &initp->AdapterFibsSize,
3718 3717 AAC_ADAPTER_FIBS * AAC_FIB_SIZE);
3719 3718 ddi_put32(acc, &initp->PrintfBufferAddress,
3720 3719 comm_space_phyaddr + \
3721 3720 offsetof(struct aac_comm_space, adapter_print_buf));
3722 3721 ddi_put32(acc, &initp->PrintfBufferSize,
3723 3722 AAC_ADAPTER_PRINT_BUFSIZE);
3724 3723 ddi_put32(acc, &initp->MiniPortRevision,
3725 3724 AAC_INIT_STRUCT_MINIPORT_REVISION);
3726 3725 ddi_put32(acc, &initp->HostPhysMemPages, AAC_MAX_PFN);
3727 3726
3728 3727 qoffset = (comm_space_phyaddr + \
3729 3728 offsetof(struct aac_comm_space, qtable)) % \
3730 3729 AAC_QUEUE_ALIGN;
3731 3730 if (qoffset)
3732 3731 qoffset = AAC_QUEUE_ALIGN - qoffset;
3733 3732 softs->qtablep = (struct aac_queue_table *) \
3734 3733 ((char *)&softs->comm_space->qtable + qoffset);
3735 3734 ddi_put32(acc, &initp->CommHeaderAddress, comm_space_phyaddr + \
3736 3735 offsetof(struct aac_comm_space, qtable) + qoffset);
3737 3736
3738 3737 /* Init queue table */
3739 3738 ddi_put32(acc, &softs->qtablep-> \
3740 3739 qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_PRODUCER_INDEX],
3741 3740 AAC_HOST_NORM_CMD_ENTRIES);
3742 3741 ddi_put32(acc, &softs->qtablep-> \
3743 3742 qt_qindex[AAC_HOST_NORM_CMD_Q][AAC_CONSUMER_INDEX],
3744 3743 AAC_HOST_NORM_CMD_ENTRIES);
3745 3744 ddi_put32(acc, &softs->qtablep-> \
3746 3745 qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
3747 3746 AAC_HOST_HIGH_CMD_ENTRIES);
3748 3747 ddi_put32(acc, &softs->qtablep-> \
3749 3748 qt_qindex[AAC_HOST_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
3750 3749 AAC_HOST_HIGH_CMD_ENTRIES);
3751 3750 ddi_put32(acc, &softs->qtablep-> \
3752 3751 qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_PRODUCER_INDEX],
3753 3752 AAC_ADAP_NORM_CMD_ENTRIES);
3754 3753 ddi_put32(acc, &softs->qtablep-> \
3755 3754 qt_qindex[AAC_ADAP_NORM_CMD_Q][AAC_CONSUMER_INDEX],
3756 3755 AAC_ADAP_NORM_CMD_ENTRIES);
3757 3756 ddi_put32(acc, &softs->qtablep-> \
3758 3757 qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_PRODUCER_INDEX],
3759 3758 AAC_ADAP_HIGH_CMD_ENTRIES);
3760 3759 ddi_put32(acc, &softs->qtablep-> \
3761 3760 qt_qindex[AAC_ADAP_HIGH_CMD_Q][AAC_CONSUMER_INDEX],
3762 3761 AAC_ADAP_HIGH_CMD_ENTRIES);
3763 3762 ddi_put32(acc, &softs->qtablep-> \
3764 3763 qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_PRODUCER_INDEX],
3765 3764 AAC_HOST_NORM_RESP_ENTRIES);
3766 3765 ddi_put32(acc, &softs->qtablep-> \
3767 3766 qt_qindex[AAC_HOST_NORM_RESP_Q][AAC_CONSUMER_INDEX],
3768 3767 AAC_HOST_NORM_RESP_ENTRIES);
3769 3768 ddi_put32(acc, &softs->qtablep-> \
3770 3769 qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
3771 3770 AAC_HOST_HIGH_RESP_ENTRIES);
3772 3771 ddi_put32(acc, &softs->qtablep-> \
3773 3772 qt_qindex[AAC_HOST_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
3774 3773 AAC_HOST_HIGH_RESP_ENTRIES);
3775 3774 ddi_put32(acc, &softs->qtablep-> \
3776 3775 qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_PRODUCER_INDEX],
3777 3776 AAC_ADAP_NORM_RESP_ENTRIES);
3778 3777 ddi_put32(acc, &softs->qtablep-> \
3779 3778 qt_qindex[AAC_ADAP_NORM_RESP_Q][AAC_CONSUMER_INDEX],
3780 3779 AAC_ADAP_NORM_RESP_ENTRIES);
3781 3780 ddi_put32(acc, &softs->qtablep-> \
3782 3781 qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_PRODUCER_INDEX],
3783 3782 AAC_ADAP_HIGH_RESP_ENTRIES);
3784 3783 ddi_put32(acc, &softs->qtablep-> \
3785 3784 qt_qindex[AAC_ADAP_HIGH_RESP_Q][AAC_CONSUMER_INDEX],
3786 3785 AAC_ADAP_HIGH_RESP_ENTRIES);
3787 3786
3788 3787 /* Init queue entries */
3789 3788 softs->qentries[AAC_HOST_NORM_CMD_Q] =
3790 3789 &softs->qtablep->qt_HostNormCmdQueue[0];
3791 3790 softs->qentries[AAC_HOST_HIGH_CMD_Q] =
3792 3791 &softs->qtablep->qt_HostHighCmdQueue[0];
3793 3792 softs->qentries[AAC_ADAP_NORM_CMD_Q] =
3794 3793 &softs->qtablep->qt_AdapNormCmdQueue[0];
3795 3794 softs->qentries[AAC_ADAP_HIGH_CMD_Q] =
3796 3795 &softs->qtablep->qt_AdapHighCmdQueue[0];
3797 3796 softs->qentries[AAC_HOST_NORM_RESP_Q] =
3798 3797 &softs->qtablep->qt_HostNormRespQueue[0];
3799 3798 softs->qentries[AAC_HOST_HIGH_RESP_Q] =
3800 3799 &softs->qtablep->qt_HostHighRespQueue[0];
3801 3800 softs->qentries[AAC_ADAP_NORM_RESP_Q] =
3802 3801 &softs->qtablep->qt_AdapNormRespQueue[0];
3803 3802 softs->qentries[AAC_ADAP_HIGH_RESP_Q] =
3804 3803 &softs->qtablep->qt_AdapHighRespQueue[0];
3805 3804 }
3806 3805 (void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
3807 3806
3808 3807 /* Send init structure to the card */
3809 3808 if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT,
3810 3809 comm_space_phyaddr + \
3811 3810 offsetof(struct aac_comm_space, init_data),
3812 3811 0, 0, 0, NULL) == AACERR) {
3813 3812 AACDB_PRINT(softs, CE_WARN,
3814 3813 "Cannot send init structure to adapter");
3815 3814 return (AACERR);
3816 3815 }
3817 3816
3818 3817 return (AACOK);
3819 3818 }
3820 3819
3821 3820 static uchar_t *
3822 3821 aac_vendor_id(struct aac_softstate *softs, uchar_t *buf)
3823 3822 {
3824 3823 (void) memset(buf, ' ', AAC_VENDOR_LEN);
3825 3824 bcopy(softs->vendor_name, buf, strlen(softs->vendor_name));
3826 3825 return (buf + AAC_VENDOR_LEN);
3827 3826 }
3828 3827
3829 3828 static uchar_t *
3830 3829 aac_product_id(struct aac_softstate *softs, uchar_t *buf)
3831 3830 {
3832 3831 (void) memset(buf, ' ', AAC_PRODUCT_LEN);
3833 3832 bcopy(softs->product_name, buf, strlen(softs->product_name));
3834 3833 return (buf + AAC_PRODUCT_LEN);
3835 3834 }
3836 3835
3837 3836 /*
3838 3837 * Construct unit serial number from container uid
3839 3838 */
3840 3839 static uchar_t *
3841 3840 aac_lun_serialno(struct aac_softstate *softs, int tgt, uchar_t *buf)
3842 3841 {
3843 3842 int i, d;
3844 3843 uint32_t uid;
3845 3844
3846 3845 ASSERT(tgt >= 0 && tgt < AAC_MAX_LD);
3847 3846
3848 3847 uid = softs->containers[tgt].uid;
3849 3848 for (i = 7; i >= 0; i--) {
3850 3849 d = uid & 0xf;
3851 3850 buf[i] = d > 9 ? 'A' + (d - 0xa) : '0' + d;
3852 3851 uid >>= 4;
3853 3852 }
3854 3853 return (buf + 8);
3855 3854 }
3856 3855
3857 3856 /*
3858 3857 * SPC-3 7.5 INQUIRY command implementation
3859 3858 */
3860 3859 static void
3861 3860 aac_inquiry(struct aac_softstate *softs, struct scsi_pkt *pkt,
3862 3861 union scsi_cdb *cdbp, struct buf *bp)
3863 3862 {
3864 3863 int tgt = pkt->pkt_address.a_target;
3865 3864 char *b_addr = NULL;
3866 3865 uchar_t page = cdbp->cdb_opaque[2];
3867 3866
3868 3867 if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_CMDDT) {
3869 3868 /* Command Support Data is not supported */
3870 3869 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x00, 0);
3871 3870 return;
3872 3871 }
3873 3872
3874 3873 if (bp && bp->b_un.b_addr && bp->b_bcount) {
3875 3874 if (bp->b_flags & (B_PHYS | B_PAGEIO))
3876 3875 bp_mapin(bp);
3877 3876 b_addr = bp->b_un.b_addr;
3878 3877 }
3879 3878
3880 3879 if (cdbp->cdb_opaque[1] & AAC_CDB_INQUIRY_EVPD) {
3881 3880 uchar_t *vpdp = (uchar_t *)b_addr;
3882 3881 uchar_t *idp, *sp;
3883 3882
3884 3883 /* SPC-3 8.4 Vital product data parameters */
3885 3884 switch (page) {
3886 3885 case 0x00:
3887 3886 /* Supported VPD pages */
3888 3887 if (vpdp == NULL ||
3889 3888 bp->b_bcount < (AAC_VPD_PAGE_DATA + 3))
3890 3889 return;
3891 3890 bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3892 3891 vpdp[AAC_VPD_PAGE_CODE] = 0x00;
3893 3892 vpdp[AAC_VPD_PAGE_LENGTH] = 3;
3894 3893
3895 3894 vpdp[AAC_VPD_PAGE_DATA] = 0x00;
3896 3895 vpdp[AAC_VPD_PAGE_DATA + 1] = 0x80;
3897 3896 vpdp[AAC_VPD_PAGE_DATA + 2] = 0x83;
3898 3897
3899 3898 pkt->pkt_state |= STATE_XFERRED_DATA;
3900 3899 break;
3901 3900
3902 3901 case 0x80:
3903 3902 /* Unit serial number page */
3904 3903 if (vpdp == NULL ||
3905 3904 bp->b_bcount < (AAC_VPD_PAGE_DATA + 8))
3906 3905 return;
3907 3906 bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3908 3907 vpdp[AAC_VPD_PAGE_CODE] = 0x80;
3909 3908 vpdp[AAC_VPD_PAGE_LENGTH] = 8;
3910 3909
3911 3910 sp = &vpdp[AAC_VPD_PAGE_DATA];
3912 3911 (void) aac_lun_serialno(softs, tgt, sp);
3913 3912
3914 3913 pkt->pkt_state |= STATE_XFERRED_DATA;
3915 3914 break;
3916 3915
3917 3916 case 0x83:
3918 3917 /* Device identification page */
3919 3918 if (vpdp == NULL ||
3920 3919 bp->b_bcount < (AAC_VPD_PAGE_DATA + 32))
3921 3920 return;
3922 3921 bzero(vpdp, AAC_VPD_PAGE_LENGTH);
3923 3922 vpdp[AAC_VPD_PAGE_CODE] = 0x83;
3924 3923
3925 3924 idp = &vpdp[AAC_VPD_PAGE_DATA];
3926 3925 bzero(idp, AAC_VPD_ID_LENGTH);
3927 3926 idp[AAC_VPD_ID_CODESET] = 0x02;
3928 3927 idp[AAC_VPD_ID_TYPE] = 0x01;
3929 3928
3930 3929 /*
3931 3930 * SPC-3 Table 111 - Identifier type
3932 3931 * One recommanded method of constructing the remainder
3933 3932 * of identifier field is to concatenate the product
3934 3933 * identification field from the standard INQUIRY data
3935 3934 * field and the product serial number field from the
3936 3935 * unit serial number page.
3937 3936 */
3938 3937 sp = &idp[AAC_VPD_ID_DATA];
3939 3938 sp = aac_vendor_id(softs, sp);
3940 3939 sp = aac_product_id(softs, sp);
3941 3940 sp = aac_lun_serialno(softs, tgt, sp);
3942 3941 idp[AAC_VPD_ID_LENGTH] = (uintptr_t)sp - \
3943 3942 (uintptr_t)&idp[AAC_VPD_ID_DATA];
3944 3943
3945 3944 vpdp[AAC_VPD_PAGE_LENGTH] = (uintptr_t)sp - \
3946 3945 (uintptr_t)&vpdp[AAC_VPD_PAGE_DATA];
3947 3946 pkt->pkt_state |= STATE_XFERRED_DATA;
3948 3947 break;
3949 3948
3950 3949 default:
3951 3950 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3952 3951 0x24, 0x00, 0);
3953 3952 break;
3954 3953 }
3955 3954 } else {
3956 3955 struct scsi_inquiry *inqp = (struct scsi_inquiry *)b_addr;
3957 3956 size_t len = sizeof (struct scsi_inquiry);
3958 3957
3959 3958 if (page != 0) {
3960 3959 aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
3961 3960 0x24, 0x00, 0);
3962 3961 return;
3963 3962 }
3964 3963 if (inqp == NULL || bp->b_bcount < len)
3965 3964 return;
3966 3965
3967 3966 bzero(inqp, len);
3968 3967 inqp->inq_len = AAC_ADDITIONAL_LEN;
3969 3968 inqp->inq_ansi = AAC_ANSI_VER;
3970 3969 inqp->inq_rdf = AAC_RESP_DATA_FORMAT;
3971 3970 (void) aac_vendor_id(softs, (uchar_t *)inqp->inq_vid);
3972 3971 (void) aac_product_id(softs, (uchar_t *)inqp->inq_pid);
3973 3972 bcopy("V1.0", inqp->inq_revision, 4);
3974 3973 inqp->inq_cmdque = 1; /* enable tagged-queuing */
3975 3974 /*
3976 3975 * For "sd-max-xfer-size" property which may impact performance
3977 3976 * when IO threads increase.
3978 3977 */
3979 3978 inqp->inq_wbus32 = 1;
3980 3979
3981 3980 pkt->pkt_state |= STATE_XFERRED_DATA;
3982 3981 }
3983 3982 }
3984 3983
3985 3984 /*
3986 3985 * SPC-3 7.10 MODE SENSE command implementation
3987 3986 */
3988 3987 static void
3989 3988 aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt,
3990 3989 union scsi_cdb *cdbp, struct buf *bp, int capacity)
3991 3990 {
3992 3991 uchar_t pagecode;
3993 3992 struct mode_header *headerp;
3994 3993 struct mode_header_g1 *g1_headerp;
3995 3994 unsigned int ncyl;
3996 3995 caddr_t sense_data;
3997 3996 caddr_t next_page;
3998 3997 size_t sdata_size;
3999 3998 size_t pages_size;
4000 3999 int unsupport_page = 0;
4001 4000
4002 4001 ASSERT(cdbp->scc_cmd == SCMD_MODE_SENSE ||
4003 4002 cdbp->scc_cmd == SCMD_MODE_SENSE_G1);
4004 4003
4005 4004 if (!(bp && bp->b_un.b_addr && bp->b_bcount))
4006 4005 return;
4007 4006
4008 4007 if (bp->b_flags & (B_PHYS | B_PAGEIO))
4009 4008 bp_mapin(bp);
4010 4009 pkt->pkt_state |= STATE_XFERRED_DATA;
4011 4010 pagecode = cdbp->cdb_un.sg.scsi[0] & 0x3F;
4012 4011
4013 4012 /* calculate the size of needed buffer */
4014 4013 if (cdbp->scc_cmd == SCMD_MODE_SENSE)
4015 4014 sdata_size = MODE_HEADER_LENGTH;
4016 4015 else /* must be SCMD_MODE_SENSE_G1 */
4017 4016 sdata_size = MODE_HEADER_LENGTH_G1;
4018 4017
4019 4018 pages_size = 0;
4020 4019 switch (pagecode) {
4021 4020 case SD_MODE_SENSE_PAGE3_CODE:
4022 4021 pages_size += sizeof (struct mode_format);
4023 4022 break;
4024 4023
4025 4024 case SD_MODE_SENSE_PAGE4_CODE:
4026 4025 pages_size += sizeof (struct mode_geometry);
4027 4026 break;
4028 4027
4029 4028 case MODEPAGE_CTRL_MODE:
4030 4029 if (softs->flags & AAC_FLAGS_LBA_64BIT) {
4031 4030 pages_size += sizeof (struct mode_control_scsi3);
4032 4031 } else {
4033 4032 unsupport_page = 1;
4034 4033 }
4035 4034 break;
4036 4035
4037 4036 case MODEPAGE_ALLPAGES:
4038 4037 if (softs->flags & AAC_FLAGS_LBA_64BIT) {
4039 4038 pages_size += sizeof (struct mode_format) +
4040 4039 sizeof (struct mode_geometry) +
4041 4040 sizeof (struct mode_control_scsi3);
4042 4041 } else {
4043 4042 pages_size += sizeof (struct mode_format) +
4044 4043 sizeof (struct mode_geometry);
4045 4044 }
4046 4045 break;
4047 4046
4048 4047 default:
4049 4048 /* unsupported pages */
4050 4049 unsupport_page = 1;
4051 4050 }
4052 4051
4053 4052 /* allocate buffer to fill the send data */
4054 4053 sdata_size += pages_size;
4055 4054 sense_data = kmem_zalloc(sdata_size, KM_SLEEP);
4056 4055
4057 4056 if (cdbp->scc_cmd == SCMD_MODE_SENSE) {
4058 4057 headerp = (struct mode_header *)sense_data;
4059 4058 headerp->length = MODE_HEADER_LENGTH + pages_size -
4060 4059 sizeof (headerp->length);
4061 4060 headerp->bdesc_length = 0;
4062 4061 next_page = sense_data + sizeof (struct mode_header);
4063 4062 } else {
4064 4063 g1_headerp = (void *)sense_data;
4065 4064 g1_headerp->length = BE_16(MODE_HEADER_LENGTH_G1 + pages_size -
4066 4065 sizeof (g1_headerp->length));
4067 4066 g1_headerp->bdesc_length = 0;
4068 4067 next_page = sense_data + sizeof (struct mode_header_g1);
4069 4068 }
4070 4069
4071 4070 if (unsupport_page)
4072 4071 goto finish;
4073 4072
4074 4073 if (pagecode == SD_MODE_SENSE_PAGE3_CODE ||
4075 4074 pagecode == MODEPAGE_ALLPAGES) {
4076 4075 /* SBC-3 7.1.3.3 Format device page */
4077 4076 struct mode_format *page3p;
4078 4077
4079 4078 page3p = (void *)next_page;
4080 4079 page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE;
4081 4080 page3p->mode_page.length = sizeof (struct mode_format);
4082 4081 page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE);
4083 4082 page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK);
4084 4083
4085 4084 next_page += sizeof (struct mode_format);
4086 4085 }
4087 4086
4088 4087 if (pagecode == SD_MODE_SENSE_PAGE4_CODE ||
4089 4088 pagecode == MODEPAGE_ALLPAGES) {
4090 4089 /* SBC-3 7.1.3.8 Rigid disk device geometry page */
4091 4090 struct mode_geometry *page4p;
4092 4091
4093 4092 page4p = (void *)next_page;
4094 4093 page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE;
4095 4094 page4p->mode_page.length = sizeof (struct mode_geometry);
4096 4095 page4p->heads = AAC_NUMBER_OF_HEADS;
4097 4096 page4p->rpm = BE_16(AAC_ROTATION_SPEED);
4098 4097 ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK);
4099 4098 page4p->cyl_lb = ncyl & 0xff;
4100 4099 page4p->cyl_mb = (ncyl >> 8) & 0xff;
4101 4100 page4p->cyl_ub = (ncyl >> 16) & 0xff;
4102 4101
4103 4102 next_page += sizeof (struct mode_geometry);
4104 4103 }
4105 4104
4106 4105 if ((pagecode == MODEPAGE_CTRL_MODE || pagecode == MODEPAGE_ALLPAGES) &&
4107 4106 softs->flags & AAC_FLAGS_LBA_64BIT) {
4108 4107 /* 64-bit LBA need large sense data */
4109 4108 struct mode_control_scsi3 *mctl;
4110 4109
4111 4110 mctl = (void *)next_page;
4112 4111 mctl->mode_page.code = MODEPAGE_CTRL_MODE;
4113 4112 mctl->mode_page.length =
4114 4113 sizeof (struct mode_control_scsi3) -
4115 4114 sizeof (struct mode_page);
4116 4115 mctl->d_sense = 1;
4117 4116 }
4118 4117
4119 4118 finish:
4120 4119 /* copyout the valid data. */
4121 4120 bcopy(sense_data, bp->b_un.b_addr, min(sdata_size, bp->b_bcount));
4122 4121 kmem_free(sense_data, sdata_size);
4123 4122 }
4124 4123
4125 4124 static int
4126 4125 aac_name_node(dev_info_t *dip, char *name, int len)
4127 4126 {
4128 4127 int tgt, lun;
4129 4128
4130 4129 tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4131 4130 DDI_PROP_DONTPASS, "target", -1);
4132 4131 if (tgt == -1)
4133 4132 return (DDI_FAILURE);
4134 4133 lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4135 4134 DDI_PROP_DONTPASS, "lun", -1);
4136 4135 if (lun == -1)
4137 4136 return (DDI_FAILURE);
4138 4137
4139 4138 (void) snprintf(name, len, "%x,%x", tgt, lun);
4140 4139 return (DDI_SUCCESS);
4141 4140 }
4142 4141
4143 4142 /*ARGSUSED*/
4144 4143 static int
4145 4144 aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4146 4145 scsi_hba_tran_t *tran, struct scsi_device *sd)
4147 4146 {
4148 4147 struct aac_softstate *softs = AAC_TRAN2SOFTS(tran);
4149 4148 #if defined(DEBUG) || defined(__lock_lint)
4150 4149 int ctl = ddi_get_instance(softs->devinfo_p);
4151 4150 #endif
4152 4151 uint16_t tgt = sd->sd_address.a_target;
4153 4152 uint8_t lun = sd->sd_address.a_lun;
4154 4153 struct aac_device *dvp;
4155 4154
4156 4155 DBCALLED(softs, 2);
4157 4156
4158 4157 if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
4159 4158 /*
4160 4159 * If no persistent node exist, we don't allow .conf node
4161 4160 * to be created.
4162 4161 */
4163 4162 if (aac_find_child(softs, tgt, lun) != NULL) {
4164 4163 if (ndi_merge_node(tgt_dip, aac_name_node) !=
4165 4164 DDI_SUCCESS)
4166 4165 /* Create this .conf node */
4167 4166 return (DDI_SUCCESS);
4168 4167 }
4169 4168 return (DDI_FAILURE);
4170 4169 }
4171 4170
4172 4171 /*
4173 4172 * Only support container/phys. device that has been
4174 4173 * detected and valid
4175 4174 */
4176 4175 mutex_enter(&softs->io_lock);
4177 4176 if (tgt >= AAC_MAX_DEV(softs)) {
4178 4177 AACDB_PRINT_TRAN(softs,
4179 4178 "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun);
4180 4179 mutex_exit(&softs->io_lock);
4181 4180 return (DDI_FAILURE);
4182 4181 }
4183 4182
4184 4183 if (tgt < AAC_MAX_LD) {
4185 4184 dvp = (struct aac_device *)&softs->containers[tgt];
4186 4185 if (lun != 0 || !AAC_DEV_IS_VALID(dvp)) {
4187 4186 AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d",
4188 4187 ctl, tgt, lun);
4189 4188 mutex_exit(&softs->io_lock);
4190 4189 return (DDI_FAILURE);
4191 4190 }
4192 4191 /*
4193 4192 * Save the tgt_dip for the given target if one doesn't exist
4194 4193 * already. Dip's for non-existance tgt's will be cleared in
4195 4194 * tgt_free.
4196 4195 */
4197 4196 if (softs->containers[tgt].dev.dip == NULL &&
4198 4197 strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0)
4199 4198 softs->containers[tgt].dev.dip = tgt_dip;
4200 4199 } else {
4201 4200 dvp = (struct aac_device *)&softs->nondasds[AAC_PD(tgt)];
4202 4201 /*
4203 4202 * Save the tgt_dip for the given target if one doesn't exist
4204 4203 * already. Dip's for non-existance tgt's will be cleared in
4205 4204 * tgt_free.
4206 4205 */
4207 4206
4208 4207 if (softs->nondasds[AAC_PD(tgt)].dev.dip == NULL &&
4209 4208 strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0)
4210 4209 softs->nondasds[AAC_PD(tgt)].dev.dip = tgt_dip;
4211 4210 }
4212 4211
4213 4212 if (softs->flags & AAC_FLAGS_BRKUP) {
4214 4213 if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
4215 4214 "buf_break", 1) != DDI_PROP_SUCCESS) {
4216 4215 cmn_err(CE_CONT, "unable to create "
4217 4216 "property for t%dL%d (buf_break)", tgt, lun);
4218 4217 }
4219 4218 }
4220 4219
4221 4220 AACDB_PRINT(softs, CE_NOTE,
4222 4221 "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun,
4223 4222 (dvp->type == AAC_DEV_PD) ? "pd" : "ld");
4224 4223 mutex_exit(&softs->io_lock);
4225 4224 return (DDI_SUCCESS);
4226 4225 }
4227 4226
4228 4227 static void
4229 4228 aac_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4230 4229 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
4231 4230 {
4232 4231 #ifndef __lock_lint
4233 4232 _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran))
4234 4233 #endif
4235 4234
4236 4235 struct aac_softstate *softs = SD2AAC(sd);
4237 4236 int tgt = sd->sd_address.a_target;
4238 4237
4239 4238 mutex_enter(&softs->io_lock);
4240 4239 if (tgt < AAC_MAX_LD) {
4241 4240 if (softs->containers[tgt].dev.dip == tgt_dip)
4242 4241 softs->containers[tgt].dev.dip = NULL;
4243 4242 } else {
4244 4243 if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip)
4245 4244 softs->nondasds[AAC_PD(tgt)].dev.dip = NULL;
4246 4245 softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID;
4247 4246 }
4248 4247 mutex_exit(&softs->io_lock);
4249 4248 }
4250 4249
4251 4250 /*
4252 4251 * Check if the firmware is Up And Running. If it is in the Kernel Panic
4253 4252 * state, (BlinkLED code + 1) is returned.
4254 4253 * 0 -- firmware up and running
4255 4254 * -1 -- firmware dead
4256 4255 * >0 -- firmware kernel panic
4257 4256 */
4258 4257 static int
4259 4258 aac_check_adapter_health(struct aac_softstate *softs)
4260 4259 {
4261 4260 int rval;
4262 4261
4263 4262 rval = PCI_MEM_GET32(softs, AAC_OMR0);
4264 4263
4265 4264 if (rval & AAC_KERNEL_UP_AND_RUNNING) {
4266 4265 rval = 0;
4267 4266 } else if (rval & AAC_KERNEL_PANIC) {
4268 4267 cmn_err(CE_WARN, "firmware panic");
4269 4268 rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */
4270 4269 } else {
4271 4270 cmn_err(CE_WARN, "firmware dead");
4272 4271 rval = -1;
4273 4272 }
4274 4273 return (rval);
4275 4274 }
4276 4275
4277 4276 static void
4278 4277 aac_abort_iocmd(struct aac_softstate *softs, struct aac_cmd *acp,
4279 4278 uchar_t reason)
4280 4279 {
4281 4280 acp->flags |= AAC_CMD_ABORT;
4282 4281
4283 4282 if (acp->pkt) {
4284 4283 if (acp->slotp) { /* outstanding cmd */
4285 4284 acp->pkt->pkt_state |= STATE_GOT_STATUS;
4286 4285 }
4287 4286
4288 4287 switch (reason) {
4289 4288 case CMD_TIMEOUT:
4290 4289 AACDB_PRINT(softs, CE_NOTE, "CMD_TIMEOUT: acp=0x%p",
4291 4290 acp);
4292 4291 aac_set_pkt_reason(softs, acp, CMD_TIMEOUT,
4293 4292 STAT_TIMEOUT | STAT_BUS_RESET);
4294 4293 break;
4295 4294 case CMD_RESET:
4296 4295 /* aac support only RESET_ALL */
4297 4296 AACDB_PRINT(softs, CE_NOTE, "CMD_RESET: acp=0x%p", acp);
4298 4297 aac_set_pkt_reason(softs, acp, CMD_RESET,
4299 4298 STAT_BUS_RESET);
4300 4299 break;
4301 4300 case CMD_ABORTED:
4302 4301 AACDB_PRINT(softs, CE_NOTE, "CMD_ABORTED: acp=0x%p",
4303 4302 acp);
4304 4303 aac_set_pkt_reason(softs, acp, CMD_ABORTED,
4305 4304 STAT_ABORTED);
4306 4305 break;
4307 4306 }
4308 4307 }
4309 4308 aac_end_io(softs, acp);
4310 4309 }
4311 4310
4312 4311 /*
4313 4312 * Abort all the pending commands of type iocmd or just the command pkt
4314 4313 * corresponding to pkt
4315 4314 */
4316 4315 static void
4317 4316 aac_abort_iocmds(struct aac_softstate *softs, int iocmd, struct scsi_pkt *pkt,
4318 4317 int reason)
4319 4318 {
4320 4319 struct aac_cmd *ac_arg, *acp;
4321 4320 int i;
4322 4321
4323 4322 if (pkt == NULL) {
4324 4323 ac_arg = NULL;
4325 4324 } else {
4326 4325 ac_arg = PKT2AC(pkt);
4327 4326 iocmd = (ac_arg->flags & AAC_CMD_SYNC) ?
4328 4327 AAC_IOCMD_SYNC : AAC_IOCMD_ASYNC;
4329 4328 }
4330 4329
4331 4330 /*
4332 4331 * a) outstanding commands on the controller
4333 4332 * Note: should abort outstanding commands only after one
4334 4333 * IOP reset has been done.
4335 4334 */
4336 4335 if (iocmd & AAC_IOCMD_OUTSTANDING) {
4337 4336 struct aac_cmd *acp;
4338 4337
4339 4338 for (i = 0; i < AAC_MAX_LD; i++) {
4340 4339 if (AAC_DEV_IS_VALID(&softs->containers[i].dev))
4341 4340 softs->containers[i].reset = 1;
4342 4341 }
4343 4342 while ((acp = softs->q_busy.q_head) != NULL)
4344 4343 aac_abort_iocmd(softs, acp, reason);
4345 4344 }
4346 4345
4347 4346 /* b) commands in the waiting queues */
4348 4347 for (i = 0; i < AAC_CMDQ_NUM; i++) {
4349 4348 if (iocmd & (1 << i)) {
4350 4349 if (ac_arg) {
4351 4350 aac_abort_iocmd(softs, ac_arg, reason);
4352 4351 } else {
4353 4352 while ((acp = softs->q_wait[i].q_head) != NULL)
4354 4353 aac_abort_iocmd(softs, acp, reason);
4355 4354 }
4356 4355 }
4357 4356 }
4358 4357 }
4359 4358
4360 4359 /*
4361 4360 * The draining thread is shared among quiesce threads. It terminates
4362 4361 * when the adapter is quiesced or stopped by aac_stop_drain().
4363 4362 */
4364 4363 static void
4365 4364 aac_check_drain(void *arg)
4366 4365 {
4367 4366 struct aac_softstate *softs = arg;
4368 4367
4369 4368 mutex_enter(&softs->io_lock);
4370 4369 if (softs->ndrains) {
4371 4370 softs->drain_timeid = 0;
4372 4371 /*
4373 4372 * If both ASYNC and SYNC bus throttle are held,
4374 4373 * wake up threads only when both are drained out.
4375 4374 */
4376 4375 if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 ||
4377 4376 softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) &&
4378 4377 (softs->bus_throttle[AAC_CMDQ_SYNC] > 0 ||
4379 4378 softs->bus_ncmds[AAC_CMDQ_SYNC] == 0))
4380 4379 cv_broadcast(&softs->drain_cv);
4381 4380 else
4382 4381 softs->drain_timeid = timeout(aac_check_drain, softs,
4383 4382 AAC_QUIESCE_TICK * drv_usectohz(1000000));
4384 4383 }
4385 4384 mutex_exit(&softs->io_lock);
4386 4385 }
4387 4386
4388 4387 /*
4389 4388 * If not draining the outstanding cmds, drain them. Otherwise,
4390 4389 * only update ndrains.
4391 4390 */
4392 4391 static void
4393 4392 aac_start_drain(struct aac_softstate *softs)
4394 4393 {
4395 4394 if (softs->ndrains == 0) {
4396 4395 ASSERT(softs->drain_timeid == 0);
4397 4396 softs->drain_timeid = timeout(aac_check_drain, softs,
4398 4397 AAC_QUIESCE_TICK * drv_usectohz(1000000));
4399 4398 }
4400 4399 softs->ndrains++;
4401 4400 }
4402 4401
4403 4402 /*
4404 4403 * Stop the draining thread when no other threads use it any longer.
4405 4404 * Side effect: io_lock may be released in the middle.
4406 4405 */
4407 4406 static void
4408 4407 aac_stop_drain(struct aac_softstate *softs)
4409 4408 {
4410 4409 softs->ndrains--;
4411 4410 if (softs->ndrains == 0) {
4412 4411 if (softs->drain_timeid != 0) {
4413 4412 timeout_id_t tid = softs->drain_timeid;
4414 4413
4415 4414 softs->drain_timeid = 0;
4416 4415 mutex_exit(&softs->io_lock);
4417 4416 (void) untimeout(tid);
4418 4417 mutex_enter(&softs->io_lock);
4419 4418 }
4420 4419 }
4421 4420 }
4422 4421
4423 4422 /*
4424 4423 * The following function comes from Adaptec:
4425 4424 *
4426 4425 * Once do an IOP reset, basically the driver have to re-initialize the card
4427 4426 * as if up from a cold boot, and the driver is responsible for any IO that
4428 4427 * is outstanding to the adapter at the time of the IOP RESET. And prepare
4429 4428 * for IOP RESET by making the init code modular with the ability to call it
4430 4429 * from multiple places.
4431 4430 */
4432 4431 static int
4433 4432 aac_reset_adapter(struct aac_softstate *softs)
4434 4433 {
4435 4434 int health;
4436 4435 uint32_t status;
4437 4436 int rval = AAC_IOP_RESET_FAILED;
4438 4437
4439 4438 DBCALLED(softs, 1);
4440 4439
4441 4440 ASSERT(softs->state & AAC_STATE_RESET);
4442 4441
4443 4442 ddi_fm_acc_err_clear(softs->pci_mem_handle, DDI_FME_VER0);
4444 4443 /* Disable interrupt */
4445 4444 AAC_DISABLE_INTR(softs);
4446 4445
4447 4446 health = aac_check_adapter_health(softs);
4448 4447 if (health == -1) {
4449 4448 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
4450 4449 goto finish;
4451 4450 }
4452 4451 if (health == 0) /* flush drives if possible */
4453 4452 (void) aac_shutdown(softs);
4454 4453
4455 4454 /* Execute IOP reset */
4456 4455 if ((aac_sync_mbcommand(softs, AAC_IOP_RESET, 0, 0, 0, 0,
4457 4456 &status)) != AACOK) {
4458 4457 ddi_acc_handle_t acc;
4459 4458 struct aac_fib *fibp;
4460 4459 struct aac_pause_command *pc;
4461 4460
4462 4461 if ((status & 0xf) == 0xf) {
4463 4462 uint32_t wait_count;
4464 4463
4465 4464 /*
4466 4465 * Sunrise Lake has dual cores and we must drag the
4467 4466 * other core with us to reset simultaneously. There
4468 4467 * are 2 bits in the Inbound Reset Control and Status
4469 4468 * Register (offset 0x38) of the Sunrise Lake to reset
4470 4469 * the chip without clearing out the PCI configuration
4471 4470 * info (COMMAND & BARS).
4472 4471 */
4473 4472 PCI_MEM_PUT32(softs, AAC_IRCSR, AAC_IRCSR_CORES_RST);
4474 4473
4475 4474 /*
4476 4475 * We need to wait for 5 seconds before accessing the MU
4477 4476 * again 10000 * 100us = 1000,000us = 1000ms = 1s
4478 4477 */
4479 4478 wait_count = 5 * 10000;
4480 4479 while (wait_count) {
4481 4480 drv_usecwait(100); /* delay 100 microseconds */
4482 4481 wait_count--;
4483 4482 }
4484 4483 } else {
4485 4484 if (status == SRB_STATUS_INVALID_REQUEST)
4486 4485 cmn_err(CE_WARN, "!IOP_RESET not supported");
4487 4486 else /* probably timeout */
4488 4487 cmn_err(CE_WARN, "!IOP_RESET failed");
4489 4488
4490 4489 /* Unwind aac_shutdown() */
4491 4490 (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
4492 4491 acc = softs->sync_ac.slotp->fib_acc_handle;
4493 4492
4494 4493 fibp = softs->sync_ac.slotp->fibp;
4495 4494 pc = (struct aac_pause_command *)&fibp->data[0];
4496 4495
4497 4496 bzero(pc, sizeof (*pc));
4498 4497 ddi_put32(acc, &pc->Command, VM_ContainerConfig);
4499 4498 ddi_put32(acc, &pc->Type, CT_PAUSE_IO);
4500 4499 ddi_put32(acc, &pc->Timeout, 1);
4501 4500 ddi_put32(acc, &pc->Min, 1);
4502 4501 ddi_put32(acc, &pc->NoRescan, 1);
4503 4502
4504 4503 (void) aac_sync_fib(softs, ContainerCommand,
4505 4504 AAC_FIB_SIZEOF(struct aac_pause_command));
4506 4505 aac_sync_fib_slot_release(softs, &softs->sync_ac);
4507 4506
4508 4507 if (aac_check_adapter_health(softs) != 0)
4509 4508 ddi_fm_service_impact(softs->devinfo_p,
4510 4509 DDI_SERVICE_LOST);
4511 4510 else
4512 4511 /*
4513 4512 * IOP reset not supported or IOP not reseted
4514 4513 */
4515 4514 rval = AAC_IOP_RESET_ABNORMAL;
4516 4515 goto finish;
4517 4516 }
4518 4517 }
4519 4518
4520 4519 /*
4521 4520 * Re-read and renegotiate the FIB parameters, as one of the actions
4522 4521 * that can result from an IOP reset is the running of a new firmware
4523 4522 * image.
4524 4523 */
4525 4524 if (aac_common_attach(softs) != AACOK)
4526 4525 goto finish;
4527 4526
4528 4527 rval = AAC_IOP_RESET_SUCCEED;
4529 4528
4530 4529 finish:
4531 4530 AAC_ENABLE_INTR(softs);
4532 4531 return (rval);
4533 4532 }
4534 4533
4535 4534 static void
4536 4535 aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q,
4537 4536 int throttle)
4538 4537 {
4539 4538 /*
4540 4539 * If the bus is draining/quiesced, no changes to the throttles
4541 4540 * are allowed. All throttles should have been set to 0.
4542 4541 */
4543 4542 if ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains)
4544 4543 return;
4545 4544 dvp->throttle[q] = throttle;
4546 4545 }
4547 4546
4548 4547 static void
4549 4548 aac_hold_bus(struct aac_softstate *softs, int iocmds)
4550 4549 {
4551 4550 int i, q;
4552 4551
4553 4552 /* Hold bus by holding every device on the bus */
4554 4553 for (q = 0; q < AAC_CMDQ_NUM; q++) {
4555 4554 if (iocmds & (1 << q)) {
4556 4555 softs->bus_throttle[q] = 0;
4557 4556 for (i = 0; i < AAC_MAX_LD; i++)
4558 4557 aac_set_throttle(softs,
4559 4558 &softs->containers[i].dev, q, 0);
4560 4559 for (i = 0; i < AAC_MAX_PD(softs); i++)
4561 4560 aac_set_throttle(softs,
4562 4561 &softs->nondasds[i].dev, q, 0);
4563 4562 }
4564 4563 }
4565 4564 }
4566 4565
4567 4566 static void
4568 4567 aac_unhold_bus(struct aac_softstate *softs, int iocmds)
4569 4568 {
4570 4569 int i, q, max_throttle;
4571 4570
4572 4571 for (q = 0; q < AAC_CMDQ_NUM; q++) {
4573 4572 if (iocmds & (1 << q)) {
4574 4573 /*
4575 4574 * Should not unhold AAC_IOCMD_ASYNC bus, if it has been
4576 4575 * quiesced or being drained by possibly some quiesce
4577 4576 * threads.
4578 4577 */
4579 4578 if (q == AAC_CMDQ_ASYNC && ((softs->state &
4580 4579 AAC_STATE_QUIESCED) || softs->ndrains))
4581 4580 continue;
4582 4581 if (q == AAC_CMDQ_ASYNC)
4583 4582 max_throttle = softs->total_slots -
4584 4583 AAC_MGT_SLOT_NUM;
4585 4584 else
4586 4585 max_throttle = softs->total_slots - 1;
4587 4586 softs->bus_throttle[q] = max_throttle;
4588 4587 for (i = 0; i < AAC_MAX_LD; i++)
4589 4588 aac_set_throttle(softs,
4590 4589 &softs->containers[i].dev,
4591 4590 q, max_throttle);
4592 4591 for (i = 0; i < AAC_MAX_PD(softs); i++)
4593 4592 aac_set_throttle(softs, &softs->nondasds[i].dev,
4594 4593 q, max_throttle);
4595 4594 }
4596 4595 }
4597 4596 }
4598 4597
4599 4598 static int
4600 4599 aac_do_reset(struct aac_softstate *softs)
4601 4600 {
4602 4601 int health;
4603 4602 int rval;
4604 4603
4605 4604 softs->state |= AAC_STATE_RESET;
4606 4605 health = aac_check_adapter_health(softs);
4607 4606
4608 4607 /*
4609 4608 * Hold off new io commands and wait all outstanding io
4610 4609 * commands to complete.
4611 4610 */
4612 4611 if (health == 0) {
4613 4612 int sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC];
4614 4613 int async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC];
4615 4614
4616 4615 if (sync_cmds == 0 && async_cmds == 0) {
4617 4616 rval = AAC_IOP_RESET_SUCCEED;
4618 4617 goto finish;
4619 4618 }
4620 4619 /*
4621 4620 * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds
4622 4621 * to complete the outstanding io commands
4623 4622 */
4624 4623 int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10;
4625 4624 int (*intr_handler)(struct aac_softstate *);
4626 4625
4627 4626 aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
4628 4627 /*
4629 4628 * Poll the adapter by ourselves in case interrupt is disabled
4630 4629 * and to avoid releasing the io_lock.
4631 4630 */
4632 4631 intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
4633 4632 aac_process_intr_new : aac_process_intr_old;
4634 4633 while ((softs->bus_ncmds[AAC_CMDQ_SYNC] ||
4635 4634 softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) {
4636 4635 drv_usecwait(100);
4637 4636 (void) intr_handler(softs);
4638 4637 timeout--;
4639 4638 }
4640 4639 aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC);
4641 4640
4642 4641 if (softs->bus_ncmds[AAC_CMDQ_SYNC] == 0 &&
4643 4642 softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) {
4644 4643 /* Cmds drained out */
4645 4644 rval = AAC_IOP_RESET_SUCCEED;
4646 4645 goto finish;
4647 4646 } else if (softs->bus_ncmds[AAC_CMDQ_SYNC] < sync_cmds ||
4648 4647 softs->bus_ncmds[AAC_CMDQ_ASYNC] < async_cmds) {
4649 4648 /* Cmds not drained out, adapter overloaded */
4650 4649 rval = AAC_IOP_RESET_ABNORMAL;
4651 4650 goto finish;
4652 4651 }
4653 4652 }
4654 4653
4655 4654 /*
4656 4655 * If a longer waiting time still can't drain any outstanding io
4657 4656 * commands, do IOP reset.
4658 4657 */
4659 4658 if ((rval = aac_reset_adapter(softs)) == AAC_IOP_RESET_FAILED)
4660 4659 softs->state |= AAC_STATE_DEAD;
4661 4660
4662 4661 finish:
4663 4662 softs->state &= ~AAC_STATE_RESET;
4664 4663 return (rval);
4665 4664 }
4666 4665
4667 4666 static int
4668 4667 aac_tran_reset(struct scsi_address *ap, int level)
4669 4668 {
4670 4669 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4671 4670 int rval;
4672 4671
4673 4672 DBCALLED(softs, 1);
4674 4673
4675 4674 if (level != RESET_ALL) {
4676 4675 cmn_err(CE_NOTE, "!reset target/lun not supported");
4677 4676 return (0);
4678 4677 }
4679 4678
4680 4679 mutex_enter(&softs->io_lock);
4681 4680 switch (rval = aac_do_reset(softs)) {
4682 4681 case AAC_IOP_RESET_SUCCEED:
4683 4682 aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC,
4684 4683 NULL, CMD_RESET);
4685 4684 aac_start_waiting_io(softs);
4686 4685 break;
4687 4686 case AAC_IOP_RESET_FAILED:
4688 4687 /* Abort IOCTL cmds when adapter is dead */
4689 4688 aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET);
4690 4689 break;
4691 4690 case AAC_IOP_RESET_ABNORMAL:
4692 4691 aac_start_waiting_io(softs);
4693 4692 }
4694 4693 mutex_exit(&softs->io_lock);
4695 4694
4696 4695 aac_drain_comp_q(softs);
4697 4696 return (rval == 0);
4698 4697 }
4699 4698
4700 4699 static int
4701 4700 aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
4702 4701 {
4703 4702 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4704 4703
4705 4704 DBCALLED(softs, 1);
4706 4705
4707 4706 mutex_enter(&softs->io_lock);
4708 4707 aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED);
4709 4708 mutex_exit(&softs->io_lock);
4710 4709
4711 4710 aac_drain_comp_q(softs);
4712 4711 return (1);
4713 4712 }
4714 4713
4715 4714 void
4716 4715 aac_free_dmamap(struct aac_cmd *acp)
4717 4716 {
4718 4717 /* Free dma mapping */
4719 4718 if (acp->flags & AAC_CMD_DMA_VALID) {
4720 4719 ASSERT(acp->buf_dma_handle);
4721 4720 (void) ddi_dma_unbind_handle(acp->buf_dma_handle);
4722 4721 acp->flags &= ~AAC_CMD_DMA_VALID;
4723 4722 }
4724 4723
4725 4724 if (acp->abp != NULL) { /* free non-aligned buf DMA */
4726 4725 ASSERT(acp->buf_dma_handle);
4727 4726 if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp)
4728 4727 ddi_rep_get8(acp->abh, (uint8_t *)acp->bp->b_un.b_addr,
4729 4728 (uint8_t *)acp->abp, acp->bp->b_bcount,
4730 4729 DDI_DEV_AUTOINCR);
4731 4730 ddi_dma_mem_free(&acp->abh);
4732 4731 acp->abp = NULL;
4733 4732 }
4734 4733
4735 4734 if (acp->buf_dma_handle) {
4736 4735 ddi_dma_free_handle(&acp->buf_dma_handle);
4737 4736 acp->buf_dma_handle = NULL;
4738 4737 }
4739 4738 }
4740 4739
4741 4740 static void
4742 4741 aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
4743 4742 {
4744 4743 AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported",
4745 4744 ((union scsi_cdb *)(void *)acp->pkt->pkt_cdbp)->scc_cmd);
4746 4745 aac_free_dmamap(acp);
4747 4746 aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0);
4748 4747 aac_soft_callback(softs, acp);
4749 4748 }
4750 4749
4751 4750 /*
4752 4751 * Handle command to logical device
4753 4752 */
4754 4753 static int
4755 4754 aac_tran_start_ld(struct aac_softstate *softs, struct aac_cmd *acp)
4756 4755 {
4757 4756 struct aac_container *dvp;
4758 4757 struct scsi_pkt *pkt;
4759 4758 union scsi_cdb *cdbp;
4760 4759 struct buf *bp;
4761 4760 int rval;
4762 4761
4763 4762 dvp = (struct aac_container *)acp->dvp;
4764 4763 pkt = acp->pkt;
4765 4764 cdbp = (void *)pkt->pkt_cdbp;
4766 4765 bp = acp->bp;
4767 4766
4768 4767 switch (cdbp->scc_cmd) {
4769 4768 case SCMD_INQUIRY: /* inquiry */
4770 4769 aac_free_dmamap(acp);
4771 4770 aac_inquiry(softs, pkt, cdbp, bp);
4772 4771 aac_soft_callback(softs, acp);
4773 4772 rval = TRAN_ACCEPT;
4774 4773 break;
4775 4774
4776 4775 case SCMD_READ_CAPACITY: /* read capacity */
4777 4776 if (bp && bp->b_un.b_addr && bp->b_bcount) {
4778 4777 struct scsi_capacity cap;
4779 4778 uint64_t last_lba;
4780 4779
4781 4780 /* check 64-bit LBA */
4782 4781 last_lba = dvp->size - 1;
4783 4782 if (last_lba > 0xffffffffull) {
4784 4783 cap.capacity = 0xfffffffful;
4785 4784 } else {
4786 4785 cap.capacity = BE_32(last_lba);
4787 4786 }
4788 4787 cap.lbasize = BE_32(AAC_SECTOR_SIZE);
4789 4788
4790 4789 aac_free_dmamap(acp);
4791 4790 if (bp->b_flags & (B_PHYS|B_PAGEIO))
4792 4791 bp_mapin(bp);
4793 4792 bcopy(&cap, bp->b_un.b_addr, min(bp->b_bcount, 8));
4794 4793 pkt->pkt_state |= STATE_XFERRED_DATA;
4795 4794 }
4796 4795 aac_soft_callback(softs, acp);
4797 4796 rval = TRAN_ACCEPT;
4798 4797 break;
4799 4798
4800 4799 case SCMD_SVC_ACTION_IN_G4: /* read capacity 16 */
4801 4800 /* Check if containers need 64-bit LBA support */
4802 4801 if (cdbp->cdb_opaque[1] == SSVC_ACTION_READ_CAPACITY_G4) {
4803 4802 if (bp && bp->b_un.b_addr && bp->b_bcount) {
4804 4803 struct scsi_capacity_16 cap16;
4805 4804 int cap_len = sizeof (struct scsi_capacity_16);
4806 4805
4807 4806 bzero(&cap16, cap_len);
4808 4807 cap16.sc_capacity = BE_64(dvp->size - 1);
4809 4808 cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE);
4810 4809
4811 4810 aac_free_dmamap(acp);
4812 4811 if (bp->b_flags & (B_PHYS | B_PAGEIO))
4813 4812 bp_mapin(bp);
4814 4813 bcopy(&cap16, bp->b_un.b_addr,
4815 4814 min(bp->b_bcount, cap_len));
4816 4815 pkt->pkt_state |= STATE_XFERRED_DATA;
4817 4816 }
4818 4817 aac_soft_callback(softs, acp);
4819 4818 } else {
4820 4819 aac_unknown_scmd(softs, acp);
4821 4820 }
4822 4821 rval = TRAN_ACCEPT;
4823 4822 break;
4824 4823
4825 4824 case SCMD_READ_G4: /* read_16 */
4826 4825 case SCMD_WRITE_G4: /* write_16 */
4827 4826 if (softs->flags & AAC_FLAGS_RAW_IO) {
4828 4827 /* NOTE: GETG4ADDRTL(cdbp) is int32_t */
4829 4828 acp->blkno = ((uint64_t) \
4830 4829 GETG4ADDR(cdbp) << 32) | \
4831 4830 (uint32_t)GETG4ADDRTL(cdbp);
4832 4831 goto do_io;
4833 4832 }
4834 4833 AACDB_PRINT(softs, CE_WARN, "64-bit LBA not supported");
4835 4834 aac_unknown_scmd(softs, acp);
4836 4835 rval = TRAN_ACCEPT;
4837 4836 break;
4838 4837
4839 4838 case SCMD_READ: /* read_6 */
4840 4839 case SCMD_WRITE: /* write_6 */
4841 4840 acp->blkno = GETG0ADDR(cdbp);
4842 4841 goto do_io;
4843 4842
4844 4843 case SCMD_READ_G5: /* read_12 */
4845 4844 case SCMD_WRITE_G5: /* write_12 */
4846 4845 acp->blkno = GETG5ADDR(cdbp);
4847 4846 goto do_io;
4848 4847
4849 4848 case SCMD_READ_G1: /* read_10 */
4850 4849 case SCMD_WRITE_G1: /* write_10 */
4851 4850 acp->blkno = (uint32_t)GETG1ADDR(cdbp);
4852 4851 do_io:
4853 4852 if (acp->flags & AAC_CMD_DMA_VALID) {
4854 4853 uint64_t cnt_size = dvp->size;
4855 4854
4856 4855 /*
4857 4856 * If LBA > array size AND rawio, the
4858 4857 * adapter may hang. So check it before
4859 4858 * sending.
4860 4859 * NOTE: (blkno + blkcnt) may overflow
4861 4860 */
4862 4861 if ((acp->blkno < cnt_size) &&
4863 4862 ((acp->blkno + acp->bcount /
4864 4863 AAC_BLK_SIZE) <= cnt_size)) {
4865 4864 rval = aac_do_io(softs, acp);
4866 4865 } else {
4867 4866 /*
4868 4867 * Request exceeds the capacity of disk,
4869 4868 * set error block number to last LBA
4870 4869 * + 1.
4871 4870 */
4872 4871 aac_set_arq_data(pkt,
4873 4872 KEY_ILLEGAL_REQUEST, 0x21,
4874 4873 0x00, cnt_size);
4875 4874 aac_soft_callback(softs, acp);
4876 4875 rval = TRAN_ACCEPT;
4877 4876 }
4878 4877 } else if (acp->bcount == 0) {
4879 4878 /* For 0 length IO, just return ok */
4880 4879 aac_soft_callback(softs, acp);
4881 4880 rval = TRAN_ACCEPT;
4882 4881 } else {
4883 4882 rval = TRAN_BADPKT;
4884 4883 }
4885 4884 break;
4886 4885
4887 4886 case SCMD_MODE_SENSE: /* mode_sense_6 */
4888 4887 case SCMD_MODE_SENSE_G1: { /* mode_sense_10 */
4889 4888 int capacity;
4890 4889
4891 4890 aac_free_dmamap(acp);
4892 4891 if (dvp->size > 0xffffffffull)
4893 4892 capacity = 0xfffffffful; /* 64-bit LBA */
4894 4893 else
4895 4894 capacity = dvp->size;
4896 4895 aac_mode_sense(softs, pkt, cdbp, bp, capacity);
4897 4896 aac_soft_callback(softs, acp);
4898 4897 rval = TRAN_ACCEPT;
4899 4898 break;
4900 4899 }
4901 4900
4902 4901 case SCMD_START_STOP:
4903 4902 if (softs->support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
4904 4903 acp->aac_cmd_fib = aac_cmd_fib_startstop;
4905 4904 acp->ac_comp = aac_startstop_complete;
4906 4905 rval = aac_do_io(softs, acp);
4907 4906 break;
4908 4907 }
4909 4908 /* FALLTHRU */
4910 4909 case SCMD_TEST_UNIT_READY:
4911 4910 case SCMD_REQUEST_SENSE:
4912 4911 case SCMD_FORMAT:
4913 4912 aac_free_dmamap(acp);
4914 4913 if (bp && bp->b_un.b_addr && bp->b_bcount) {
4915 4914 if (acp->flags & AAC_CMD_BUF_READ) {
4916 4915 if (bp->b_flags & (B_PHYS|B_PAGEIO))
4917 4916 bp_mapin(bp);
4918 4917 bzero(bp->b_un.b_addr, bp->b_bcount);
4919 4918 }
4920 4919 pkt->pkt_state |= STATE_XFERRED_DATA;
4921 4920 }
4922 4921 aac_soft_callback(softs, acp);
4923 4922 rval = TRAN_ACCEPT;
4924 4923 break;
4925 4924
4926 4925 case SCMD_SYNCHRONIZE_CACHE:
4927 4926 acp->flags |= AAC_CMD_NTAG;
4928 4927 acp->aac_cmd_fib = aac_cmd_fib_sync;
4929 4928 acp->ac_comp = aac_synccache_complete;
4930 4929 rval = aac_do_io(softs, acp);
4931 4930 break;
4932 4931
4933 4932 case SCMD_DOORLOCK:
4934 4933 aac_free_dmamap(acp);
4935 4934 dvp->locked = (pkt->pkt_cdbp[4] & 0x01) ? 1 : 0;
4936 4935 aac_soft_callback(softs, acp);
4937 4936 rval = TRAN_ACCEPT;
4938 4937 break;
4939 4938
4940 4939 default: /* unknown command */
4941 4940 aac_unknown_scmd(softs, acp);
4942 4941 rval = TRAN_ACCEPT;
4943 4942 break;
4944 4943 }
4945 4944
4946 4945 return (rval);
4947 4946 }
4948 4947
4949 4948 static int
4950 4949 aac_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
4951 4950 {
4952 4951 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
4953 4952 struct aac_cmd *acp = PKT2AC(pkt);
4954 4953 struct aac_device *dvp = acp->dvp;
4955 4954 int rval;
4956 4955
4957 4956 DBCALLED(softs, 2);
4958 4957
4959 4958 /*
4960 4959 * Reinitialize some fields of ac and pkt; the packet may
4961 4960 * have been resubmitted
4962 4961 */
4963 4962 acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \
4964 4963 AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID;
4965 4964 acp->timeout = acp->pkt->pkt_time;
4966 4965 if (pkt->pkt_flags & FLAG_NOINTR)
4967 4966 acp->flags |= AAC_CMD_NO_INTR;
4968 4967 #ifdef DEBUG
4969 4968 acp->fib_flags = AACDB_FLAGS_FIB_SCMD;
4970 4969 #endif
4971 4970 pkt->pkt_reason = CMD_CMPLT;
4972 4971 pkt->pkt_state = 0;
4973 4972 pkt->pkt_statistics = 0;
4974 4973 *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */
4975 4974
4976 4975 if (acp->flags & AAC_CMD_DMA_VALID) {
4977 4976 pkt->pkt_resid = acp->bcount;
4978 4977 /* Consistent packets need to be sync'ed first */
4979 4978 if ((acp->flags & AAC_CMD_CONSISTENT) &&
4980 4979 (acp->flags & AAC_CMD_BUF_WRITE))
4981 4980 if (aac_dma_sync_ac(acp) != AACOK) {
4982 4981 ddi_fm_service_impact(softs->devinfo_p,
4983 4982 DDI_SERVICE_UNAFFECTED);
4984 4983 return (TRAN_BADPKT);
4985 4984 }
4986 4985 } else {
4987 4986 pkt->pkt_resid = 0;
4988 4987 }
4989 4988
4990 4989 mutex_enter(&softs->io_lock);
4991 4990 AACDB_PRINT_SCMD(softs, acp);
4992 4991 if ((dvp->flags & (AAC_DFLAG_VALID | AAC_DFLAG_CONFIGURING)) &&
4993 4992 !(softs->state & AAC_STATE_DEAD)) {
4994 4993 if (dvp->type == AAC_DEV_LD) {
4995 4994 if (ap->a_lun == 0)
4996 4995 rval = aac_tran_start_ld(softs, acp);
4997 4996 else
4998 4997 goto error;
4999 4998 } else {
5000 4999 rval = aac_do_io(softs, acp);
5001 5000 }
5002 5001 } else {
5003 5002 error:
5004 5003 #ifdef DEBUG
5005 5004 if (!(softs->state & AAC_STATE_DEAD)) {
5006 5005 AACDB_PRINT_TRAN(softs,
5007 5006 "Cannot send cmd to target t%dL%d: %s",
5008 5007 ap->a_target, ap->a_lun,
5009 5008 "target invalid");
5010 5009 } else {
5011 5010 AACDB_PRINT(softs, CE_WARN,
5012 5011 "Cannot send cmd to target t%dL%d: %s",
5013 5012 ap->a_target, ap->a_lun,
5014 5013 "adapter dead");
5015 5014 }
5016 5015 #endif
5017 5016 rval = TRAN_FATAL_ERROR;
5018 5017 }
5019 5018 mutex_exit(&softs->io_lock);
5020 5019 return (rval);
5021 5020 }
5022 5021
5023 5022 static int
5024 5023 aac_tran_getcap(struct scsi_address *ap, char *cap, int whom)
5025 5024 {
5026 5025 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
5027 5026 struct aac_device *dvp;
5028 5027 int rval;
5029 5028
5030 5029 DBCALLED(softs, 2);
5031 5030
5032 5031 /* We don't allow inquiring about capabilities for other targets */
5033 5032 if (cap == NULL || whom == 0) {
5034 5033 AACDB_PRINT(softs, CE_WARN,
5035 5034 "GetCap> %s not supported: whom=%d", cap, whom);
5036 5035 return (-1);
5037 5036 }
5038 5037
5039 5038 mutex_enter(&softs->io_lock);
5040 5039 dvp = AAC_DEV(softs, ap->a_target);
5041 5040 if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
5042 5041 mutex_exit(&softs->io_lock);
5043 5042 AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to getcap",
5044 5043 ap->a_target, ap->a_lun);
5045 5044 return (-1);
5046 5045 }
5047 5046
5048 5047 switch (scsi_hba_lookup_capstr(cap)) {
5049 5048 case SCSI_CAP_ARQ: /* auto request sense */
5050 5049 rval = 1;
5051 5050 break;
5052 5051 case SCSI_CAP_UNTAGGED_QING:
5053 5052 case SCSI_CAP_TAGGED_QING:
5054 5053 rval = 1;
5055 5054 break;
5056 5055 case SCSI_CAP_DMA_MAX:
5057 5056 rval = softs->dma_max;
5058 5057 break;
5059 5058 default:
5060 5059 rval = -1;
5061 5060 break;
5062 5061 }
5063 5062 mutex_exit(&softs->io_lock);
5064 5063
5065 5064 AACDB_PRINT_TRAN(softs, "GetCap> %s t%dL%d: rval=%d",
5066 5065 cap, ap->a_target, ap->a_lun, rval);
5067 5066 return (rval);
5068 5067 }
5069 5068
5070 5069 /*ARGSUSED*/
5071 5070 static int
5072 5071 aac_tran_setcap(struct scsi_address *ap, char *cap, int value, int whom)
5073 5072 {
5074 5073 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
5075 5074 struct aac_device *dvp;
5076 5075 int rval;
5077 5076
5078 5077 DBCALLED(softs, 2);
5079 5078
5080 5079 /* We don't allow inquiring about capabilities for other targets */
5081 5080 if (cap == NULL || whom == 0) {
5082 5081 AACDB_PRINT(softs, CE_WARN,
5083 5082 "SetCap> %s not supported: whom=%d", cap, whom);
5084 5083 return (-1);
5085 5084 }
5086 5085
5087 5086 mutex_enter(&softs->io_lock);
5088 5087 dvp = AAC_DEV(softs, ap->a_target);
5089 5088 if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) {
5090 5089 mutex_exit(&softs->io_lock);
5091 5090 AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to setcap",
5092 5091 ap->a_target, ap->a_lun);
5093 5092 return (-1);
5094 5093 }
5095 5094
5096 5095 switch (scsi_hba_lookup_capstr(cap)) {
5097 5096 case SCSI_CAP_ARQ:
5098 5097 /* Force auto request sense */
5099 5098 rval = (value == 1) ? 1 : 0;
5100 5099 break;
5101 5100 case SCSI_CAP_UNTAGGED_QING:
5102 5101 case SCSI_CAP_TAGGED_QING:
5103 5102 rval = (value == 1) ? 1 : 0;
5104 5103 break;
5105 5104 default:
5106 5105 rval = -1;
5107 5106 break;
5108 5107 }
5109 5108 mutex_exit(&softs->io_lock);
5110 5109
5111 5110 AACDB_PRINT_TRAN(softs, "SetCap> %s t%dL%d val=%d: rval=%d",
5112 5111 cap, ap->a_target, ap->a_lun, value, rval);
5113 5112 return (rval);
5114 5113 }
5115 5114
5116 5115 static void
5117 5116 aac_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
5118 5117 {
5119 5118 struct aac_cmd *acp = PKT2AC(pkt);
5120 5119
5121 5120 DBCALLED(NULL, 2);
5122 5121
5123 5122 if (acp->sgt) {
5124 5123 kmem_free(acp->sgt, sizeof (struct aac_sge) * \
5125 5124 acp->left_cookien);
5126 5125 }
5127 5126 aac_free_dmamap(acp);
5128 5127 ASSERT(acp->slotp == NULL);
5129 5128 scsi_hba_pkt_free(ap, pkt);
5130 5129 }
5131 5130
5132 5131 int
5133 5132 aac_cmd_dma_alloc(struct aac_softstate *softs, struct aac_cmd *acp,
5134 5133 struct buf *bp, int flags, int (*cb)(), caddr_t arg)
5135 5134 {
5136 5135 int kf = (cb == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
5137 5136 uint_t oldcookiec;
5138 5137 int bioerr;
5139 5138 int rval;
5140 5139
5141 5140 oldcookiec = acp->left_cookien;
5142 5141
5143 5142 /* Move window to build s/g map */
5144 5143 if (acp->total_nwin > 0) {
5145 5144 if (++acp->cur_win < acp->total_nwin) {
5146 5145 off_t off;
5147 5146 size_t len;
5148 5147
5149 5148 rval = ddi_dma_getwin(acp->buf_dma_handle, acp->cur_win,
5150 5149 &off, &len, &acp->cookie, &acp->left_cookien);
5151 5150 if (rval == DDI_SUCCESS)
5152 5151 goto get_dma_cookies;
5153 5152 AACDB_PRINT(softs, CE_WARN,
5154 5153 "ddi_dma_getwin() fail %d", rval);
5155 5154 return (AACERR);
5156 5155 }
5157 5156 AACDB_PRINT(softs, CE_WARN, "Nothing to transfer");
5158 5157 return (AACERR);
5159 5158 }
5160 5159
5161 5160 /* We need to transfer data, so we alloc DMA resources for this pkt */
5162 5161 if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) {
5163 5162 uint_t dma_flags = 0;
5164 5163 struct aac_sge *sge;
5165 5164
5166 5165 /*
5167 5166 * We will still use this point to fake some
5168 5167 * infomation in tran_start
5169 5168 */
5170 5169 acp->bp = bp;
5171 5170
5172 5171 /* Set dma flags */
5173 5172 if (BUF_IS_READ(bp)) {
5174 5173 dma_flags |= DDI_DMA_READ;
5175 5174 acp->flags |= AAC_CMD_BUF_READ;
5176 5175 } else {
5177 5176 dma_flags |= DDI_DMA_WRITE;
5178 5177 acp->flags |= AAC_CMD_BUF_WRITE;
5179 5178 }
5180 5179 if (flags & PKT_CONSISTENT)
5181 5180 dma_flags |= DDI_DMA_CONSISTENT;
5182 5181 if (flags & PKT_DMA_PARTIAL)
5183 5182 dma_flags |= DDI_DMA_PARTIAL;
5184 5183
5185 5184 /* Alloc buf dma handle */
5186 5185 if (!acp->buf_dma_handle) {
5187 5186 rval = ddi_dma_alloc_handle(softs->devinfo_p,
5188 5187 &softs->buf_dma_attr, cb, arg,
5189 5188 &acp->buf_dma_handle);
5190 5189 if (rval != DDI_SUCCESS) {
5191 5190 AACDB_PRINT(softs, CE_WARN,
5192 5191 "Can't allocate DMA handle, errno=%d",
5193 5192 rval);
5194 5193 goto error_out;
5195 5194 }
5196 5195 }
5197 5196
5198 5197 /* Bind buf */
5199 5198 if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0) {
5200 5199 rval = ddi_dma_buf_bind_handle(acp->buf_dma_handle,
5201 5200 bp, dma_flags, cb, arg, &acp->cookie,
5202 5201 &acp->left_cookien);
5203 5202 } else {
5204 5203 size_t bufsz;
5205 5204
5206 5205 AACDB_PRINT_TRAN(softs,
5207 5206 "non-aligned buffer: addr=0x%p, cnt=%lu",
5208 5207 (void *)bp->b_un.b_addr, bp->b_bcount);
5209 5208 if (bp->b_flags & (B_PAGEIO|B_PHYS))
5210 5209 bp_mapin(bp);
5211 5210
5212 5211 rval = ddi_dma_mem_alloc(acp->buf_dma_handle,
5213 5212 AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN),
5214 5213 &softs->acc_attr, DDI_DMA_STREAMING,
5215 5214 cb, arg, &acp->abp, &bufsz, &acp->abh);
5216 5215
5217 5216 if (rval != DDI_SUCCESS) {
5218 5217 AACDB_PRINT(softs, CE_NOTE,
5219 5218 "Cannot alloc DMA to non-aligned buf");
5220 5219 bioerr = 0;
5221 5220 goto error_out;
5222 5221 }
5223 5222
5224 5223 if (acp->flags & AAC_CMD_BUF_WRITE)
5225 5224 ddi_rep_put8(acp->abh,
5226 5225 (uint8_t *)bp->b_un.b_addr,
5227 5226 (uint8_t *)acp->abp, bp->b_bcount,
5228 5227 DDI_DEV_AUTOINCR);
5229 5228
5230 5229 rval = ddi_dma_addr_bind_handle(acp->buf_dma_handle,
5231 5230 NULL, acp->abp, bufsz, dma_flags, cb, arg,
5232 5231 &acp->cookie, &acp->left_cookien);
5233 5232 }
5234 5233
5235 5234 switch (rval) {
5236 5235 case DDI_DMA_PARTIAL_MAP:
5237 5236 if (ddi_dma_numwin(acp->buf_dma_handle,
5238 5237 &acp->total_nwin) == DDI_FAILURE) {
5239 5238 AACDB_PRINT(softs, CE_WARN,
5240 5239 "Cannot get number of DMA windows");
5241 5240 bioerr = 0;
5242 5241 goto error_out;
5243 5242 }
5244 5243 AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
5245 5244 acp->left_cookien);
5246 5245 acp->cur_win = 0;
5247 5246 break;
5248 5247
5249 5248 case DDI_DMA_MAPPED:
5250 5249 AACDB_PRINT_TRAN(softs, "buf bind, %d seg(s)",
5251 5250 acp->left_cookien);
5252 5251 acp->cur_win = 0;
5253 5252 acp->total_nwin = 1;
5254 5253 break;
5255 5254
5256 5255 case DDI_DMA_NORESOURCES:
5257 5256 bioerr = 0;
5258 5257 AACDB_PRINT(softs, CE_WARN,
5259 5258 "Cannot bind buf for DMA: DDI_DMA_NORESOURCES");
5260 5259 goto error_out;
5261 5260 case DDI_DMA_BADATTR:
5262 5261 case DDI_DMA_NOMAPPING:
5263 5262 bioerr = EFAULT;
5264 5263 AACDB_PRINT(softs, CE_WARN,
5265 5264 "Cannot bind buf for DMA: DDI_DMA_NOMAPPING");
5266 5265 goto error_out;
5267 5266 case DDI_DMA_TOOBIG:
5268 5267 bioerr = EINVAL;
5269 5268 AACDB_PRINT(softs, CE_WARN,
5270 5269 "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d)",
5271 5270 bp->b_bcount);
5272 5271 goto error_out;
5273 5272 default:
5274 5273 bioerr = EINVAL;
5275 5274 AACDB_PRINT(softs, CE_WARN,
5276 5275 "Cannot bind buf for DMA: %d", rval);
5277 5276 goto error_out;
5278 5277 }
5279 5278 acp->flags |= AAC_CMD_DMA_VALID;
5280 5279
5281 5280 get_dma_cookies:
5282 5281 ASSERT(acp->left_cookien > 0);
5283 5282 if (acp->left_cookien > softs->aac_sg_tablesize) {
5284 5283 AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d",
5285 5284 acp->left_cookien);
5286 5285 bioerr = EINVAL;
5287 5286 goto error_out;
5288 5287 }
5289 5288 if (oldcookiec != acp->left_cookien && acp->sgt != NULL) {
5290 5289 kmem_free(acp->sgt, sizeof (struct aac_sge) * \
5291 5290 oldcookiec);
5292 5291 acp->sgt = NULL;
5293 5292 }
5294 5293 if (acp->sgt == NULL) {
5295 5294 acp->sgt = kmem_alloc(sizeof (struct aac_sge) * \
5296 5295 acp->left_cookien, kf);
5297 5296 if (acp->sgt == NULL) {
5298 5297 AACDB_PRINT(softs, CE_WARN,
5299 5298 "sgt kmem_alloc fail");
5300 5299 bioerr = ENOMEM;
5301 5300 goto error_out;
5302 5301 }
5303 5302 }
5304 5303
5305 5304 sge = &acp->sgt[0];
5306 5305 sge->bcount = acp->cookie.dmac_size;
5307 5306 sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
5308 5307 sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
5309 5308 acp->bcount = acp->cookie.dmac_size;
5310 5309 for (sge++; sge < &acp->sgt[acp->left_cookien]; sge++) {
5311 5310 ddi_dma_nextcookie(acp->buf_dma_handle, &acp->cookie);
5312 5311 sge->bcount = acp->cookie.dmac_size;
5313 5312 sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress);
5314 5313 sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress);
5315 5314 acp->bcount += acp->cookie.dmac_size;
5316 5315 }
5317 5316
5318 5317 /*
5319 5318 * Note: The old DMA engine do not correctly handle
5320 5319 * dma_attr_maxxfer attribute. So we have to ensure
5321 5320 * it by ourself.
5322 5321 */
5323 5322 if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) {
5324 5323 AACDB_PRINT(softs, CE_NOTE,
5325 5324 "large xfer size received %d\n", acp->bcount);
5326 5325 bioerr = EINVAL;
5327 5326 goto error_out;
5328 5327 }
5329 5328
5330 5329 acp->total_xfer += acp->bcount;
5331 5330
5332 5331 if (acp->pkt) {
5333 5332 /* Return remaining byte count */
5334 5333 if (acp->total_xfer <= bp->b_bcount) {
5335 5334 acp->pkt->pkt_resid = bp->b_bcount - \
5336 5335 acp->total_xfer;
5337 5336 } else {
5338 5337 /*
5339 5338 * Allocated DMA size is greater than the buf
5340 5339 * size of bp. This is caused by devices like
5341 5340 * tape. we have extra bytes allocated, but
5342 5341 * the packet residual has to stay correct.
5343 5342 */
5344 5343 acp->pkt->pkt_resid = 0;
5345 5344 }
5346 5345 AACDB_PRINT_TRAN(softs,
5347 5346 "bp=0x%p, xfered=%d/%d, resid=%d",
5348 5347 (void *)bp->b_un.b_addr, (int)acp->total_xfer,
5349 5348 (int)bp->b_bcount, (int)acp->pkt->pkt_resid);
5350 5349 }
5351 5350 }
5352 5351 return (AACOK);
5353 5352
5354 5353 error_out:
5355 5354 bioerror(bp, bioerr);
5356 5355 return (AACERR);
5357 5356 }
5358 5357
5359 5358 static struct scsi_pkt *
5360 5359 aac_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
5361 5360 struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
5362 5361 int (*callback)(), caddr_t arg)
5363 5362 {
5364 5363 struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran);
5365 5364 struct aac_cmd *acp, *new_acp;
5366 5365
5367 5366 DBCALLED(softs, 2);
5368 5367
5369 5368 /* Allocate pkt */
5370 5369 if (pkt == NULL) {
5371 5370 int slen;
5372 5371
5373 5372 /* Force auto request sense */
5374 5373 slen = (statuslen > softs->slen) ? statuslen : softs->slen;
5375 5374 pkt = scsi_hba_pkt_alloc(softs->devinfo_p, ap, cmdlen,
5376 5375 slen, tgtlen, sizeof (struct aac_cmd), callback, arg);
5377 5376 if (pkt == NULL) {
5378 5377 AACDB_PRINT(softs, CE_WARN, "Alloc scsi pkt failed");
5379 5378 return (NULL);
5380 5379 }
5381 5380 acp = new_acp = PKT2AC(pkt);
5382 5381 acp->pkt = pkt;
5383 5382 acp->cmdlen = cmdlen;
5384 5383
5385 5384 if (ap->a_target < AAC_MAX_LD) {
5386 5385 acp->dvp = &softs->containers[ap->a_target].dev;
5387 5386 acp->aac_cmd_fib = softs->aac_cmd_fib;
5388 5387 acp->ac_comp = aac_ld_complete;
5389 5388 } else {
5390 5389 _NOTE(ASSUMING_PROTECTED(softs->nondasds))
5391 5390
5392 5391 acp->dvp = &softs->nondasds[AAC_PD(ap->a_target)].dev;
5393 5392 acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
5394 5393 acp->ac_comp = aac_pd_complete;
5395 5394 }
5396 5395 } else {
5397 5396 acp = PKT2AC(pkt);
5398 5397 new_acp = NULL;
5399 5398 }
5400 5399
5401 5400 if (aac_cmd_dma_alloc(softs, acp, bp, flags, callback, arg) == AACOK)
5402 5401 return (pkt);
5403 5402
5404 5403 if (new_acp)
5405 5404 aac_tran_destroy_pkt(ap, pkt);
5406 5405 return (NULL);
5407 5406 }
5408 5407
5409 5408 /*
5410 5409 * tran_sync_pkt(9E) - explicit DMA synchronization
5411 5410 */
5412 5411 /*ARGSUSED*/
5413 5412 static void
5414 5413 aac_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
5415 5414 {
5416 5415 struct aac_cmd *acp = PKT2AC(pkt);
5417 5416
5418 5417 DBCALLED(NULL, 2);
5419 5418
5420 5419 if (aac_dma_sync_ac(acp) != AACOK)
5421 5420 ddi_fm_service_impact(
5422 5421 (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p,
5423 5422 DDI_SERVICE_UNAFFECTED);
5424 5423 }
5425 5424
5426 5425 /*
5427 5426 * tran_dmafree(9E) - deallocate DMA resources allocated for command
5428 5427 */
5429 5428 /*ARGSUSED*/
5430 5429 static void
5431 5430 aac_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
5432 5431 {
5433 5432 struct aac_cmd *acp = PKT2AC(pkt);
5434 5433
5435 5434 DBCALLED(NULL, 2);
5436 5435
5437 5436 aac_free_dmamap(acp);
5438 5437 }
5439 5438
5440 5439 static int
5441 5440 aac_do_quiesce(struct aac_softstate *softs)
5442 5441 {
5443 5442 aac_hold_bus(softs, AAC_IOCMD_ASYNC);
5444 5443 if (softs->bus_ncmds[AAC_CMDQ_ASYNC]) {
5445 5444 aac_start_drain(softs);
5446 5445 do {
5447 5446 if (cv_wait_sig(&softs->drain_cv,
5448 5447 &softs->io_lock) == 0) {
5449 5448 /* Quiesce has been interrupted */
5450 5449 aac_stop_drain(softs);
5451 5450 aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
5452 5451 aac_start_waiting_io(softs);
5453 5452 return (AACERR);
5454 5453 }
5455 5454 } while (softs->bus_ncmds[AAC_CMDQ_ASYNC]);
5456 5455 aac_stop_drain(softs);
5457 5456 }
5458 5457
5459 5458 softs->state |= AAC_STATE_QUIESCED;
5460 5459 return (AACOK);
5461 5460 }
5462 5461
5463 5462 static int
5464 5463 aac_tran_quiesce(dev_info_t *dip)
5465 5464 {
5466 5465 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
5467 5466 int rval;
5468 5467
5469 5468 DBCALLED(softs, 1);
5470 5469
5471 5470 mutex_enter(&softs->io_lock);
5472 5471 if (aac_do_quiesce(softs) == AACOK)
5473 5472 rval = 0;
5474 5473 else
5475 5474 rval = 1;
5476 5475 mutex_exit(&softs->io_lock);
5477 5476 return (rval);
5478 5477 }
5479 5478
5480 5479 static int
5481 5480 aac_do_unquiesce(struct aac_softstate *softs)
5482 5481 {
5483 5482 softs->state &= ~AAC_STATE_QUIESCED;
5484 5483 aac_unhold_bus(softs, AAC_IOCMD_ASYNC);
5485 5484
5486 5485 aac_start_waiting_io(softs);
5487 5486 return (AACOK);
5488 5487 }
5489 5488
5490 5489 static int
5491 5490 aac_tran_unquiesce(dev_info_t *dip)
5492 5491 {
5493 5492 struct aac_softstate *softs = AAC_DIP2SOFTS(dip);
5494 5493 int rval;
5495 5494
5496 5495 DBCALLED(softs, 1);
5497 5496
5498 5497 mutex_enter(&softs->io_lock);
5499 5498 if (aac_do_unquiesce(softs) == AACOK)
5500 5499 rval = 0;
5501 5500 else
5502 5501 rval = 1;
5503 5502 mutex_exit(&softs->io_lock);
5504 5503 return (rval);
5505 5504 }
5506 5505
5507 5506 static int
5508 5507 aac_hba_setup(struct aac_softstate *softs)
5509 5508 {
5510 5509 scsi_hba_tran_t *hba_tran;
5511 5510 int rval;
5512 5511
5513 5512 hba_tran = scsi_hba_tran_alloc(softs->devinfo_p, SCSI_HBA_CANSLEEP);
5514 5513 if (hba_tran == NULL)
5515 5514 return (AACERR);
5516 5515 hba_tran->tran_hba_private = softs;
5517 5516 hba_tran->tran_tgt_init = aac_tran_tgt_init;
5518 5517 hba_tran->tran_tgt_free = aac_tran_tgt_free;
5519 5518 hba_tran->tran_tgt_probe = scsi_hba_probe;
5520 5519 hba_tran->tran_start = aac_tran_start;
5521 5520 hba_tran->tran_getcap = aac_tran_getcap;
5522 5521 hba_tran->tran_setcap = aac_tran_setcap;
5523 5522 hba_tran->tran_init_pkt = aac_tran_init_pkt;
5524 5523 hba_tran->tran_destroy_pkt = aac_tran_destroy_pkt;
5525 5524 hba_tran->tran_reset = aac_tran_reset;
5526 5525 hba_tran->tran_abort = aac_tran_abort;
5527 5526 hba_tran->tran_sync_pkt = aac_tran_sync_pkt;
5528 5527 hba_tran->tran_dmafree = aac_tran_dmafree;
5529 5528 hba_tran->tran_quiesce = aac_tran_quiesce;
5530 5529 hba_tran->tran_unquiesce = aac_tran_unquiesce;
5531 5530 hba_tran->tran_bus_config = aac_tran_bus_config;
5532 5531 rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr,
5533 5532 hba_tran, 0);
5534 5533 if (rval != DDI_SUCCESS) {
5535 5534 scsi_hba_tran_free(hba_tran);
5536 5535 AACDB_PRINT(softs, CE_WARN, "aac_hba_setup failed");
5537 5536 return (AACERR);
5538 5537 }
5539 5538
5540 5539 softs->hba_tran = hba_tran;
5541 5540 return (AACOK);
5542 5541 }
5543 5542
5544 5543 /*
5545 5544 * FIB setup operations
5546 5545 */
5547 5546
5548 5547 /*
5549 5548 * Init FIB header
5550 5549 */
5551 5550 static void
5552 5551 aac_cmd_fib_header(struct aac_softstate *softs, struct aac_cmd *acp,
5553 5552 uint16_t cmd)
5554 5553 {
5555 5554 struct aac_slot *slotp = acp->slotp;
5556 5555 ddi_acc_handle_t acc = slotp->fib_acc_handle;
5557 5556 struct aac_fib *fibp = slotp->fibp;
5558 5557 uint32_t xfer_state;
5559 5558
5560 5559 xfer_state =
5561 5560 AAC_FIBSTATE_HOSTOWNED |
5562 5561 AAC_FIBSTATE_INITIALISED |
5563 5562 AAC_FIBSTATE_EMPTY |
5564 5563 AAC_FIBSTATE_FAST_RESPONSE | /* enable fast io */
5565 5564 AAC_FIBSTATE_FROMHOST |
5566 5565 AAC_FIBSTATE_REXPECTED |
5567 5566 AAC_FIBSTATE_NORM;
5568 5567
5569 5568 if (!(acp->flags & AAC_CMD_SYNC))
5570 5569 xfer_state |= AAC_FIBSTATE_ASYNC;
5571 5570
5572 5571 ddi_put32(acc, &fibp->Header.XferState, xfer_state);
5573 5572 ddi_put16(acc, &fibp->Header.Command, cmd);
5574 5573 ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB);
5575 5574 ddi_put8(acc, &fibp->Header.Flags, 0); /* don't care */
5576 5575 ddi_put16(acc, &fibp->Header.Size, acp->fib_size);
5577 5576 ddi_put16(acc, &fibp->Header.SenderSize, softs->aac_max_fib_size);
5578 5577 ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2));
5579 5578 ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
5580 5579 ddi_put32(acc, &fibp->Header.SenderData, 0); /* don't care */
5581 5580 }
5582 5581
5583 5582 /*
5584 5583 * Init FIB for raw IO command
5585 5584 */
5586 5585 static void
5587 5586 aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp)
5588 5587 {
5589 5588 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5590 5589 struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0];
5591 5590 struct aac_sg_entryraw *sgp;
5592 5591 struct aac_sge *sge;
5593 5592
5594 5593 /* Calculate FIB size */
5595 5594 acp->fib_size = sizeof (struct aac_fib_header) + \
5596 5595 sizeof (struct aac_raw_io) + (acp->left_cookien - 1) * \
5597 5596 sizeof (struct aac_sg_entryraw);
5598 5597
5599 5598 aac_cmd_fib_header(softs, acp, RawIo);
5600 5599
5601 5600 ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0);
5602 5601 ddi_put16(acc, &io->BpTotal, 0);
5603 5602 ddi_put16(acc, &io->BpComplete, 0);
5604 5603
5605 5604 ddi_put32(acc, AAC_LO32(&io->BlockNumber), AAC_LS32(acp->blkno));
5606 5605 ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno));
5607 5606 ddi_put16(acc, &io->ContainerId,
5608 5607 ((struct aac_container *)acp->dvp)->cid);
5609 5608
5610 5609 /* Fill SG table */
5611 5610 ddi_put32(acc, &io->SgMapRaw.SgCount, acp->left_cookien);
5612 5611 ddi_put32(acc, &io->ByteCount, acp->bcount);
5613 5612
5614 5613 for (sge = &acp->sgt[0], sgp = &io->SgMapRaw.SgEntryRaw[0];
5615 5614 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5616 5615 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5617 5616 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5618 5617 ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5619 5618 sgp->Next = 0;
5620 5619 sgp->Prev = 0;
5621 5620 sgp->Flags = 0;
5622 5621 }
5623 5622 }
5624 5623
5625 5624 /* Init FIB for 64-bit block IO command */
5626 5625 static void
5627 5626 aac_cmd_fib_brw64(struct aac_softstate *softs, struct aac_cmd *acp)
5628 5627 {
5629 5628 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5630 5629 struct aac_blockread64 *br = (struct aac_blockread64 *) \
5631 5630 &acp->slotp->fibp->data[0];
5632 5631 struct aac_sg_entry64 *sgp;
5633 5632 struct aac_sge *sge;
5634 5633
5635 5634 acp->fib_size = sizeof (struct aac_fib_header) + \
5636 5635 sizeof (struct aac_blockread64) + (acp->left_cookien - 1) * \
5637 5636 sizeof (struct aac_sg_entry64);
5638 5637
5639 5638 aac_cmd_fib_header(softs, acp, ContainerCommand64);
5640 5639
5641 5640 /*
5642 5641 * The definitions for aac_blockread64 and aac_blockwrite64
5643 5642 * are the same.
5644 5643 */
5645 5644 ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
5646 5645 ddi_put16(acc, &br->ContainerId,
5647 5646 ((struct aac_container *)acp->dvp)->cid);
5648 5647 ddi_put32(acc, &br->Command, (acp->flags & AAC_CMD_BUF_READ) ?
5649 5648 VM_CtHostRead64 : VM_CtHostWrite64);
5650 5649 ddi_put16(acc, &br->Pad, 0);
5651 5650 ddi_put16(acc, &br->Flags, 0);
5652 5651
5653 5652 /* Fill SG table */
5654 5653 ddi_put32(acc, &br->SgMap64.SgCount, acp->left_cookien);
5655 5654 ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE);
5656 5655
5657 5656 for (sge = &acp->sgt[0], sgp = &br->SgMap64.SgEntry64[0];
5658 5657 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5659 5658 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5660 5659 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5661 5660 ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5662 5661 }
5663 5662 }
5664 5663
5665 5664 /* Init FIB for block IO command */
5666 5665 static void
5667 5666 aac_cmd_fib_brw(struct aac_softstate *softs, struct aac_cmd *acp)
5668 5667 {
5669 5668 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5670 5669 struct aac_blockread *br = (struct aac_blockread *) \
5671 5670 &acp->slotp->fibp->data[0];
5672 5671 struct aac_sg_entry *sgp;
5673 5672 struct aac_sge *sge = &acp->sgt[0];
5674 5673
5675 5674 if (acp->flags & AAC_CMD_BUF_READ) {
5676 5675 acp->fib_size = sizeof (struct aac_fib_header) + \
5677 5676 sizeof (struct aac_blockread) + (acp->left_cookien - 1) * \
5678 5677 sizeof (struct aac_sg_entry);
5679 5678
5680 5679 ddi_put32(acc, &br->Command, VM_CtBlockRead);
5681 5680 ddi_put32(acc, &br->SgMap.SgCount, acp->left_cookien);
5682 5681 sgp = &br->SgMap.SgEntry[0];
5683 5682 } else {
5684 5683 struct aac_blockwrite *bw = (struct aac_blockwrite *)br;
5685 5684
5686 5685 acp->fib_size = sizeof (struct aac_fib_header) + \
5687 5686 sizeof (struct aac_blockwrite) + (acp->left_cookien - 1) * \
5688 5687 sizeof (struct aac_sg_entry);
5689 5688
5690 5689 ddi_put32(acc, &bw->Command, VM_CtBlockWrite);
5691 5690 ddi_put32(acc, &bw->Stable, CUNSTABLE);
5692 5691 ddi_put32(acc, &bw->SgMap.SgCount, acp->left_cookien);
5693 5692 sgp = &bw->SgMap.SgEntry[0];
5694 5693 }
5695 5694 aac_cmd_fib_header(softs, acp, ContainerCommand);
5696 5695
5697 5696 /*
5698 5697 * aac_blockread and aac_blockwrite have the similar
5699 5698 * structure head, so use br for bw here
5700 5699 */
5701 5700 ddi_put32(acc, &br->BlockNumber, (uint32_t)acp->blkno);
5702 5701 ddi_put32(acc, &br->ContainerId,
5703 5702 ((struct aac_container *)acp->dvp)->cid);
5704 5703 ddi_put32(acc, &br->ByteCount, acp->bcount);
5705 5704
5706 5705 /* Fill SG table */
5707 5706 for (sge = &acp->sgt[0];
5708 5707 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5709 5708 ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
5710 5709 ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5711 5710 }
5712 5711 }
5713 5712
5714 5713 /*ARGSUSED*/
5715 5714 void
5716 5715 aac_cmd_fib_copy(struct aac_softstate *softs, struct aac_cmd *acp)
5717 5716 {
5718 5717 struct aac_slot *slotp = acp->slotp;
5719 5718 struct aac_fib *fibp = slotp->fibp;
5720 5719 ddi_acc_handle_t acc = slotp->fib_acc_handle;
5721 5720
5722 5721 ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp,
5723 5722 acp->fib_size, /* only copy data of needed length */
5724 5723 DDI_DEV_AUTOINCR);
5725 5724 ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr);
5726 5725 ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2);
5727 5726 }
5728 5727
5729 5728 static void
5730 5729 aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp)
5731 5730 {
5732 5731 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5733 5732 struct aac_synchronize_command *sync =
5734 5733 (struct aac_synchronize_command *)&acp->slotp->fibp->data[0];
5735 5734
5736 5735 acp->fib_size = AAC_FIB_SIZEOF(struct aac_synchronize_command);
5737 5736
5738 5737 aac_cmd_fib_header(softs, acp, ContainerCommand);
5739 5738 ddi_put32(acc, &sync->Command, VM_ContainerConfig);
5740 5739 ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE);
5741 5740 ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid);
5742 5741 ddi_put32(acc, &sync->Count,
5743 5742 sizeof (((struct aac_synchronize_reply *)0)->Data));
5744 5743 }
5745 5744
5746 5745 /*
5747 5746 * Start/Stop unit (Power Management)
5748 5747 */
5749 5748 static void
5750 5749 aac_cmd_fib_startstop(struct aac_softstate *softs, struct aac_cmd *acp)
5751 5750 {
5752 5751 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5753 5752 struct aac_Container *cmd =
5754 5753 (struct aac_Container *)&acp->slotp->fibp->data[0];
5755 5754 union scsi_cdb *cdbp = (void *)acp->pkt->pkt_cdbp;
5756 5755
5757 5756 acp->fib_size = AAC_FIB_SIZEOF(struct aac_Container);
5758 5757
5759 5758 aac_cmd_fib_header(softs, acp, ContainerCommand);
5760 5759 bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE);
5761 5760 ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
5762 5761 ddi_put32(acc, &cmd->CTCommand.command, CT_PM_DRIVER_SUPPORT);
5763 5762 ddi_put32(acc, &cmd->CTCommand.param[0], cdbp->cdb_opaque[4] & 1 ? \
5764 5763 AAC_PM_DRIVERSUP_START_UNIT : AAC_PM_DRIVERSUP_STOP_UNIT);
5765 5764 ddi_put32(acc, &cmd->CTCommand.param[1],
5766 5765 ((struct aac_container *)acp->dvp)->cid);
5767 5766 ddi_put32(acc, &cmd->CTCommand.param[2], cdbp->cdb_opaque[1] & 1);
5768 5767 }
5769 5768
5770 5769 /*
5771 5770 * Init FIB for pass-through SCMD
5772 5771 */
5773 5772 static void
5774 5773 aac_cmd_fib_srb(struct aac_cmd *acp)
5775 5774 {
5776 5775 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5777 5776 struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
5778 5777 uint8_t *cdb;
5779 5778
5780 5779 ddi_put32(acc, &srb->function, SRBF_ExecuteScsi);
5781 5780 ddi_put32(acc, &srb->retry_limit, 0);
5782 5781 ddi_put32(acc, &srb->cdb_size, acp->cmdlen);
5783 5782 ddi_put32(acc, &srb->timeout, 0); /* use driver timeout */
5784 5783 if (acp->fibp == NULL) {
5785 5784 if (acp->flags & AAC_CMD_BUF_READ)
5786 5785 ddi_put32(acc, &srb->flags, SRB_DataIn);
5787 5786 else if (acp->flags & AAC_CMD_BUF_WRITE)
5788 5787 ddi_put32(acc, &srb->flags, SRB_DataOut);
5789 5788 ddi_put32(acc, &srb->channel,
5790 5789 ((struct aac_nondasd *)acp->dvp)->bus);
5791 5790 ddi_put32(acc, &srb->id, ((struct aac_nondasd *)acp->dvp)->tid);
5792 5791 ddi_put32(acc, &srb->lun, 0);
5793 5792 cdb = acp->pkt->pkt_cdbp;
5794 5793 } else {
5795 5794 struct aac_srb *srb0 = (struct aac_srb *)&acp->fibp->data[0];
5796 5795
5797 5796 ddi_put32(acc, &srb->flags, srb0->flags);
5798 5797 ddi_put32(acc, &srb->channel, srb0->channel);
5799 5798 ddi_put32(acc, &srb->id, srb0->id);
5800 5799 ddi_put32(acc, &srb->lun, srb0->lun);
5801 5800 cdb = srb0->cdb;
5802 5801 }
5803 5802 ddi_rep_put8(acc, cdb, srb->cdb, acp->cmdlen, DDI_DEV_AUTOINCR);
5804 5803 }
5805 5804
5806 5805 static void
5807 5806 aac_cmd_fib_scsi32(struct aac_softstate *softs, struct aac_cmd *acp)
5808 5807 {
5809 5808 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5810 5809 struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
5811 5810 struct aac_sg_entry *sgp;
5812 5811 struct aac_sge *sge;
5813 5812
5814 5813 acp->fib_size = sizeof (struct aac_fib_header) + \
5815 5814 sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
5816 5815 acp->left_cookien * sizeof (struct aac_sg_entry);
5817 5816
5818 5817 /* Fill FIB and SRB headers, and copy cdb */
5819 5818 aac_cmd_fib_header(softs, acp, ScsiPortCommand);
5820 5819 aac_cmd_fib_srb(acp);
5821 5820
5822 5821 /* Fill SG table */
5823 5822 ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
5824 5823 ddi_put32(acc, &srb->count, acp->bcount);
5825 5824
5826 5825 for (sge = &acp->sgt[0], sgp = &srb->sg.SgEntry[0];
5827 5826 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5828 5827 ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32);
5829 5828 ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5830 5829 }
5831 5830 }
5832 5831
5833 5832 static void
5834 5833 aac_cmd_fib_scsi64(struct aac_softstate *softs, struct aac_cmd *acp)
5835 5834 {
5836 5835 ddi_acc_handle_t acc = acp->slotp->fib_acc_handle;
5837 5836 struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0];
5838 5837 struct aac_sg_entry64 *sgp;
5839 5838 struct aac_sge *sge;
5840 5839
5841 5840 acp->fib_size = sizeof (struct aac_fib_header) + \
5842 5841 sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \
5843 5842 acp->left_cookien * sizeof (struct aac_sg_entry64);
5844 5843
5845 5844 /* Fill FIB and SRB headers, and copy cdb */
5846 5845 aac_cmd_fib_header(softs, acp, ScsiPortCommandU64);
5847 5846 aac_cmd_fib_srb(acp);
5848 5847
5849 5848 /* Fill SG table */
5850 5849 ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien);
5851 5850 ddi_put32(acc, &srb->count, acp->bcount);
5852 5851
5853 5852 for (sge = &acp->sgt[0],
5854 5853 sgp = &((struct aac_sg_table64 *)&srb->sg)->SgEntry64[0];
5855 5854 sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) {
5856 5855 ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo);
5857 5856 ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi);
5858 5857 ddi_put32(acc, &sgp->SgByteCount, sge->bcount);
5859 5858 }
5860 5859 }
5861 5860
5862 5861 static int
5863 5862 aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
5864 5863 {
5865 5864 struct aac_slot *slotp;
5866 5865
5867 5866 if (slotp = aac_get_slot(softs)) {
5868 5867 acp->slotp = slotp;
5869 5868 slotp->acp = acp;
5870 5869 acp->aac_cmd_fib(softs, acp);
5871 5870 (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0,
5872 5871 DDI_DMA_SYNC_FORDEV);
5873 5872 return (AACOK);
5874 5873 }
5875 5874 return (AACERR);
5876 5875 }
5877 5876
5878 5877 static int
5879 5878 aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp)
5880 5879 {
5881 5880 struct aac_device *dvp = acp->dvp;
5882 5881 int q = AAC_CMDQ(acp);
5883 5882
5884 5883 if (softs->bus_ncmds[q] < softs->bus_throttle[q]) {
5885 5884 if (dvp) {
5886 5885 if (dvp->ncmds[q] < dvp->throttle[q]) {
5887 5886 if (!(acp->flags & AAC_CMD_NTAG) ||
5888 5887 dvp->ncmds[q] == 0) {
5889 5888 return (aac_cmd_slot_bind(softs, acp));
5890 5889 }
5891 5890 ASSERT(q == AAC_CMDQ_ASYNC);
5892 5891 aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC,
5893 5892 AAC_THROTTLE_DRAIN);
5894 5893 }
5895 5894 } else {
5896 5895 return (aac_cmd_slot_bind(softs, acp));
5897 5896 }
5898 5897 }
5899 5898 return (AACERR);
5900 5899 }
5901 5900
5902 5901 static int
5903 5902 aac_sync_fib_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp)
5904 5903 {
5905 5904 struct aac_slot *slotp;
5906 5905
5907 5906 while (softs->sync_ac.slotp)
5908 5907 cv_wait(&softs->sync_fib_cv, &softs->io_lock);
5909 5908
5910 5909 if (slotp = aac_get_slot(softs)) {
5911 5910 ASSERT(acp->slotp == NULL);
5912 5911
5913 5912 acp->slotp = slotp;
5914 5913 slotp->acp = acp;
5915 5914 return (AACOK);
5916 5915 }
5917 5916 return (AACERR);
5918 5917 }
5919 5918
5920 5919 static void
5921 5920 aac_sync_fib_slot_release(struct aac_softstate *softs, struct aac_cmd *acp)
5922 5921 {
5923 5922 ASSERT(acp->slotp);
5924 5923
5925 5924 aac_release_slot(softs, acp->slotp);
5926 5925 acp->slotp->acp = NULL;
5927 5926 acp->slotp = NULL;
5928 5927
5929 5928 cv_signal(&softs->sync_fib_cv);
5930 5929 }
5931 5930
5932 5931 static void
5933 5932 aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp)
5934 5933 {
5935 5934 struct aac_slot *slotp = acp->slotp;
5936 5935 int q = AAC_CMDQ(acp);
5937 5936 int rval;
5938 5937
5939 5938 /* Set ac and pkt */
5940 5939 if (acp->pkt) { /* ac from ioctl has no pkt */
5941 5940 acp->pkt->pkt_state |=
5942 5941 STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD;
5943 5942 }
5944 5943 if (acp->timeout) /* 0 indicates no timeout */
5945 5944 acp->timeout += aac_timebase + aac_tick;
5946 5945
5947 5946 if (acp->dvp)
5948 5947 acp->dvp->ncmds[q]++;
5949 5948 softs->bus_ncmds[q]++;
5950 5949 aac_cmd_enqueue(&softs->q_busy, acp);
5951 5950
5952 5951 AACDB_PRINT_FIB(softs, slotp);
5953 5952
5954 5953 if (softs->flags & AAC_FLAGS_NEW_COMM) {
5955 5954 rval = aac_send_command(softs, slotp);
5956 5955 } else {
5957 5956 /*
5958 5957 * If fib can not be enqueued, the adapter is in an abnormal
5959 5958 * state, there will be no interrupt to us.
5960 5959 */
5961 5960 rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q,
5962 5961 slotp->fib_phyaddr, acp->fib_size);
5963 5962 }
5964 5963
5965 5964 if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS)
5966 5965 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED);
5967 5966
5968 5967 /*
5969 5968 * NOTE: We send command only when slots availabe, so should never
5970 5969 * reach here.
5971 5970 */
5972 5971 if (rval != AACOK) {
5973 5972 AACDB_PRINT(softs, CE_NOTE, "SCMD send failed");
5974 5973 if (acp->pkt) {
5975 5974 acp->pkt->pkt_state &= ~STATE_SENT_CMD;
5976 5975 aac_set_pkt_reason(softs, acp, CMD_INCOMPLETE, 0);
5977 5976 }
5978 5977 aac_end_io(softs, acp);
5979 5978 if (!(acp->flags & (AAC_CMD_NO_INTR | AAC_CMD_NO_CB)))
5980 5979 ddi_trigger_softintr(softs->softint_id);
5981 5980 }
5982 5981 }
5983 5982
5984 5983 static void
5985 5984 aac_start_waitq(struct aac_softstate *softs, struct aac_cmd_queue *q)
5986 5985 {
5987 5986 struct aac_cmd *acp, *next_acp;
5988 5987
5989 5988 /* Serve as many waiting io's as possible */
5990 5989 for (acp = q->q_head; acp; acp = next_acp) {
5991 5990 next_acp = acp->next;
5992 5991 if (aac_bind_io(softs, acp) == AACOK) {
5993 5992 aac_cmd_delete(q, acp);
5994 5993 aac_start_io(softs, acp);
5995 5994 }
5996 5995 if (softs->free_io_slot_head == NULL)
5997 5996 break;
5998 5997 }
5999 5998 }
6000 5999
6001 6000 static void
6002 6001 aac_start_waiting_io(struct aac_softstate *softs)
6003 6002 {
6004 6003 /*
6005 6004 * Sync FIB io is served before async FIB io so that io requests
6006 6005 * sent by interactive userland commands get responded asap.
6007 6006 */
6008 6007 if (softs->q_wait[AAC_CMDQ_SYNC].q_head)
6009 6008 aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_SYNC]);
6010 6009 if (softs->q_wait[AAC_CMDQ_ASYNC].q_head)
6011 6010 aac_start_waitq(softs, &softs->q_wait[AAC_CMDQ_ASYNC]);
6012 6011 }
6013 6012
6014 6013 static void
6015 6014 aac_drain_comp_q(struct aac_softstate *softs)
6016 6015 {
6017 6016 struct aac_cmd *acp;
6018 6017 struct scsi_pkt *pkt;
6019 6018
6020 6019 /*CONSTCOND*/
6021 6020 while (1) {
6022 6021 mutex_enter(&softs->q_comp_mutex);
6023 6022 acp = aac_cmd_dequeue(&softs->q_comp);
6024 6023 mutex_exit(&softs->q_comp_mutex);
6025 6024 if (acp != NULL) {
6026 6025 ASSERT(acp->pkt != NULL);
6027 6026 pkt = acp->pkt;
6028 6027
6029 6028 if (pkt->pkt_reason == CMD_CMPLT) {
6030 6029 /*
6031 6030 * Consistent packets need to be sync'ed first
6032 6031 */
6033 6032 if ((acp->flags & AAC_CMD_CONSISTENT) &&
6034 6033 (acp->flags & AAC_CMD_BUF_READ)) {
6035 6034 if (aac_dma_sync_ac(acp) != AACOK) {
6036 6035 ddi_fm_service_impact(
6037 6036 softs->devinfo_p,
6038 6037 DDI_SERVICE_UNAFFECTED);
6039 6038 pkt->pkt_reason = CMD_TRAN_ERR;
6040 6039 pkt->pkt_statistics = 0;
6041 6040 }
6042 6041 }
6043 6042 if ((aac_check_acc_handle(softs-> \
6044 6043 comm_space_acc_handle) != DDI_SUCCESS) ||
6045 6044 (aac_check_acc_handle(softs-> \
6046 6045 pci_mem_handle) != DDI_SUCCESS)) {
6047 6046 ddi_fm_service_impact(softs->devinfo_p,
6048 6047 DDI_SERVICE_UNAFFECTED);
6049 6048 ddi_fm_acc_err_clear(softs-> \
6050 6049 pci_mem_handle, DDI_FME_VER0);
6051 6050 pkt->pkt_reason = CMD_TRAN_ERR;
6052 6051 pkt->pkt_statistics = 0;
6053 6052 }
6054 6053 if (aac_check_dma_handle(softs-> \
6055 6054 comm_space_dma_handle) != DDI_SUCCESS) {
6056 6055 ddi_fm_service_impact(softs->devinfo_p,
6057 6056 DDI_SERVICE_UNAFFECTED);
6058 6057 pkt->pkt_reason = CMD_TRAN_ERR;
6059 6058 pkt->pkt_statistics = 0;
6060 6059 }
6061 6060 }
6062 6061 scsi_hba_pkt_comp(pkt);
6063 6062 } else {
6064 6063 break;
6065 6064 }
6066 6065 }
6067 6066 }
6068 6067
6069 6068 static int
6070 6069 aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp)
6071 6070 {
6072 6071 size_t rlen;
6073 6072 ddi_dma_cookie_t cookie;
6074 6073 uint_t cookien;
6075 6074
6076 6075 /* Allocate FIB dma resource */
6077 6076 if (ddi_dma_alloc_handle(
6078 6077 softs->devinfo_p,
6079 6078 &softs->addr_dma_attr,
6080 6079 DDI_DMA_SLEEP,
6081 6080 NULL,
6082 6081 &slotp->fib_dma_handle) != DDI_SUCCESS) {
6083 6082 AACDB_PRINT(softs, CE_WARN,
6084 6083 "Cannot alloc dma handle for slot fib area");
6085 6084 goto error;
6086 6085 }
6087 6086 if (ddi_dma_mem_alloc(
6088 6087 slotp->fib_dma_handle,
6089 6088 softs->aac_max_fib_size,
6090 6089 &softs->acc_attr,
6091 6090 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6092 6091 DDI_DMA_SLEEP,
6093 6092 NULL,
6094 6093 (caddr_t *)&slotp->fibp,
6095 6094 &rlen,
6096 6095 &slotp->fib_acc_handle) != DDI_SUCCESS) {
6097 6096 AACDB_PRINT(softs, CE_WARN,
6098 6097 "Cannot alloc mem for slot fib area");
6099 6098 goto error;
6100 6099 }
6101 6100 if (ddi_dma_addr_bind_handle(
6102 6101 slotp->fib_dma_handle,
6103 6102 NULL,
6104 6103 (caddr_t)slotp->fibp,
6105 6104 softs->aac_max_fib_size,
6106 6105 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6107 6106 DDI_DMA_SLEEP,
6108 6107 NULL,
6109 6108 &cookie,
6110 6109 &cookien) != DDI_DMA_MAPPED) {
6111 6110 AACDB_PRINT(softs, CE_WARN,
6112 6111 "dma bind failed for slot fib area");
6113 6112 goto error;
6114 6113 }
6115 6114
6116 6115 /* Check dma handles allocated in fib attach */
6117 6116 if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) {
6118 6117 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
6119 6118 goto error;
6120 6119 }
6121 6120
6122 6121 /* Check acc handles allocated in fib attach */
6123 6122 if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) {
6124 6123 ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST);
6125 6124 goto error;
6126 6125 }
6127 6126
6128 6127 slotp->fib_phyaddr = cookie.dmac_laddress;
6129 6128 return (AACOK);
6130 6129
6131 6130 error:
6132 6131 if (slotp->fib_acc_handle) {
6133 6132 ddi_dma_mem_free(&slotp->fib_acc_handle);
6134 6133 slotp->fib_acc_handle = NULL;
6135 6134 }
6136 6135 if (slotp->fib_dma_handle) {
6137 6136 ddi_dma_free_handle(&slotp->fib_dma_handle);
6138 6137 slotp->fib_dma_handle = NULL;
6139 6138 }
6140 6139 return (AACERR);
6141 6140 }
6142 6141
6143 6142 static void
6144 6143 aac_free_fib(struct aac_slot *slotp)
6145 6144 {
6146 6145 (void) ddi_dma_unbind_handle(slotp->fib_dma_handle);
6147 6146 ddi_dma_mem_free(&slotp->fib_acc_handle);
6148 6147 slotp->fib_acc_handle = NULL;
6149 6148 ddi_dma_free_handle(&slotp->fib_dma_handle);
6150 6149 slotp->fib_dma_handle = NULL;
6151 6150 slotp->fib_phyaddr = 0;
6152 6151 }
6153 6152
6154 6153 static void
6155 6154 aac_alloc_fibs(struct aac_softstate *softs)
6156 6155 {
6157 6156 int i;
6158 6157 struct aac_slot *slotp;
6159 6158
6160 6159 for (i = 0; i < softs->total_slots &&
6161 6160 softs->total_fibs < softs->total_slots; i++) {
6162 6161 slotp = &(softs->io_slot[i]);
6163 6162 if (slotp->fib_phyaddr)
6164 6163 continue;
6165 6164 if (aac_alloc_fib(softs, slotp) != AACOK)
6166 6165 break;
6167 6166
6168 6167 /* Insert the slot to the free slot list */
6169 6168 aac_release_slot(softs, slotp);
6170 6169 softs->total_fibs++;
6171 6170 }
6172 6171 }
6173 6172
6174 6173 static void
6175 6174 aac_destroy_fibs(struct aac_softstate *softs)
6176 6175 {
6177 6176 struct aac_slot *slotp;
6178 6177
6179 6178 while ((slotp = softs->free_io_slot_head) != NULL) {
6180 6179 ASSERT(slotp->fib_phyaddr);
6181 6180 softs->free_io_slot_head = slotp->next;
6182 6181 aac_free_fib(slotp);
6183 6182 ASSERT(slotp->index == (slotp - softs->io_slot));
6184 6183 softs->total_fibs--;
6185 6184 }
6186 6185 ASSERT(softs->total_fibs == 0);
6187 6186 }
6188 6187
6189 6188 static int
6190 6189 aac_create_slots(struct aac_softstate *softs)
6191 6190 {
6192 6191 int i;
6193 6192
6194 6193 softs->total_slots = softs->aac_max_fibs;
6195 6194 softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \
6196 6195 softs->total_slots, KM_SLEEP);
6197 6196 if (softs->io_slot == NULL) {
6198 6197 AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot");
6199 6198 return (AACERR);
6200 6199 }
6201 6200 for (i = 0; i < softs->total_slots; i++)
6202 6201 softs->io_slot[i].index = i;
6203 6202 softs->free_io_slot_head = NULL;
6204 6203 softs->total_fibs = 0;
6205 6204 return (AACOK);
6206 6205 }
6207 6206
6208 6207 static void
6209 6208 aac_destroy_slots(struct aac_softstate *softs)
6210 6209 {
6211 6210 ASSERT(softs->free_io_slot_head == NULL);
6212 6211
6213 6212 kmem_free(softs->io_slot, sizeof (struct aac_slot) * \
6214 6213 softs->total_slots);
6215 6214 softs->io_slot = NULL;
6216 6215 softs->total_slots = 0;
6217 6216 }
6218 6217
6219 6218 struct aac_slot *
6220 6219 aac_get_slot(struct aac_softstate *softs)
6221 6220 {
6222 6221 struct aac_slot *slotp;
6223 6222
6224 6223 if ((slotp = softs->free_io_slot_head) != NULL) {
6225 6224 softs->free_io_slot_head = slotp->next;
6226 6225 slotp->next = NULL;
6227 6226 }
6228 6227 return (slotp);
6229 6228 }
6230 6229
6231 6230 static void
6232 6231 aac_release_slot(struct aac_softstate *softs, struct aac_slot *slotp)
6233 6232 {
6234 6233 ASSERT((slotp->index >= 0) && (slotp->index < softs->total_slots));
6235 6234 ASSERT(slotp == &softs->io_slot[slotp->index]);
6236 6235
6237 6236 slotp->acp = NULL;
6238 6237 slotp->next = softs->free_io_slot_head;
6239 6238 softs->free_io_slot_head = slotp;
6240 6239 }
6241 6240
6242 6241 int
6243 6242 aac_do_io(struct aac_softstate *softs, struct aac_cmd *acp)
6244 6243 {
6245 6244 if (aac_bind_io(softs, acp) == AACOK)
6246 6245 aac_start_io(softs, acp);
6247 6246 else
6248 6247 aac_cmd_enqueue(&softs->q_wait[AAC_CMDQ(acp)], acp);
6249 6248
6250 6249 if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR)))
6251 6250 return (TRAN_ACCEPT);
6252 6251 /*
6253 6252 * Because sync FIB is always 512 bytes and used for critical
6254 6253 * functions, async FIB is used for poll IO.
6255 6254 */
6256 6255 if (acp->flags & AAC_CMD_NO_INTR) {
6257 6256 if (aac_do_poll_io(softs, acp) == AACOK)
6258 6257 return (TRAN_ACCEPT);
6259 6258 } else {
6260 6259 if (aac_do_sync_io(softs, acp) == AACOK)
6261 6260 return (TRAN_ACCEPT);
6262 6261 }
6263 6262 return (TRAN_BADPKT);
6264 6263 }
6265 6264
6266 6265 static int
6267 6266 aac_do_poll_io(struct aac_softstate *softs, struct aac_cmd *acp)
6268 6267 {
6269 6268 int (*intr_handler)(struct aac_softstate *);
6270 6269
6271 6270 /*
6272 6271 * Interrupt is disabled, we have to poll the adapter by ourselves.
6273 6272 */
6274 6273 intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ?
6275 6274 aac_process_intr_new : aac_process_intr_old;
6276 6275 while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) {
6277 6276 int i = AAC_POLL_TIME * 1000;
6278 6277
6279 6278 AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i);
6280 6279 if (i == 0)
6281 6280 aac_cmd_timeout(softs, acp);
6282 6281 }
6283 6282
6284 6283 ddi_trigger_softintr(softs->softint_id);
6285 6284
6286 6285 if ((acp->flags & AAC_CMD_CMPLT) && !(acp->flags & AAC_CMD_ERR))
6287 6286 return (AACOK);
6288 6287 return (AACERR);
6289 6288 }
6290 6289
6291 6290 static int
6292 6291 aac_do_sync_io(struct aac_softstate *softs, struct aac_cmd *acp)
6293 6292 {
6294 6293 ASSERT(softs && acp);
6295 6294
6296 6295 while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT)))
6297 6296 cv_wait(&softs->event, &softs->io_lock);
6298 6297
6299 6298 if (acp->flags & AAC_CMD_CMPLT)
6300 6299 return (AACOK);
6301 6300 return (AACERR);
6302 6301 }
6303 6302
6304 6303 static int
6305 6304 aac_dma_sync_ac(struct aac_cmd *acp)
6306 6305 {
6307 6306 if (acp->buf_dma_handle) {
6308 6307 if (acp->flags & AAC_CMD_BUF_WRITE) {
6309 6308 if (acp->abp != NULL)
6310 6309 ddi_rep_put8(acp->abh,
6311 6310 (uint8_t *)acp->bp->b_un.b_addr,
6312 6311 (uint8_t *)acp->abp, acp->bp->b_bcount,
6313 6312 DDI_DEV_AUTOINCR);
6314 6313 (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
6315 6314 DDI_DMA_SYNC_FORDEV);
6316 6315 } else {
6317 6316 (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0,
6318 6317 DDI_DMA_SYNC_FORCPU);
6319 6318 if (aac_check_dma_handle(acp->buf_dma_handle) !=
6320 6319 DDI_SUCCESS)
6321 6320 return (AACERR);
6322 6321 if (acp->abp != NULL)
6323 6322 ddi_rep_get8(acp->abh,
6324 6323 (uint8_t *)acp->bp->b_un.b_addr,
6325 6324 (uint8_t *)acp->abp, acp->bp->b_bcount,
6326 6325 DDI_DEV_AUTOINCR);
6327 6326 }
6328 6327 }
6329 6328 return (AACOK);
6330 6329 }
6331 6330
6332 6331 /*
6333 6332 * Copy AIF from adapter to the empty AIF slot and inform AIF threads
6334 6333 */
6335 6334 static void
6336 6335 aac_save_aif(struct aac_softstate *softs, ddi_acc_handle_t acc,
6337 6336 struct aac_fib *fibp0, int fib_size0)
6338 6337 {
6339 6338 struct aac_fib *fibp; /* FIB in AIF queue */
6340 6339 int fib_size;
6341 6340 uint16_t fib_command;
6342 6341 int current, next;
6343 6342
6344 6343 /* Ignore non AIF messages */
6345 6344 fib_command = ddi_get16(acc, &fibp0->Header.Command);
6346 6345 if (fib_command != AifRequest) {
6347 6346 cmn_err(CE_WARN, "!Unknown command from controller");
6348 6347 return;
6349 6348 }
6350 6349
6351 6350 mutex_enter(&softs->aifq_mutex);
6352 6351
6353 6352 /* Save AIF */
6354 6353 fibp = &softs->aifq[softs->aifq_idx].d;
6355 6354 fib_size = (fib_size0 > AAC_FIB_SIZE) ? AAC_FIB_SIZE : fib_size0;
6356 6355 ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0, fib_size,
6357 6356 DDI_DEV_AUTOINCR);
6358 6357
6359 6358 if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) {
6360 6359 ddi_fm_service_impact(softs->devinfo_p,
6361 6360 DDI_SERVICE_UNAFFECTED);
6362 6361 mutex_exit(&softs->aifq_mutex);
6363 6362 return;
6364 6363 }
6365 6364
6366 6365 AACDB_PRINT_AIF(softs, (struct aac_aif_command *)&fibp->data[0]);
6367 6366
6368 6367 /* Modify AIF contexts */
6369 6368 current = softs->aifq_idx;
6370 6369 next = (current + 1) % AAC_AIFQ_LENGTH;
6371 6370 if (next == 0) {
6372 6371 struct aac_fib_context *ctx_p;
6373 6372
6374 6373 softs->aifq_wrap = 1;
6375 6374 for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) {
6376 6375 if (next == ctx_p->ctx_idx) {
6377 6376 ctx_p->ctx_flags |= AAC_CTXFLAG_FILLED;
6378 6377 } else if (current == ctx_p->ctx_idx &&
6379 6378 (ctx_p->ctx_flags & AAC_CTXFLAG_FILLED)) {
6380 6379 ctx_p->ctx_idx = next;
6381 6380 ctx_p->ctx_overrun++;
6382 6381 }
6383 6382 }
6384 6383 }
6385 6384 softs->aifq_idx = next;
6386 6385
6387 6386 /* Wakeup AIF threads */
6388 6387 cv_broadcast(&softs->aifq_cv);
6389 6388 mutex_exit(&softs->aifq_mutex);
6390 6389
6391 6390 /* Wakeup event thread to handle aif */
6392 6391 aac_event_disp(softs, AAC_EVENT_AIF);
6393 6392 }
6394 6393
6395 6394 static int
6396 6395 aac_return_aif_common(struct aac_softstate *softs, struct aac_fib_context *ctx,
6397 6396 struct aac_fib **fibpp)
6398 6397 {
6399 6398 int current;
6400 6399
6401 6400 current = ctx->ctx_idx;
6402 6401 if (current == softs->aifq_idx &&
6403 6402 !(ctx->ctx_flags & AAC_CTXFLAG_FILLED))
6404 6403 return (EAGAIN); /* Empty */
6405 6404
6406 6405 *fibpp = &softs->aifq[current].d;
6407 6406
6408 6407 ctx->ctx_flags &= ~AAC_CTXFLAG_FILLED;
6409 6408 ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH;
6410 6409 return (0);
6411 6410 }
6412 6411
6413 6412 int
6414 6413 aac_return_aif(struct aac_softstate *softs, struct aac_fib_context *ctx,
6415 6414 struct aac_fib **fibpp)
6416 6415 {
6417 6416 int rval;
6418 6417
6419 6418 mutex_enter(&softs->aifq_mutex);
6420 6419 rval = aac_return_aif_common(softs, ctx, fibpp);
6421 6420 mutex_exit(&softs->aifq_mutex);
6422 6421 return (rval);
6423 6422 }
6424 6423
6425 6424 int
6426 6425 aac_return_aif_wait(struct aac_softstate *softs, struct aac_fib_context *ctx,
6427 6426 struct aac_fib **fibpp)
6428 6427 {
6429 6428 int rval;
6430 6429
6431 6430 mutex_enter(&softs->aifq_mutex);
6432 6431 rval = aac_return_aif_common(softs, ctx, fibpp);
6433 6432 if (rval == EAGAIN) {
6434 6433 AACDB_PRINT(softs, CE_NOTE, "Waiting for AIF");
6435 6434 rval = cv_wait_sig(&softs->aifq_cv, &softs->aifq_mutex);
6436 6435 }
6437 6436 mutex_exit(&softs->aifq_mutex);
6438 6437 return ((rval > 0) ? 0 : EINTR);
6439 6438 }
6440 6439
6441 6440 /*
6442 6441 * The following function comes from Adaptec:
6443 6442 *
6444 6443 * When driver sees a particular event that means containers are changed, it
6445 6444 * will rescan containers. However a change may not be complete until some
6446 6445 * other event is received. For example, creating or deleting an array will
6447 6446 * incur as many as six AifEnConfigChange events which would generate six
6448 6447 * container rescans. To diminish rescans, driver set a flag to wait for
6449 6448 * another particular event. When sees that events come in, it will do rescan.
6450 6449 */
6451 6450 static int
6452 6451 aac_handle_aif(struct aac_softstate *softs, struct aac_aif_command *aif)
6453 6452 {
6454 6453 ddi_acc_handle_t acc = softs->comm_space_acc_handle;
6455 6454 int en_type;
6456 6455 int devcfg_needed;
6457 6456 int cid;
6458 6457 uint32_t bus_id, tgt_id;
6459 6458 enum aac_cfg_event event = AAC_CFG_NULL_EXIST;
6460 6459
6461 6460 devcfg_needed = 0;
6462 6461 en_type = LE_32((uint32_t)aif->data.EN.type);
6463 6462
6464 6463 switch (LE_32((uint32_t)aif->command)) {
6465 6464 case AifCmdDriverNotify: {
6466 6465 cid = LE_32(aif->data.EN.data.ECC.container[0]);
6467 6466
6468 6467 switch (en_type) {
6469 6468 case AifDenMorphComplete:
6470 6469 case AifDenVolumeExtendComplete:
6471 6470 if (AAC_DEV_IS_VALID(&softs->containers[cid].dev))
6472 6471 softs->devcfg_wait_on = AifEnConfigChange;
6473 6472 break;
6474 6473 }
6475 6474 if (softs->devcfg_wait_on == en_type)
6476 6475 devcfg_needed = 1;
6477 6476 break;
6478 6477 }
6479 6478
6480 6479 case AifCmdEventNotify:
6481 6480 cid = LE_32(aif->data.EN.data.ECC.container[0]);
6482 6481 switch (en_type) {
6483 6482 case AifEnAddContainer:
6484 6483 case AifEnDeleteContainer:
6485 6484 softs->devcfg_wait_on = AifEnConfigChange;
6486 6485 break;
6487 6486 case AifEnContainerChange:
6488 6487 if (!softs->devcfg_wait_on)
6489 6488 softs->devcfg_wait_on = AifEnConfigChange;
6490 6489 break;
6491 6490 case AifEnContainerEvent:
6492 6491 if (ddi_get32(acc, &aif-> \
6493 6492 data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE)
6494 6493 devcfg_needed = 1;
6495 6494 break;
6496 6495 case AifEnAddJBOD:
6497 6496 if (!(softs->flags & AAC_FLAGS_JBOD))
6498 6497 return (AACERR);
6499 6498 event = AAC_CFG_ADD;
6500 6499 bus_id = (cid >> 24) & 0xf;
6501 6500 tgt_id = cid & 0xffff;
6502 6501 break;
6503 6502 case AifEnDeleteJBOD:
6504 6503 if (!(softs->flags & AAC_FLAGS_JBOD))
6505 6504 return (AACERR);
6506 6505 event = AAC_CFG_DELETE;
6507 6506 bus_id = (cid >> 24) & 0xf;
6508 6507 tgt_id = cid & 0xffff;
6509 6508 break;
6510 6509 }
6511 6510 if (softs->devcfg_wait_on == en_type)
6512 6511 devcfg_needed = 1;
6513 6512 break;
6514 6513
6515 6514 case AifCmdJobProgress:
6516 6515 if (LE_32((uint32_t)aif->data.PR[0].jd.type) == AifJobCtrZero) {
6517 6516 int pr_status;
6518 6517 uint32_t pr_ftick, pr_ctick;
6519 6518
6520 6519 pr_status = LE_32((uint32_t)aif->data.PR[0].status);
6521 6520 pr_ctick = LE_32(aif->data.PR[0].currentTick);
6522 6521 pr_ftick = LE_32(aif->data.PR[0].finalTick);
6523 6522
6524 6523 if ((pr_ctick == pr_ftick) ||
6525 6524 (pr_status == AifJobStsSuccess))
6526 6525 softs->devcfg_wait_on = AifEnContainerChange;
6527 6526 else if ((pr_ctick == 0) &&
6528 6527 (pr_status == AifJobStsRunning))
6529 6528 softs->devcfg_wait_on = AifEnContainerChange;
6530 6529 }
6531 6530 break;
6532 6531 }
6533 6532
6534 6533 if (devcfg_needed) {
6535 6534 softs->devcfg_wait_on = 0;
6536 6535 (void) aac_probe_containers(softs);
6537 6536 }
6538 6537
6539 6538 if (event != AAC_CFG_NULL_EXIST) {
6540 6539 ASSERT(en_type == AifEnAddJBOD || en_type == AifEnDeleteJBOD);
6541 6540 (void) aac_probe_jbod(softs,
6542 6541 AAC_P2VTGT(softs, bus_id, tgt_id), event);
6543 6542 }
6544 6543 return (AACOK);
6545 6544 }
6546 6545
6547 6546
6548 6547 /*
6549 6548 * Check and handle AIF events
6550 6549 */
6551 6550 static void
6552 6551 aac_aif_event(struct aac_softstate *softs)
6553 6552 {
6554 6553 struct aac_fib *fibp;
6555 6554
6556 6555 /*CONSTCOND*/
6557 6556 while (1) {
6558 6557 if (aac_return_aif(softs, &softs->aifctx, &fibp) != 0)
6559 6558 break; /* No more AIFs to handle, end loop */
6560 6559
6561 6560 /* AIF overrun, array create/delete may missed. */
6562 6561 if (softs->aifctx.ctx_overrun) {
6563 6562 softs->aifctx.ctx_overrun = 0;
6564 6563 }
6565 6564
6566 6565 /* AIF received, handle it */
6567 6566 struct aac_aif_command *aifp =
6568 6567 (struct aac_aif_command *)&fibp->data[0];
6569 6568 uint32_t aif_command = LE_32((uint32_t)aifp->command);
6570 6569
6571 6570 if (aif_command == AifCmdDriverNotify ||
6572 6571 aif_command == AifCmdEventNotify ||
6573 6572 aif_command == AifCmdJobProgress)
6574 6573 (void) aac_handle_aif(softs, aifp);
6575 6574 }
6576 6575 }
6577 6576
6578 6577 /*
6579 6578 * Timeout recovery
6580 6579 */
6581 6580 /*ARGSUSED*/
6582 6581 static void
6583 6582 aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp)
6584 6583 {
6585 6584 #ifdef DEBUG
6586 6585 acp->fib_flags |= AACDB_FLAGS_FIB_TIMEOUT;
6587 6586 AACDB_PRINT(softs, CE_WARN, "acp %p timed out", acp);
6588 6587 AACDB_PRINT_FIB(softs, acp->slotp);
6589 6588 #endif
6590 6589
6591 6590 /*
6592 6591 * Besides the firmware in unhealthy state, an overloaded
6593 6592 * adapter may also incur pkt timeout.
6594 6593 * There is a chance for an adapter with a slower IOP to take
6595 6594 * longer than 60 seconds to process the commands, such as when
6596 6595 * to perform IOs. So the adapter is doing a build on a RAID-5
6597 6596 * while being required longer completion times should be
6598 6597 * tolerated.
6599 6598 */
6600 6599 switch (aac_do_reset(softs)) {
6601 6600 case AAC_IOP_RESET_SUCCEED:
6602 6601 aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, CMD_RESET);
6603 6602 aac_start_waiting_io(softs);
6604 6603 break;
6605 6604 case AAC_IOP_RESET_FAILED:
6606 6605 /* Abort all waiting cmds when adapter is dead */
6607 6606 aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_TIMEOUT);
6608 6607 break;
6609 6608 case AAC_IOP_RESET_ABNORMAL:
6610 6609 aac_start_waiting_io(softs);
6611 6610 }
6612 6611 }
6613 6612
6614 6613 /*
6615 6614 * The following function comes from Adaptec:
6616 6615 *
6617 6616 * Time sync. command added to synchronize time with firmware every 30
6618 6617 * minutes (required for correct AIF timestamps etc.)
6619 6618 */
6620 6619 static void
6621 6620 aac_sync_tick(struct aac_softstate *softs)
6622 6621 {
6623 6622 ddi_acc_handle_t acc;
6624 6623 int rval;
6625 6624
6626 6625 mutex_enter(&softs->time_mutex);
6627 6626 ASSERT(softs->time_sync <= softs->timebase);
6628 6627 softs->time_sync = 0;
6629 6628 mutex_exit(&softs->time_mutex);
6630 6629
6631 6630 /* Time sync. with firmware every AAC_SYNC_TICK */
6632 6631 (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac);
6633 6632 acc = softs->sync_ac.slotp->fib_acc_handle;
6634 6633
6635 6634 ddi_put32(acc, (void *)&softs->sync_ac.slotp->fibp->data[0],
6636 6635 ddi_get_time());
6637 6636 rval = aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t));
6638 6637 aac_sync_fib_slot_release(softs, &softs->sync_ac);
6639 6638
6640 6639 mutex_enter(&softs->time_mutex);
6641 6640 softs->time_sync = softs->timebase;
6642 6641 if (rval != AACOK)
6643 6642 /* retry shortly */
6644 6643 softs->time_sync += aac_tick << 1;
6645 6644 else
6646 6645 softs->time_sync += AAC_SYNC_TICK;
6647 6646 mutex_exit(&softs->time_mutex);
6648 6647 }
6649 6648
6650 6649 /*
6651 6650 * Timeout checking and handling
6652 6651 */
6653 6652 static void
6654 6653 aac_daemon(struct aac_softstate *softs)
6655 6654 {
6656 6655 int time_out; /* set if timeout happened */
6657 6656 int time_adjust;
6658 6657 uint32_t softs_timebase;
6659 6658
6660 6659 mutex_enter(&softs->time_mutex);
6661 6660 ASSERT(softs->time_out <= softs->timebase);
6662 6661 softs->time_out = 0;
6663 6662 softs_timebase = softs->timebase;
6664 6663 mutex_exit(&softs->time_mutex);
6665 6664
6666 6665 /* Check slots for timeout pkts */
6667 6666 time_adjust = 0;
6668 6667 do {
6669 6668 struct aac_cmd *acp;
6670 6669
6671 6670 time_out = 0;
6672 6671 for (acp = softs->q_busy.q_head; acp; acp = acp->next) {
6673 6672 if (acp->timeout == 0)
6674 6673 continue;
6675 6674
6676 6675 /*
6677 6676 * If timeout happened, update outstanding cmds
6678 6677 * to be checked later again.
6679 6678 */
6680 6679 if (time_adjust) {
6681 6680 acp->timeout += time_adjust;
6682 6681 continue;
6683 6682 }
6684 6683
6685 6684 if (acp->timeout <= softs_timebase) {
6686 6685 aac_cmd_timeout(softs, acp);
6687 6686 time_out = 1;
6688 6687 time_adjust = aac_tick * drv_usectohz(1000000);
6689 6688 break; /* timeout happened */
6690 6689 } else {
6691 6690 break; /* no timeout */
6692 6691 }
6693 6692 }
6694 6693 } while (time_out);
6695 6694
6696 6695 mutex_enter(&softs->time_mutex);
6697 6696 softs->time_out = softs->timebase + aac_tick;
6698 6697 mutex_exit(&softs->time_mutex);
6699 6698 }
6700 6699
6701 6700 /*
6702 6701 * The event thread handles various tasks serially for the other parts of
6703 6702 * the driver, so that they can run fast.
6704 6703 */
6705 6704 static void
6706 6705 aac_event_thread(struct aac_softstate *softs)
6707 6706 {
6708 6707 int run = 1;
6709 6708
6710 6709 DBCALLED(softs, 1);
6711 6710
6712 6711 mutex_enter(&softs->ev_lock);
6713 6712 while (run) {
6714 6713 int events;
6715 6714
6716 6715 if ((events = softs->events) == 0) {
6717 6716 cv_wait(&softs->event_disp_cv, &softs->ev_lock);
6718 6717 events = softs->events;
6719 6718 }
6720 6719 softs->events = 0;
6721 6720 mutex_exit(&softs->ev_lock);
6722 6721
6723 6722 mutex_enter(&softs->io_lock);
6724 6723 if ((softs->state & AAC_STATE_RUN) &&
6725 6724 (softs->state & AAC_STATE_DEAD) == 0) {
6726 6725 if (events & AAC_EVENT_TIMEOUT)
6727 6726 aac_daemon(softs);
6728 6727 if (events & AAC_EVENT_SYNCTICK)
6729 6728 aac_sync_tick(softs);
6730 6729 if (events & AAC_EVENT_AIF)
6731 6730 aac_aif_event(softs);
6732 6731 } else {
6733 6732 run = 0;
6734 6733 }
6735 6734 mutex_exit(&softs->io_lock);
6736 6735
6737 6736 mutex_enter(&softs->ev_lock);
6738 6737 }
6739 6738
6740 6739 cv_signal(&softs->event_wait_cv);
6741 6740 mutex_exit(&softs->ev_lock);
6742 6741 }
6743 6742
6744 6743 /*
6745 6744 * Internal timer. It is only responsbile for time counting and report time
6746 6745 * related events. Events handling is done by aac_event_thread(), so that
6747 6746 * the timer itself could be as precise as possible.
6748 6747 */
6749 6748 static void
6750 6749 aac_timer(void *arg)
6751 6750 {
6752 6751 struct aac_softstate *softs = arg;
6753 6752 int events = 0;
6754 6753
6755 6754 mutex_enter(&softs->time_mutex);
6756 6755
6757 6756 /* If timer is being stopped, exit */
6758 6757 if (softs->timeout_id) {
6759 6758 softs->timeout_id = timeout(aac_timer, (void *)softs,
6760 6759 (aac_tick * drv_usectohz(1000000)));
6761 6760 } else {
6762 6761 mutex_exit(&softs->time_mutex);
6763 6762 return;
6764 6763 }
6765 6764
6766 6765 /* Time counting */
6767 6766 softs->timebase += aac_tick;
6768 6767
6769 6768 /* Check time related events */
6770 6769 if (softs->time_out && softs->time_out <= softs->timebase)
6771 6770 events |= AAC_EVENT_TIMEOUT;
6772 6771 if (softs->time_sync && softs->time_sync <= softs->timebase)
6773 6772 events |= AAC_EVENT_SYNCTICK;
6774 6773
6775 6774 mutex_exit(&softs->time_mutex);
6776 6775
6777 6776 if (events)
6778 6777 aac_event_disp(softs, events);
6779 6778 }
6780 6779
6781 6780 /*
6782 6781 * Dispatch events to daemon thread for handling
6783 6782 */
6784 6783 static void
6785 6784 aac_event_disp(struct aac_softstate *softs, int events)
6786 6785 {
6787 6786 mutex_enter(&softs->ev_lock);
6788 6787 softs->events |= events;
6789 6788 cv_broadcast(&softs->event_disp_cv);
6790 6789 mutex_exit(&softs->ev_lock);
6791 6790 }
6792 6791
6793 6792 /*
6794 6793 * Architecture dependent functions
6795 6794 */
6796 6795 static int
6797 6796 aac_rx_get_fwstatus(struct aac_softstate *softs)
6798 6797 {
6799 6798 return (PCI_MEM_GET32(softs, AAC_OMR0));
6800 6799 }
6801 6800
6802 6801 static int
6803 6802 aac_rx_get_mailbox(struct aac_softstate *softs, int mb)
6804 6803 {
6805 6804 return (PCI_MEM_GET32(softs, AAC_RX_MAILBOX + mb * 4));
6806 6805 }
6807 6806
6808 6807 static void
6809 6808 aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
6810 6809 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
6811 6810 {
6812 6811 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX, cmd);
6813 6812 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 4, arg0);
6814 6813 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 8, arg1);
6815 6814 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 12, arg2);
6816 6815 PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 16, arg3);
6817 6816 }
6818 6817
6819 6818 static int
6820 6819 aac_rkt_get_fwstatus(struct aac_softstate *softs)
6821 6820 {
6822 6821 return (PCI_MEM_GET32(softs, AAC_OMR0));
6823 6822 }
6824 6823
6825 6824 static int
6826 6825 aac_rkt_get_mailbox(struct aac_softstate *softs, int mb)
6827 6826 {
6828 6827 return (PCI_MEM_GET32(softs, AAC_RKT_MAILBOX + mb *4));
6829 6828 }
6830 6829
6831 6830 static void
6832 6831 aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd,
6833 6832 uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
6834 6833 {
6835 6834 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX, cmd);
6836 6835 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 4, arg0);
6837 6836 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 8, arg1);
6838 6837 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 12, arg2);
6839 6838 PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 16, arg3);
6840 6839 }
6841 6840
6842 6841 /*
6843 6842 * cb_ops functions
6844 6843 */
6845 6844 static int
6846 6845 aac_open(dev_t *devp, int flag, int otyp, cred_t *cred)
6847 6846 {
6848 6847 struct aac_softstate *softs;
6849 6848 int minor0, minor;
6850 6849 int instance;
6851 6850
6852 6851 DBCALLED(NULL, 2);
6853 6852
6854 6853 if (otyp != OTYP_BLK && otyp != OTYP_CHR)
6855 6854 return (EINVAL);
6856 6855
6857 6856 minor0 = getminor(*devp);
6858 6857 minor = AAC_SCSA_MINOR(minor0);
6859 6858
6860 6859 if (AAC_IS_SCSA_NODE(minor))
6861 6860 return (scsi_hba_open(devp, flag, otyp, cred));
6862 6861
6863 6862 instance = MINOR2INST(minor0);
6864 6863 if (instance >= AAC_MAX_ADAPTERS)
6865 6864 return (ENXIO);
6866 6865
6867 6866 softs = ddi_get_soft_state(aac_softstatep, instance);
6868 6867 if (softs == NULL)
6869 6868 return (ENXIO);
6870 6869
6871 6870 return (0);
6872 6871 }
6873 6872
6874 6873 /*ARGSUSED*/
6875 6874 static int
6876 6875 aac_close(dev_t dev, int flag, int otyp, cred_t *cred)
6877 6876 {
6878 6877 int minor0, minor;
6879 6878 int instance;
6880 6879
6881 6880 DBCALLED(NULL, 2);
6882 6881
6883 6882 if (otyp != OTYP_BLK && otyp != OTYP_CHR)
6884 6883 return (EINVAL);
6885 6884
6886 6885 minor0 = getminor(dev);
6887 6886 minor = AAC_SCSA_MINOR(minor0);
6888 6887
6889 6888 if (AAC_IS_SCSA_NODE(minor))
6890 6889 return (scsi_hba_close(dev, flag, otyp, cred));
6891 6890
6892 6891 instance = MINOR2INST(minor0);
6893 6892 if (instance >= AAC_MAX_ADAPTERS)
6894 6893 return (ENXIO);
6895 6894
6896 6895 return (0);
6897 6896 }
6898 6897
6899 6898 static int
6900 6899 aac_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p,
6901 6900 int *rval_p)
6902 6901 {
6903 6902 struct aac_softstate *softs;
6904 6903 int minor0, minor;
6905 6904 int instance;
6906 6905
6907 6906 DBCALLED(NULL, 2);
6908 6907
6909 6908 if (drv_priv(cred_p) != 0)
6910 6909 return (EPERM);
6911 6910
6912 6911 minor0 = getminor(dev);
6913 6912 minor = AAC_SCSA_MINOR(minor0);
6914 6913
6915 6914 if (AAC_IS_SCSA_NODE(minor))
6916 6915 return (scsi_hba_ioctl(dev, cmd, arg, flag, cred_p, rval_p));
6917 6916
6918 6917 instance = MINOR2INST(minor0);
6919 6918 if (instance < AAC_MAX_ADAPTERS) {
6920 6919 softs = ddi_get_soft_state(aac_softstatep, instance);
6921 6920 return (aac_do_ioctl(softs, dev, cmd, arg, flag));
6922 6921 }
6923 6922 return (ENXIO);
6924 6923 }
6925 6924
6926 6925 /*
6927 6926 * The IO fault service error handling callback function
6928 6927 */
6929 6928 /*ARGSUSED*/
6930 6929 static int
6931 6930 aac_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
6932 6931 {
6933 6932 /*
6934 6933 * as the driver can always deal with an error in any dma or
6935 6934 * access handle, we can just return the fme_status value.
6936 6935 */
6937 6936 pci_ereport_post(dip, err, NULL);
6938 6937 return (err->fme_status);
6939 6938 }
6940 6939
6941 6940 /*
6942 6941 * aac_fm_init - initialize fma capabilities and register with IO
6943 6942 * fault services.
6944 6943 */
6945 6944 static void
6946 6945 aac_fm_init(struct aac_softstate *softs)
6947 6946 {
6948 6947 /*
6949 6948 * Need to change iblock to priority for new MSI intr
6950 6949 */
6951 6950 ddi_iblock_cookie_t fm_ibc;
6952 6951
6953 6952 softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p,
6954 6953 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
6955 6954 DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
6956 6955 DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
6957 6956
6958 6957 /* Only register with IO Fault Services if we have some capability */
6959 6958 if (softs->fm_capabilities) {
6960 6959 /* Adjust access and dma attributes for FMA */
6961 6960 softs->reg_attr.devacc_attr_access = DDI_FLAGERR_ACC;
6962 6961 softs->addr_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
6963 6962 softs->buf_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
6964 6963
6965 6964 /*
6966 6965 * Register capabilities with IO Fault Services.
6967 6966 * fm_capabilities will be updated to indicate
6968 6967 * capabilities actually supported (not requested.)
6969 6968 */
6970 6969 ddi_fm_init(softs->devinfo_p, &softs->fm_capabilities, &fm_ibc);
6971 6970
6972 6971 /*
6973 6972 * Initialize pci ereport capabilities if ereport
6974 6973 * capable (should always be.)
6975 6974 */
6976 6975 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
6977 6976 DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
6978 6977 pci_ereport_setup(softs->devinfo_p);
6979 6978 }
6980 6979
6981 6980 /*
6982 6981 * Register error callback if error callback capable.
6983 6982 */
6984 6983 if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
6985 6984 ddi_fm_handler_register(softs->devinfo_p,
6986 6985 aac_fm_error_cb, (void *) softs);
6987 6986 }
6988 6987 }
6989 6988 }
6990 6989
6991 6990 /*
6992 6991 * aac_fm_fini - Releases fma capabilities and un-registers with IO
6993 6992 * fault services.
6994 6993 */
6995 6994 static void
6996 6995 aac_fm_fini(struct aac_softstate *softs)
6997 6996 {
6998 6997 /* Only unregister FMA capabilities if registered */
6999 6998 if (softs->fm_capabilities) {
7000 6999 /*
7001 7000 * Un-register error callback if error callback capable.
7002 7001 */
7003 7002 if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
7004 7003 ddi_fm_handler_unregister(softs->devinfo_p);
7005 7004 }
7006 7005
7007 7006 /*
7008 7007 * Release any resources allocated by pci_ereport_setup()
7009 7008 */
7010 7009 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities) ||
7011 7010 DDI_FM_ERRCB_CAP(softs->fm_capabilities)) {
7012 7011 pci_ereport_teardown(softs->devinfo_p);
7013 7012 }
7014 7013
7015 7014 /* Unregister from IO Fault Services */
7016 7015 ddi_fm_fini(softs->devinfo_p);
7017 7016
7018 7017 /* Adjust access and dma attributes for FMA */
7019 7018 softs->reg_attr.devacc_attr_access = DDI_DEFAULT_ACC;
7020 7019 softs->addr_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
7021 7020 softs->buf_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
7022 7021 }
7023 7022 }
7024 7023
7025 7024 int
7026 7025 aac_check_acc_handle(ddi_acc_handle_t handle)
7027 7026 {
7028 7027 ddi_fm_error_t de;
7029 7028
7030 7029 ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
7031 7030 return (de.fme_status);
7032 7031 }
7033 7032
7034 7033 int
7035 7034 aac_check_dma_handle(ddi_dma_handle_t handle)
7036 7035 {
7037 7036 ddi_fm_error_t de;
7038 7037
7039 7038 ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
7040 7039 return (de.fme_status);
7041 7040 }
7042 7041
7043 7042 void
7044 7043 aac_fm_ereport(struct aac_softstate *softs, char *detail)
7045 7044 {
7046 7045 uint64_t ena;
7047 7046 char buf[FM_MAX_CLASS];
7048 7047
7049 7048 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
7050 7049 ena = fm_ena_generate(0, FM_ENA_FMT1);
7051 7050 if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) {
7052 7051 ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP,
7053 7052 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL);
7054 7053 }
7055 7054 }
7056 7055
7057 7056 /*
7058 7057 * Autoconfiguration support
7059 7058 */
7060 7059 static int
7061 7060 aac_parse_devname(char *devnm, int *tgt, int *lun)
7062 7061 {
7063 7062 char devbuf[SCSI_MAXNAMELEN];
7064 7063 char *addr;
7065 7064 char *p, *tp, *lp;
7066 7065 long num;
7067 7066
7068 7067 /* Parse dev name and address */
7069 7068 (void) strcpy(devbuf, devnm);
7070 7069 addr = "";
7071 7070 for (p = devbuf; *p != '\0'; p++) {
7072 7071 if (*p == '@') {
7073 7072 addr = p + 1;
7074 7073 *p = '\0';
7075 7074 } else if (*p == ':') {
7076 7075 *p = '\0';
7077 7076 break;
7078 7077 }
7079 7078 }
7080 7079
7081 7080 /* Parse taget and lun */
7082 7081 for (p = tp = addr, lp = NULL; *p != '\0'; p++) {
7083 7082 if (*p == ',') {
7084 7083 lp = p + 1;
7085 7084 *p = '\0';
7086 7085 break;
7087 7086 }
7088 7087 }
7089 7088 if (tgt && tp) {
7090 7089 if (ddi_strtol(tp, NULL, 0x10, &num))
7091 7090 return (AACERR);
7092 7091 *tgt = (int)num;
7093 7092 }
7094 7093 if (lun && lp) {
7095 7094 if (ddi_strtol(lp, NULL, 0x10, &num))
7096 7095 return (AACERR);
7097 7096 *lun = (int)num;
7098 7097 }
7099 7098 return (AACOK);
7100 7099 }
7101 7100
7102 7101 static dev_info_t *
7103 7102 aac_find_child(struct aac_softstate *softs, uint16_t tgt, uint8_t lun)
7104 7103 {
7105 7104 dev_info_t *child = NULL;
7106 7105 char addr[SCSI_MAXNAMELEN];
7107 7106 char tmp[MAXNAMELEN];
7108 7107
7109 7108 if (tgt < AAC_MAX_LD) {
7110 7109 if (lun == 0) {
7111 7110 struct aac_device *dvp = &softs->containers[tgt].dev;
7112 7111
7113 7112 child = dvp->dip;
7114 7113 }
7115 7114 } else {
7116 7115 (void) sprintf(addr, "%x,%x", tgt, lun);
7117 7116 for (child = ddi_get_child(softs->devinfo_p);
7118 7117 child; child = ddi_get_next_sibling(child)) {
7119 7118 /* We don't care about non-persistent node */
7120 7119 if (ndi_dev_is_persistent_node(child) == 0)
7121 7120 continue;
7122 7121
7123 7122 if (aac_name_node(child, tmp, MAXNAMELEN) !=
7124 7123 DDI_SUCCESS)
7125 7124 continue;
7126 7125 if (strcmp(addr, tmp) == 0)
7127 7126 break;
7128 7127 }
7129 7128 }
7130 7129 return (child);
7131 7130 }
7132 7131
7133 7132 static int
7134 7133 aac_config_child(struct aac_softstate *softs, struct scsi_device *sd,
7135 7134 dev_info_t **dipp)
7136 7135 {
7137 7136 char *nodename = NULL;
7138 7137 char **compatible = NULL;
7139 7138 int ncompatible = 0;
7140 7139 char *childname;
7141 7140 dev_info_t *ldip = NULL;
7142 7141 int tgt = sd->sd_address.a_target;
7143 7142 int lun = sd->sd_address.a_lun;
7144 7143 int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
7145 7144 int rval;
7146 7145
7147 7146 DBCALLED(softs, 2);
7148 7147
7149 7148 scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype,
7150 7149 NULL, &nodename, &compatible, &ncompatible);
7151 7150 if (nodename == NULL) {
7152 7151 AACDB_PRINT(softs, CE_WARN,
7153 7152 "found no comptible driver for t%dL%d", tgt, lun);
7154 7153 rval = NDI_FAILURE;
7155 7154 goto finish;
7156 7155 }
7157 7156 childname = (softs->legacy && dtype == DTYPE_DIRECT) ? "sd" : nodename;
7158 7157
7159 7158 /* Create dev node */
7160 7159 rval = ndi_devi_alloc(softs->devinfo_p, childname, DEVI_SID_NODEID,
7161 7160 &ldip);
7162 7161 if (rval == NDI_SUCCESS) {
7163 7162 if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt)
7164 7163 != DDI_PROP_SUCCESS) {
7165 7164 AACDB_PRINT(softs, CE_WARN, "unable to create "
7166 7165 "property for t%dL%d (target)", tgt, lun);
7167 7166 rval = NDI_FAILURE;
7168 7167 goto finish;
7169 7168 }
7170 7169 if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "lun", lun)
7171 7170 != DDI_PROP_SUCCESS) {
7172 7171 AACDB_PRINT(softs, CE_WARN, "unable to create "
7173 7172 "property for t%dL%d (lun)", tgt, lun);
7174 7173 rval = NDI_FAILURE;
7175 7174 goto finish;
7176 7175 }
7177 7176 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, ldip,
7178 7177 "compatible", compatible, ncompatible)
7179 7178 != DDI_PROP_SUCCESS) {
7180 7179 AACDB_PRINT(softs, CE_WARN, "unable to create "
7181 7180 "property for t%dL%d (compatible)", tgt, lun);
7182 7181 rval = NDI_FAILURE;
7183 7182 goto finish;
7184 7183 }
7185 7184
7186 7185 rval = ndi_devi_online(ldip, NDI_ONLINE_ATTACH);
7187 7186 if (rval != NDI_SUCCESS) {
7188 7187 AACDB_PRINT(softs, CE_WARN, "unable to online t%dL%d",
7189 7188 tgt, lun);
7190 7189 ndi_prop_remove_all(ldip);
7191 7190 (void) ndi_devi_free(ldip);
7192 7191 }
7193 7192 }
7194 7193 finish:
7195 7194 if (dipp)
7196 7195 *dipp = ldip;
7197 7196
7198 7197 scsi_hba_nodename_compatible_free(nodename, compatible);
7199 7198 return (rval);
7200 7199 }
7201 7200
7202 7201 /*ARGSUSED*/
7203 7202 static int
7204 7203 aac_probe_lun(struct aac_softstate *softs, struct scsi_device *sd)
7205 7204 {
7206 7205 int tgt = sd->sd_address.a_target;
7207 7206 int lun = sd->sd_address.a_lun;
7208 7207
7209 7208 DBCALLED(softs, 2);
7210 7209
7211 7210 if (tgt < AAC_MAX_LD) {
7212 7211 enum aac_cfg_event event;
7213 7212
7214 7213 if (lun == 0) {
7215 7214 mutex_enter(&softs->io_lock);
7216 7215 event = aac_probe_container(softs, tgt);
7217 7216 mutex_exit(&softs->io_lock);
7218 7217 if ((event != AAC_CFG_NULL_NOEXIST) &&
7219 7218 (event != AAC_CFG_DELETE)) {
7220 7219 if (scsi_hba_probe(sd, NULL) ==
7221 7220 SCSIPROBE_EXISTS)
7222 7221 return (NDI_SUCCESS);
7223 7222 }
7224 7223 }
7225 7224 return (NDI_FAILURE);
7226 7225 } else {
7227 7226 int dtype;
7228 7227 int qual; /* device qualifier */
7229 7228
7230 7229 if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS)
7231 7230 return (NDI_FAILURE);
7232 7231
7233 7232 dtype = sd->sd_inq->inq_dtype & DTYPE_MASK;
7234 7233 qual = dtype >> 5;
7235 7234
7236 7235 AACDB_PRINT(softs, CE_NOTE,
7237 7236 "Phys. device found: tgt %d dtype %d: %s",
7238 7237 tgt, dtype, sd->sd_inq->inq_vid);
7239 7238
7240 7239 /* Only non-DASD and JBOD mode DASD are allowed exposed */
7241 7240 if (dtype == DTYPE_RODIRECT /* CDROM */ ||
7242 7241 dtype == DTYPE_SEQUENTIAL /* TAPE */ ||
7243 7242 dtype == DTYPE_ESI /* SES */) {
7244 7243 if (!(softs->flags & AAC_FLAGS_NONDASD))
7245 7244 return (NDI_FAILURE);
7246 7245 AACDB_PRINT(softs, CE_NOTE, "non-DASD %d found", tgt);
7247 7246
7248 7247 } else if (dtype == DTYPE_DIRECT) {
7249 7248 if (!(softs->flags & AAC_FLAGS_JBOD) || qual != 0)
7250 7249 return (NDI_FAILURE);
7251 7250 AACDB_PRINT(softs, CE_NOTE, "JBOD DASD %d found", tgt);
7252 7251 }
7253 7252
7254 7253 mutex_enter(&softs->io_lock);
7255 7254 softs->nondasds[AAC_PD(tgt)].dev.flags |= AAC_DFLAG_VALID;
7256 7255 mutex_exit(&softs->io_lock);
7257 7256 return (NDI_SUCCESS);
7258 7257 }
7259 7258 }
7260 7259
7261 7260 static int
7262 7261 aac_config_lun(struct aac_softstate *softs, uint16_t tgt, uint8_t lun,
7263 7262 dev_info_t **ldip)
7264 7263 {
7265 7264 struct scsi_device sd;
7266 7265 dev_info_t *child;
7267 7266 int rval;
7268 7267
7269 7268 DBCALLED(softs, 2);
7270 7269
7271 7270 if ((child = aac_find_child(softs, tgt, lun)) != NULL) {
7272 7271 if (ldip)
7273 7272 *ldip = child;
7274 7273 return (NDI_SUCCESS);
7275 7274 }
7276 7275
7277 7276 bzero(&sd, sizeof (struct scsi_device));
7278 7277 sd.sd_address.a_hba_tran = softs->hba_tran;
7279 7278 sd.sd_address.a_target = (uint16_t)tgt;
7280 7279 sd.sd_address.a_lun = (uint8_t)lun;
7281 7280 if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS)
7282 7281 rval = aac_config_child(softs, &sd, ldip);
7283 7282 /* scsi_unprobe is blank now. Free buffer manually */
7284 7283 if (sd.sd_inq) {
7285 7284 kmem_free(sd.sd_inq, SUN_INQSIZE);
7286 7285 sd.sd_inq = (struct scsi_inquiry *)NULL;
7287 7286 }
7288 7287 return (rval);
7289 7288 }
7290 7289
7291 7290 static int
7292 7291 aac_config_tgt(struct aac_softstate *softs, int tgt)
7293 7292 {
7294 7293 struct scsi_address ap;
7295 7294 struct buf *bp = NULL;
7296 7295 int buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + AAC_SCSI_RPTLUNS_ADDR_SIZE;
7297 7296 int list_len = 0;
7298 7297 int lun_total = 0;
7299 7298 dev_info_t *ldip;
7300 7299 int i;
7301 7300
7302 7301 ap.a_hba_tran = softs->hba_tran;
7303 7302 ap.a_target = (uint16_t)tgt;
7304 7303 ap.a_lun = 0;
7305 7304
7306 7305 for (i = 0; i < 2; i++) {
7307 7306 struct scsi_pkt *pkt;
7308 7307 uchar_t *cdb;
7309 7308 uchar_t *p;
7310 7309 uint32_t data;
7311 7310
7312 7311 if (bp == NULL) {
7313 7312 if ((bp = scsi_alloc_consistent_buf(&ap, NULL,
7314 7313 buf_len, B_READ, NULL_FUNC, NULL)) == NULL)
7315 7314 return (AACERR);
7316 7315 }
7317 7316 if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5,
7318 7317 sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT,
7319 7318 NULL, NULL)) == NULL) {
7320 7319 scsi_free_consistent_buf(bp);
7321 7320 return (AACERR);
7322 7321 }
7323 7322 cdb = pkt->pkt_cdbp;
7324 7323 bzero(cdb, CDB_GROUP5);
7325 7324 cdb[0] = SCMD_REPORT_LUNS;
7326 7325
7327 7326 /* Convert buffer len from local to LE_32 */
7328 7327 data = buf_len;
7329 7328 for (p = &cdb[9]; p > &cdb[5]; p--) {
7330 7329 *p = data & 0xff;
7331 7330 data >>= 8;
7332 7331 }
7333 7332
7334 7333 if (scsi_poll(pkt) < 0 ||
7335 7334 ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) {
7336 7335 scsi_destroy_pkt(pkt);
7337 7336 break;
7338 7337 }
7339 7338
7340 7339 /* Convert list_len from LE_32 to local */
7341 7340 for (p = (uchar_t *)bp->b_un.b_addr;
7342 7341 p < (uchar_t *)bp->b_un.b_addr + 4; p++) {
7343 7342 data <<= 8;
7344 7343 data |= *p;
7345 7344 }
7346 7345 list_len = data;
7347 7346 if (buf_len < list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE) {
7348 7347 scsi_free_consistent_buf(bp);
7349 7348 bp = NULL;
7350 7349 buf_len = list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE;
7351 7350 }
7352 7351 scsi_destroy_pkt(pkt);
7353 7352 }
7354 7353 if (i >= 2) {
7355 7354 uint8_t *buf = (uint8_t *)(bp->b_un.b_addr +
7356 7355 AAC_SCSI_RPTLUNS_HEAD_SIZE);
7357 7356
7358 7357 for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) {
7359 7358 uint16_t lun;
7360 7359
7361 7360 /* Determine report luns addressing type */
7362 7361 switch (buf[0] & AAC_SCSI_RPTLUNS_ADDR_MASK) {
7363 7362 /*
7364 7363 * Vendors in the field have been found to be
7365 7364 * concatenating bus/target/lun to equal the
7366 7365 * complete lun value instead of switching to
7367 7366 * flat space addressing
7368 7367 */
7369 7368 case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL:
7370 7369 case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT:
7371 7370 case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE:
7372 7371 lun = ((buf[0] & 0x3f) << 8) | buf[1];
7373 7372 if (lun > UINT8_MAX) {
7374 7373 AACDB_PRINT(softs, CE_WARN,
7375 7374 "abnormal lun number: %d", lun);
7376 7375 break;
7377 7376 }
7378 7377 if (aac_config_lun(softs, tgt, lun, &ldip) ==
7379 7378 NDI_SUCCESS)
7380 7379 lun_total++;
7381 7380 break;
7382 7381 }
7383 7382
7384 7383 buf += AAC_SCSI_RPTLUNS_ADDR_SIZE;
7385 7384 }
7386 7385 } else {
7387 7386 /* The target may do not support SCMD_REPORT_LUNS. */
7388 7387 if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS)
7389 7388 lun_total++;
7390 7389 }
7391 7390 scsi_free_consistent_buf(bp);
7392 7391 return (lun_total);
7393 7392 }
7394 7393
7395 7394 static void
7396 7395 aac_devcfg(struct aac_softstate *softs, int tgt, int en)
7397 7396 {
7398 7397 struct aac_device *dvp;
7399 7398
7400 7399 mutex_enter(&softs->io_lock);
7401 7400 dvp = AAC_DEV(softs, tgt);
7402 7401 if (en)
7403 7402 dvp->flags |= AAC_DFLAG_CONFIGURING;
7404 7403 else
7405 7404 dvp->flags &= ~AAC_DFLAG_CONFIGURING;
7406 7405 mutex_exit(&softs->io_lock);
7407 7406 }
7408 7407
7409 7408 static int
7410 7409 aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op,
7411 7410 void *arg, dev_info_t **childp)
7412 7411 {
7413 7412 struct aac_softstate *softs;
7414 7413 int circ = 0;
7415 7414 int rval;
7416 7415
7417 7416 if ((softs = ddi_get_soft_state(aac_softstatep,
7418 7417 ddi_get_instance(parent))) == NULL)
7419 7418 return (NDI_FAILURE);
7420 7419
7421 7420 /* Commands for bus config should be blocked as the bus is quiesced */
7422 7421 mutex_enter(&softs->io_lock);
7423 7422 if (softs->state & AAC_STATE_QUIESCED) {
7424 7423 AACDB_PRINT(softs, CE_NOTE,
7425 7424 "bus_config abroted because bus is quiesced");
7426 7425 mutex_exit(&softs->io_lock);
7427 7426 return (NDI_FAILURE);
7428 7427 }
7429 7428 mutex_exit(&softs->io_lock);
7430 7429
7431 7430 DBCALLED(softs, 1);
7432 7431
7433 7432 /* Hold the nexus across the bus_config */
7434 7433 ndi_devi_enter(parent, &circ);
7435 7434 switch (op) {
7436 7435 case BUS_CONFIG_ONE: {
7437 7436 int tgt, lun;
7438 7437
7439 7438 if (aac_parse_devname(arg, &tgt, &lun) != AACOK) {
7440 7439 rval = NDI_FAILURE;
7441 7440 break;
7442 7441 }
7443 7442 if (tgt >= AAC_MAX_LD) {
7444 7443 if (tgt >= AAC_MAX_DEV(softs)) {
7445 7444 rval = NDI_FAILURE;
7446 7445 break;
7447 7446 }
7448 7447 }
7449 7448
7450 7449 AAC_DEVCFG_BEGIN(softs, tgt);
7451 7450 rval = aac_config_lun(softs, tgt, lun, childp);
7452 7451 AAC_DEVCFG_END(softs, tgt);
7453 7452 break;
7454 7453 }
7455 7454
7456 7455 case BUS_CONFIG_DRIVER:
7457 7456 case BUS_CONFIG_ALL: {
7458 7457 uint32_t bus, tgt;
7459 7458 int index, total;
7460 7459
7461 7460 for (tgt = 0; tgt < AAC_MAX_LD; tgt++) {
7462 7461 AAC_DEVCFG_BEGIN(softs, tgt);
7463 7462 (void) aac_config_lun(softs, tgt, 0, NULL);
7464 7463 AAC_DEVCFG_END(softs, tgt);
7465 7464 }
7466 7465
7467 7466 /* Config the non-DASD devices connected to the card */
7468 7467 total = 0;
7469 7468 index = AAC_MAX_LD;
7470 7469 for (bus = 0; bus < softs->bus_max; bus++) {
7471 7470 AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus);
7472 7471 for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) {
7473 7472 AAC_DEVCFG_BEGIN(softs, index);
7474 7473 if (aac_config_tgt(softs, index))
7475 7474 total++;
7476 7475 AAC_DEVCFG_END(softs, index);
7477 7476 }
7478 7477 }
7479 7478 AACDB_PRINT(softs, CE_CONT,
7480 7479 "?Total %d phys. device(s) found", total);
7481 7480 rval = NDI_SUCCESS;
7482 7481 break;
7483 7482 }
7484 7483 }
7485 7484
7486 7485 if (rval == NDI_SUCCESS)
7487 7486 rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0);
7488 7487 ndi_devi_exit(parent, circ);
7489 7488 return (rval);
7490 7489 }
7491 7490
7492 7491 /*ARGSUSED*/
7493 7492 static int
7494 7493 aac_handle_dr(struct aac_softstate *softs, int tgt, int lun, int event)
7495 7494 {
7496 7495 struct aac_device *dvp;
7497 7496 dev_info_t *dip;
7498 7497 int valid;
7499 7498 int circ1 = 0;
7500 7499
7501 7500 DBCALLED(softs, 1);
7502 7501
7503 7502 /* Hold the nexus across the bus_config */
7504 7503 dvp = AAC_DEV(softs, tgt);
7505 7504 valid = AAC_DEV_IS_VALID(dvp);
7506 7505 dip = dvp->dip;
7507 7506 if (!(softs->state & AAC_STATE_RUN))
7508 7507 return (AACERR);
7509 7508 mutex_exit(&softs->io_lock);
7510 7509
7511 7510 switch (event) {
7512 7511 case AAC_CFG_ADD:
7513 7512 case AAC_CFG_DELETE:
7514 7513 /* Device onlined */
7515 7514 if (dip == NULL && valid) {
7516 7515 ndi_devi_enter(softs->devinfo_p, &circ1);
7517 7516 (void) aac_config_lun(softs, tgt, 0, NULL);
7518 7517 AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined",
7519 7518 softs->instance, tgt, lun);
7520 7519 ndi_devi_exit(softs->devinfo_p, circ1);
7521 7520 }
7522 7521 /* Device offlined */
7523 7522 if (dip && !valid) {
7524 7523 mutex_enter(&softs->io_lock);
7525 7524 (void) aac_do_reset(softs);
7526 7525 mutex_exit(&softs->io_lock);
7527 7526
7528 7527 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
7529 7528 AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined",
7530 7529 softs->instance, tgt, lun);
7531 7530 }
7532 7531 break;
7533 7532 }
↓ open down ↓ |
7051 lines elided |
↑ open up ↑ |
7534 7533
7535 7534 mutex_enter(&softs->io_lock);
7536 7535 return (AACOK);
7537 7536 }
7538 7537
7539 7538 #ifdef DEBUG
7540 7539
7541 7540 /* -------------------------debug aid functions-------------------------- */
7542 7541
7543 7542 #define AAC_FIB_CMD_KEY_STRINGS \
7544 - TestCommandResponse, "TestCommandResponse", \
7545 - TestAdapterCommand, "TestAdapterCommand", \
7546 - LastTestCommand, "LastTestCommand", \
7547 - ReinitHostNormCommandQueue, "ReinitHostNormCommandQueue", \
7548 - ReinitHostHighCommandQueue, "ReinitHostHighCommandQueue", \
7549 - ReinitHostHighRespQueue, "ReinitHostHighRespQueue", \
7550 - ReinitHostNormRespQueue, "ReinitHostNormRespQueue", \
7551 - ReinitAdapNormCommandQueue, "ReinitAdapNormCommandQueue", \
7552 - ReinitAdapHighCommandQueue, "ReinitAdapHighCommandQueue", \
7553 - ReinitAdapHighRespQueue, "ReinitAdapHighRespQueue", \
7554 - ReinitAdapNormRespQueue, "ReinitAdapNormRespQueue", \
7555 - InterfaceShutdown, "InterfaceShutdown", \
7556 - DmaCommandFib, "DmaCommandFib", \
7557 - StartProfile, "StartProfile", \
7558 - TermProfile, "TermProfile", \
7559 - SpeedTest, "SpeedTest", \
7560 - TakeABreakPt, "TakeABreakPt", \
7561 - RequestPerfData, "RequestPerfData", \
7562 - SetInterruptDefTimer, "SetInterruptDefTimer", \
7563 - SetInterruptDefCount, "SetInterruptDefCount", \
7564 - GetInterruptDefStatus, "GetInterruptDefStatus", \
7565 - LastCommCommand, "LastCommCommand", \
7566 - NuFileSystem, "NuFileSystem", \
7567 - UFS, "UFS", \
7568 - HostFileSystem, "HostFileSystem", \
7569 - LastFileSystemCommand, "LastFileSystemCommand", \
7570 - ContainerCommand, "ContainerCommand", \
7571 - ContainerCommand64, "ContainerCommand64", \
7572 - ClusterCommand, "ClusterCommand", \
7573 - ScsiPortCommand, "ScsiPortCommand", \
7574 - ScsiPortCommandU64, "ScsiPortCommandU64", \
7575 - AifRequest, "AifRequest", \
7576 - CheckRevision, "CheckRevision", \
7577 - FsaHostShutdown, "FsaHostShutdown", \
7578 - RequestAdapterInfo, "RequestAdapterInfo", \
7579 - IsAdapterPaused, "IsAdapterPaused", \
7580 - SendHostTime, "SendHostTime", \
7581 - LastMiscCommand, "LastMiscCommand"
7543 + {TestCommandResponse, "TestCommandResponse"}, \
7544 + {TestAdapterCommand, "TestAdapterCommand"}, \
7545 + {LastTestCommand, "LastTestCommand"}, \
7546 + {ReinitHostNormCommandQueue, "ReinitHostNormCommandQueue"}, \
7547 + {ReinitHostHighCommandQueue, "ReinitHostHighCommandQueue"}, \
7548 + {ReinitHostHighRespQueue, "ReinitHostHighRespQueue"}, \
7549 + {ReinitHostNormRespQueue, "ReinitHostNormRespQueue"}, \
7550 + {ReinitAdapNormCommandQueue, "ReinitAdapNormCommandQueue"}, \
7551 + {ReinitAdapHighCommandQueue, "ReinitAdapHighCommandQueue"}, \
7552 + {ReinitAdapHighRespQueue, "ReinitAdapHighRespQueue"}, \
7553 + {ReinitAdapNormRespQueue, "ReinitAdapNormRespQueue"}, \
7554 + {InterfaceShutdown, "InterfaceShutdown"}, \
7555 + {DmaCommandFib, "DmaCommandFib"}, \
7556 + {StartProfile, "StartProfile"}, \
7557 + {TermProfile, "TermProfile"}, \
7558 + {SpeedTest, "SpeedTest"}, \
7559 + {TakeABreakPt, "TakeABreakPt"}, \
7560 + {RequestPerfData, "RequestPerfData"}, \
7561 + {SetInterruptDefTimer, "SetInterruptDefTimer"}, \
7562 + {SetInterruptDefCount, "SetInterruptDefCount"}, \
7563 + {GetInterruptDefStatus, "GetInterruptDefStatus"}, \
7564 + {LastCommCommand, "LastCommCommand"}, \
7565 + {NuFileSystem, "NuFileSystem"}, \
7566 + {UFS, "UFS"}, \
7567 + {HostFileSystem, "HostFileSystem"}, \
7568 + {LastFileSystemCommand, "LastFileSystemCommand"}, \
7569 + {ContainerCommand, "ContainerCommand"}, \
7570 + {ContainerCommand64, "ContainerCommand64"}, \
7571 + {ClusterCommand, "ClusterCommand"}, \
7572 + {ScsiPortCommand, "ScsiPortCommand"}, \
7573 + {ScsiPortCommandU64, "ScsiPortCommandU64"}, \
7574 + {AifRequest, "AifRequest"}, \
7575 + {CheckRevision, "CheckRevision"}, \
7576 + {FsaHostShutdown, "FsaHostShutdown"}, \
7577 + {RequestAdapterInfo, "RequestAdapterInfo"}, \
7578 + {IsAdapterPaused, "IsAdapterPaused"}, \
7579 + {SendHostTime, "SendHostTime"}, \
7580 + {LastMiscCommand, "LastMiscCommand"}
7582 7581
7583 7582 #define AAC_CTVM_SUBCMD_KEY_STRINGS \
7584 - VM_Null, "VM_Null", \
7585 - VM_NameServe, "VM_NameServe", \
7586 - VM_ContainerConfig, "VM_ContainerConfig", \
7587 - VM_Ioctl, "VM_Ioctl", \
7588 - VM_FilesystemIoctl, "VM_FilesystemIoctl", \
7589 - VM_CloseAll, "VM_CloseAll", \
7590 - VM_CtBlockRead, "VM_CtBlockRead", \
7591 - VM_CtBlockWrite, "VM_CtBlockWrite", \
7592 - VM_SliceBlockRead, "VM_SliceBlockRead", \
7593 - VM_SliceBlockWrite, "VM_SliceBlockWrite", \
7594 - VM_DriveBlockRead, "VM_DriveBlockRead", \
7595 - VM_DriveBlockWrite, "VM_DriveBlockWrite", \
7596 - VM_EnclosureMgt, "VM_EnclosureMgt", \
7597 - VM_Unused, "VM_Unused", \
7598 - VM_CtBlockVerify, "VM_CtBlockVerify", \
7599 - VM_CtPerf, "VM_CtPerf", \
7600 - VM_CtBlockRead64, "VM_CtBlockRead64", \
7601 - VM_CtBlockWrite64, "VM_CtBlockWrite64", \
7602 - VM_CtBlockVerify64, "VM_CtBlockVerify64", \
7603 - VM_CtHostRead64, "VM_CtHostRead64", \
7604 - VM_CtHostWrite64, "VM_CtHostWrite64", \
7605 - VM_NameServe64, "VM_NameServe64"
7583 + {VM_Null, "VM_Null"}, \
7584 + {VM_NameServe, "VM_NameServe"}, \
7585 + {VM_ContainerConfig, "VM_ContainerConfig"}, \
7586 + {VM_Ioctl, "VM_Ioctl"}, \
7587 + {VM_FilesystemIoctl, "VM_FilesystemIoctl"}, \
7588 + {VM_CloseAll, "VM_CloseAll"}, \
7589 + {VM_CtBlockRead, "VM_CtBlockRead"}, \
7590 + {VM_CtBlockWrite, "VM_CtBlockWrite"}, \
7591 + {VM_SliceBlockRead, "VM_SliceBlockRead"}, \
7592 + {VM_SliceBlockWrite, "VM_SliceBlockWrite"}, \
7593 + {VM_DriveBlockRead, "VM_DriveBlockRead"}, \
7594 + {VM_DriveBlockWrite, "VM_DriveBlockWrite"}, \
7595 + {VM_EnclosureMgt, "VM_EnclosureMgt"}, \
7596 + {VM_Unused, "VM_Unused"}, \
7597 + {VM_CtBlockVerify, "VM_CtBlockVerify"}, \
7598 + {VM_CtPerf, "VM_CtPerf"}, \
7599 + {VM_CtBlockRead64, "VM_CtBlockRead64"}, \
7600 + {VM_CtBlockWrite64, "VM_CtBlockWrite64"}, \
7601 + {VM_CtBlockVerify64, "{VM_CtBlockVerify64"}, \
7602 + {VM_CtHostRead64, "VM_CtHostRead64"}, \
7603 + {VM_CtHostWrite64, "VM_CtHostWrite64"}, \
7604 + {VM_NameServe64, "VM_NameServe64"}
7606 7605
7607 7606 #define AAC_CT_SUBCMD_KEY_STRINGS \
7608 - CT_Null, "CT_Null", \
7609 - CT_GET_SLICE_COUNT, "CT_GET_SLICE_COUNT", \
7610 - CT_GET_PARTITION_COUNT, "CT_GET_PARTITION_COUNT", \
7611 - CT_GET_PARTITION_INFO, "CT_GET_PARTITION_INFO", \
7612 - CT_GET_CONTAINER_COUNT, "CT_GET_CONTAINER_COUNT", \
7613 - CT_GET_CONTAINER_INFO_OLD, "CT_GET_CONTAINER_INFO_OLD", \
7614 - CT_WRITE_MBR, "CT_WRITE_MBR", \
7615 - CT_WRITE_PARTITION, "CT_WRITE_PARTITION", \
7616 - CT_UPDATE_PARTITION, "CT_UPDATE_PARTITION", \
7617 - CT_UNLOAD_CONTAINER, "CT_UNLOAD_CONTAINER", \
7618 - CT_CONFIG_SINGLE_PRIMARY, "CT_CONFIG_SINGLE_PRIMARY", \
7619 - CT_READ_CONFIG_AGE, "CT_READ_CONFIG_AGE", \
7620 - CT_WRITE_CONFIG_AGE, "CT_WRITE_CONFIG_AGE", \
7621 - CT_READ_SERIAL_NUMBER, "CT_READ_SERIAL_NUMBER", \
7622 - CT_ZERO_PAR_ENTRY, "CT_ZERO_PAR_ENTRY", \
7623 - CT_READ_MBR, "CT_READ_MBR", \
7624 - CT_READ_PARTITION, "CT_READ_PARTITION", \
7625 - CT_DESTROY_CONTAINER, "CT_DESTROY_CONTAINER", \
7626 - CT_DESTROY2_CONTAINER, "CT_DESTROY2_CONTAINER", \
7627 - CT_SLICE_SIZE, "CT_SLICE_SIZE", \
7628 - CT_CHECK_CONFLICTS, "CT_CHECK_CONFLICTS", \
7629 - CT_MOVE_CONTAINER, "CT_MOVE_CONTAINER", \
7630 - CT_READ_LAST_DRIVE, "CT_READ_LAST_DRIVE", \
7631 - CT_WRITE_LAST_DRIVE, "CT_WRITE_LAST_DRIVE", \
7632 - CT_UNMIRROR, "CT_UNMIRROR", \
7633 - CT_MIRROR_DELAY, "CT_MIRROR_DELAY", \
7634 - CT_GEN_MIRROR, "CT_GEN_MIRROR", \
7635 - CT_GEN_MIRROR2, "CT_GEN_MIRROR2", \
7636 - CT_TEST_CONTAINER, "CT_TEST_CONTAINER", \
7637 - CT_MOVE2, "CT_MOVE2", \
7638 - CT_SPLIT, "CT_SPLIT", \
7639 - CT_SPLIT2, "CT_SPLIT2", \
7640 - CT_SPLIT_BROKEN, "CT_SPLIT_BROKEN", \
7641 - CT_SPLIT_BROKEN2, "CT_SPLIT_BROKEN2", \
7642 - CT_RECONFIG, "CT_RECONFIG", \
7643 - CT_BREAK2, "CT_BREAK2", \
7644 - CT_BREAK, "CT_BREAK", \
7645 - CT_MERGE2, "CT_MERGE2", \
7646 - CT_MERGE, "CT_MERGE", \
7647 - CT_FORCE_ERROR, "CT_FORCE_ERROR", \
7648 - CT_CLEAR_ERROR, "CT_CLEAR_ERROR", \
7649 - CT_ASSIGN_FAILOVER, "CT_ASSIGN_FAILOVER", \
7650 - CT_CLEAR_FAILOVER, "CT_CLEAR_FAILOVER", \
7651 - CT_GET_FAILOVER_DATA, "CT_GET_FAILOVER_DATA", \
7652 - CT_VOLUME_ADD, "CT_VOLUME_ADD", \
7653 - CT_VOLUME_ADD2, "CT_VOLUME_ADD2", \
7654 - CT_MIRROR_STATUS, "CT_MIRROR_STATUS", \
7655 - CT_COPY_STATUS, "CT_COPY_STATUS", \
7656 - CT_COPY, "CT_COPY", \
7657 - CT_UNLOCK_CONTAINER, "CT_UNLOCK_CONTAINER", \
7658 - CT_LOCK_CONTAINER, "CT_LOCK_CONTAINER", \
7659 - CT_MAKE_READ_ONLY, "CT_MAKE_READ_ONLY", \
7660 - CT_MAKE_READ_WRITE, "CT_MAKE_READ_WRITE", \
7661 - CT_CLEAN_DEAD, "CT_CLEAN_DEAD", \
7662 - CT_ABORT_MIRROR_COMMAND, "CT_ABORT_MIRROR_COMMAND", \
7663 - CT_SET, "CT_SET", \
7664 - CT_GET, "CT_GET", \
7665 - CT_GET_NVLOG_ENTRY, "CT_GET_NVLOG_ENTRY", \
7666 - CT_GET_DELAY, "CT_GET_DELAY", \
7667 - CT_ZERO_CONTAINER_SPACE, "CT_ZERO_CONTAINER_SPACE", \
7668 - CT_GET_ZERO_STATUS, "CT_GET_ZERO_STATUS", \
7669 - CT_SCRUB, "CT_SCRUB", \
7670 - CT_GET_SCRUB_STATUS, "CT_GET_SCRUB_STATUS", \
7671 - CT_GET_SLICE_INFO, "CT_GET_SLICE_INFO", \
7672 - CT_GET_SCSI_METHOD, "CT_GET_SCSI_METHOD", \
7673 - CT_PAUSE_IO, "CT_PAUSE_IO", \
7674 - CT_RELEASE_IO, "CT_RELEASE_IO", \
7675 - CT_SCRUB2, "CT_SCRUB2", \
7676 - CT_MCHECK, "CT_MCHECK", \
7677 - CT_CORRUPT, "CT_CORRUPT", \
7678 - CT_GET_TASK_COUNT, "CT_GET_TASK_COUNT", \
7679 - CT_PROMOTE, "CT_PROMOTE", \
7680 - CT_SET_DEAD, "CT_SET_DEAD", \
7681 - CT_CONTAINER_OPTIONS, "CT_CONTAINER_OPTIONS", \
7682 - CT_GET_NV_PARAM, "CT_GET_NV_PARAM", \
7683 - CT_GET_PARAM, "CT_GET_PARAM", \
7684 - CT_NV_PARAM_SIZE, "CT_NV_PARAM_SIZE", \
7685 - CT_COMMON_PARAM_SIZE, "CT_COMMON_PARAM_SIZE", \
7686 - CT_PLATFORM_PARAM_SIZE, "CT_PLATFORM_PARAM_SIZE", \
7687 - CT_SET_NV_PARAM, "CT_SET_NV_PARAM", \
7688 - CT_ABORT_SCRUB, "CT_ABORT_SCRUB", \
7689 - CT_GET_SCRUB_ERROR, "CT_GET_SCRUB_ERROR", \
7690 - CT_LABEL_CONTAINER, "CT_LABEL_CONTAINER", \
7691 - CT_CONTINUE_DATA, "CT_CONTINUE_DATA", \
7692 - CT_STOP_DATA, "CT_STOP_DATA", \
7693 - CT_GET_PARTITION_TABLE, "CT_GET_PARTITION_TABLE", \
7694 - CT_GET_DISK_PARTITIONS, "CT_GET_DISK_PARTITIONS", \
7695 - CT_GET_MISC_STATUS, "CT_GET_MISC_STATUS", \
7696 - CT_GET_CONTAINER_PERF_INFO, "CT_GET_CONTAINER_PERF_INFO", \
7697 - CT_GET_TIME, "CT_GET_TIME", \
7698 - CT_READ_DATA, "CT_READ_DATA", \
7699 - CT_CTR, "CT_CTR", \
7700 - CT_CTL, "CT_CTL", \
7701 - CT_DRAINIO, "CT_DRAINIO", \
7702 - CT_RELEASEIO, "CT_RELEASEIO", \
7703 - CT_GET_NVRAM, "CT_GET_NVRAM", \
7704 - CT_GET_MEMORY, "CT_GET_MEMORY", \
7705 - CT_PRINT_CT_LOG, "CT_PRINT_CT_LOG", \
7706 - CT_ADD_LEVEL, "CT_ADD_LEVEL", \
7707 - CT_NV_ZERO, "CT_NV_ZERO", \
7708 - CT_READ_SIGNATURE, "CT_READ_SIGNATURE", \
7709 - CT_THROTTLE_ON, "CT_THROTTLE_ON", \
7710 - CT_THROTTLE_OFF, "CT_THROTTLE_OFF", \
7711 - CT_GET_THROTTLE_STATS, "CT_GET_THROTTLE_STATS", \
7712 - CT_MAKE_SNAPSHOT, "CT_MAKE_SNAPSHOT", \
7713 - CT_REMOVE_SNAPSHOT, "CT_REMOVE_SNAPSHOT", \
7714 - CT_WRITE_USER_FLAGS, "CT_WRITE_USER_FLAGS", \
7715 - CT_READ_USER_FLAGS, "CT_READ_USER_FLAGS", \
7716 - CT_MONITOR, "CT_MONITOR", \
7717 - CT_GEN_MORPH, "CT_GEN_MORPH", \
7718 - CT_GET_SNAPSHOT_INFO, "CT_GET_SNAPSHOT_INFO", \
7719 - CT_CACHE_SET, "CT_CACHE_SET", \
7720 - CT_CACHE_STAT, "CT_CACHE_STAT", \
7721 - CT_TRACE_START, "CT_TRACE_START", \
7722 - CT_TRACE_STOP, "CT_TRACE_STOP", \
7723 - CT_TRACE_ENABLE, "CT_TRACE_ENABLE", \
7724 - CT_TRACE_DISABLE, "CT_TRACE_DISABLE", \
7725 - CT_FORCE_CORE_DUMP, "CT_FORCE_CORE_DUMP", \
7726 - CT_SET_SERIAL_NUMBER, "CT_SET_SERIAL_NUMBER", \
7727 - CT_RESET_SERIAL_NUMBER, "CT_RESET_SERIAL_NUMBER", \
7728 - CT_ENABLE_RAID5, "CT_ENABLE_RAID5", \
7729 - CT_CLEAR_VALID_DUMP_FLAG, "CT_CLEAR_VALID_DUMP_FLAG", \
7730 - CT_GET_MEM_STATS, "CT_GET_MEM_STATS", \
7731 - CT_GET_CORE_SIZE, "CT_GET_CORE_SIZE", \
7732 - CT_CREATE_CONTAINER_OLD, "CT_CREATE_CONTAINER_OLD", \
7733 - CT_STOP_DUMPS, "CT_STOP_DUMPS", \
7734 - CT_PANIC_ON_TAKE_A_BREAK, "CT_PANIC_ON_TAKE_A_BREAK", \
7735 - CT_GET_CACHE_STATS, "CT_GET_CACHE_STATS", \
7736 - CT_MOVE_PARTITION, "CT_MOVE_PARTITION", \
7737 - CT_FLUSH_CACHE, "CT_FLUSH_CACHE", \
7738 - CT_READ_NAME, "CT_READ_NAME", \
7739 - CT_WRITE_NAME, "CT_WRITE_NAME", \
7740 - CT_TOSS_CACHE, "CT_TOSS_CACHE", \
7741 - CT_LOCK_DRAINIO, "CT_LOCK_DRAINIO", \
7742 - CT_CONTAINER_OFFLINE, "CT_CONTAINER_OFFLINE", \
7743 - CT_SET_CACHE_SIZE, "CT_SET_CACHE_SIZE", \
7744 - CT_CLEAN_SHUTDOWN_STATUS, "CT_CLEAN_SHUTDOWN_STATUS", \
7745 - CT_CLEAR_DISKLOG_ON_DISK, "CT_CLEAR_DISKLOG_ON_DISK", \
7746 - CT_CLEAR_ALL_DISKLOG, "CT_CLEAR_ALL_DISKLOG", \
7747 - CT_CACHE_FAVOR, "CT_CACHE_FAVOR", \
7748 - CT_READ_PASSTHRU_MBR, "CT_READ_PASSTHRU_MBR", \
7749 - CT_SCRUB_NOFIX, "CT_SCRUB_NOFIX", \
7750 - CT_SCRUB2_NOFIX, "CT_SCRUB2_NOFIX", \
7751 - CT_FLUSH, "CT_FLUSH", \
7752 - CT_REBUILD, "CT_REBUILD", \
7753 - CT_FLUSH_CONTAINER, "CT_FLUSH_CONTAINER", \
7754 - CT_RESTART, "CT_RESTART", \
7755 - CT_GET_CONFIG_STATUS, "CT_GET_CONFIG_STATUS", \
7756 - CT_TRACE_FLAG, "CT_TRACE_FLAG", \
7757 - CT_RESTART_MORPH, "CT_RESTART_MORPH", \
7758 - CT_GET_TRACE_INFO, "CT_GET_TRACE_INFO", \
7759 - CT_GET_TRACE_ITEM, "CT_GET_TRACE_ITEM", \
7760 - CT_COMMIT_CONFIG, "CT_COMMIT_CONFIG", \
7761 - CT_CONTAINER_EXISTS, "CT_CONTAINER_EXISTS", \
7762 - CT_GET_SLICE_FROM_DEVT, "CT_GET_SLICE_FROM_DEVT", \
7763 - CT_OPEN_READ_WRITE, "CT_OPEN_READ_WRITE", \
7764 - CT_WRITE_MEMORY_BLOCK, "CT_WRITE_MEMORY_BLOCK", \
7765 - CT_GET_CACHE_PARAMS, "CT_GET_CACHE_PARAMS", \
7766 - CT_CRAZY_CACHE, "CT_CRAZY_CACHE", \
7767 - CT_GET_PROFILE_STRUCT, "CT_GET_PROFILE_STRUCT", \
7768 - CT_SET_IO_TRACE_FLAG, "CT_SET_IO_TRACE_FLAG", \
7769 - CT_GET_IO_TRACE_STRUCT, "CT_GET_IO_TRACE_STRUCT", \
7770 - CT_CID_TO_64BITS_UID, "CT_CID_TO_64BITS_UID", \
7771 - CT_64BITS_UID_TO_CID, "CT_64BITS_UID_TO_CID", \
7772 - CT_PAR_TO_64BITS_UID, "CT_PAR_TO_64BITS_UID", \
7773 - CT_CID_TO_32BITS_UID, "CT_CID_TO_32BITS_UID", \
7774 - CT_32BITS_UID_TO_CID, "CT_32BITS_UID_TO_CID", \
7775 - CT_PAR_TO_32BITS_UID, "CT_PAR_TO_32BITS_UID", \
7776 - CT_SET_FAILOVER_OPTION, "CT_SET_FAILOVER_OPTION", \
7777 - CT_GET_FAILOVER_OPTION, "CT_GET_FAILOVER_OPTION", \
7778 - CT_STRIPE_ADD2, "CT_STRIPE_ADD2", \
7779 - CT_CREATE_VOLUME_SET, "CT_CREATE_VOLUME_SET", \
7780 - CT_CREATE_STRIPE_SET, "CT_CREATE_STRIPE_SET", \
7781 - CT_VERIFY_CONTAINER, "CT_VERIFY_CONTAINER", \
7782 - CT_IS_CONTAINER_DEAD, "CT_IS_CONTAINER_DEAD", \
7783 - CT_GET_CONTAINER_OPTION, "CT_GET_CONTAINER_OPTION", \
7784 - CT_GET_SNAPSHOT_UNUSED_STRUCT, "CT_GET_SNAPSHOT_UNUSED_STRUCT", \
7785 - CT_CLEAR_SNAPSHOT_UNUSED_STRUCT, "CT_CLEAR_SNAPSHOT_UNUSED_STRUCT", \
7786 - CT_GET_CONTAINER_INFO, "CT_GET_CONTAINER_INFO", \
7787 - CT_CREATE_CONTAINER, "CT_CREATE_CONTAINER", \
7788 - CT_CHANGE_CREATIONINFO, "CT_CHANGE_CREATIONINFO", \
7789 - CT_CHECK_CONFLICT_UID, "CT_CHECK_CONFLICT_UID", \
7790 - CT_CONTAINER_UID_CHECK, "CT_CONTAINER_UID_CHECK", \
7791 - CT_IS_CONTAINER_MEATADATA_STANDARD, \
7792 - "CT_IS_CONTAINER_MEATADATA_STANDARD", \
7793 - CT_IS_SLICE_METADATA_STANDARD, "CT_IS_SLICE_METADATA_STANDARD", \
7794 - CT_GET_IMPORT_COUNT, "CT_GET_IMPORT_COUNT", \
7795 - CT_CANCEL_ALL_IMPORTS, "CT_CANCEL_ALL_IMPORTS", \
7796 - CT_GET_IMPORT_INFO, "CT_GET_IMPORT_INFO", \
7797 - CT_IMPORT_ARRAY, "CT_IMPORT_ARRAY", \
7798 - CT_GET_LOG_SIZE, "CT_GET_LOG_SIZE", \
7799 - CT_ALARM_GET_STATE, "CT_ALARM_GET_STATE", \
7800 - CT_ALARM_SET_STATE, "CT_ALARM_SET_STATE", \
7801 - CT_ALARM_ON_OFF, "CT_ALARM_ON_OFF", \
7802 - CT_GET_EE_OEM_ID, "CT_GET_EE_OEM_ID", \
7803 - CT_GET_PPI_HEADERS, "CT_GET_PPI_HEADERS", \
7804 - CT_GET_PPI_DATA, "CT_GET_PPI_DATA", \
7805 - CT_GET_PPI_ENTRIES, "CT_GET_PPI_ENTRIES", \
7806 - CT_DELETE_PPI_BUNDLE, "CT_DELETE_PPI_BUNDLE", \
7807 - CT_GET_PARTITION_TABLE_2, "CT_GET_PARTITION_TABLE_2", \
7808 - CT_GET_PARTITION_INFO_2, "CT_GET_PARTITION_INFO_2", \
7809 - CT_GET_DISK_PARTITIONS_2, "CT_GET_DISK_PARTITIONS_2", \
7810 - CT_QUIESCE_ADAPTER, "CT_QUIESCE_ADAPTER", \
7811 - CT_CLEAR_PPI_TABLE, "CT_CLEAR_PPI_TABLE"
7607 + {CT_Null, "CT_Null"}, \
7608 + {CT_GET_SLICE_COUNT, "CT_GET_SLICE_COUNT"}, \
7609 + {CT_GET_PARTITION_COUNT, "CT_GET_PARTITION_COUNT"}, \
7610 + {CT_GET_PARTITION_INFO, "CT_GET_PARTITION_INFO"}, \
7611 + {CT_GET_CONTAINER_COUNT, "CT_GET_CONTAINER_COUNT"}, \
7612 + {CT_GET_CONTAINER_INFO_OLD, "CT_GET_CONTAINER_INFO_OLD"}, \
7613 + {CT_WRITE_MBR, "CT_WRITE_MBR"}, \
7614 + {CT_WRITE_PARTITION, "CT_WRITE_PARTITION"}, \
7615 + {CT_UPDATE_PARTITION, "CT_UPDATE_PARTITION"}, \
7616 + {CT_UNLOAD_CONTAINER, "CT_UNLOAD_CONTAINER"}, \
7617 + {CT_CONFIG_SINGLE_PRIMARY, "CT_CONFIG_SINGLE_PRIMARY"}, \
7618 + {CT_READ_CONFIG_AGE, "CT_READ_CONFIG_AGE"}, \
7619 + {CT_WRITE_CONFIG_AGE, "CT_WRITE_CONFIG_AGE"}, \
7620 + {CT_READ_SERIAL_NUMBER, "CT_READ_SERIAL_NUMBER"}, \
7621 + {CT_ZERO_PAR_ENTRY, "CT_ZERO_PAR_ENTRY"}, \
7622 + {CT_READ_MBR, "CT_READ_MBR"}, \
7623 + {CT_READ_PARTITION, "CT_READ_PARTITION"}, \
7624 + {CT_DESTROY_CONTAINER, "CT_DESTROY_CONTAINER"}, \
7625 + {CT_DESTROY2_CONTAINER, "CT_DESTROY2_CONTAINER"}, \
7626 + {CT_SLICE_SIZE, "CT_SLICE_SIZE"}, \
7627 + {CT_CHECK_CONFLICTS, "CT_CHECK_CONFLICTS"}, \
7628 + {CT_MOVE_CONTAINER, "CT_MOVE_CONTAINER"}, \
7629 + {CT_READ_LAST_DRIVE, "CT_READ_LAST_DRIVE"}, \
7630 + {CT_WRITE_LAST_DRIVE, "CT_WRITE_LAST_DRIVE"}, \
7631 + {CT_UNMIRROR, "CT_UNMIRROR"}, \
7632 + {CT_MIRROR_DELAY, "CT_MIRROR_DELAY"}, \
7633 + {CT_GEN_MIRROR, "CT_GEN_MIRROR"}, \
7634 + {CT_GEN_MIRROR2, "CT_GEN_MIRROR2"}, \
7635 + {CT_TEST_CONTAINER, "CT_TEST_CONTAINER"}, \
7636 + {CT_MOVE2, "CT_MOVE2"}, \
7637 + {CT_SPLIT, "CT_SPLIT"}, \
7638 + {CT_SPLIT2, "CT_SPLIT2"}, \
7639 + {CT_SPLIT_BROKEN, "CT_SPLIT_BROKEN"}, \
7640 + {CT_SPLIT_BROKEN2, "CT_SPLIT_BROKEN2"}, \
7641 + {CT_RECONFIG, "CT_RECONFIG"}, \
7642 + {CT_BREAK2, "CT_BREAK2"}, \
7643 + {CT_BREAK, "CT_BREAK"}, \
7644 + {CT_MERGE2, "CT_MERGE2"}, \
7645 + {CT_MERGE, "CT_MERGE"}, \
7646 + {CT_FORCE_ERROR, "CT_FORCE_ERROR"}, \
7647 + {CT_CLEAR_ERROR, "CT_CLEAR_ERROR"}, \
7648 + {CT_ASSIGN_FAILOVER, "CT_ASSIGN_FAILOVER"}, \
7649 + {CT_CLEAR_FAILOVER, "CT_CLEAR_FAILOVER"}, \
7650 + {CT_GET_FAILOVER_DATA, "CT_GET_FAILOVER_DATA"}, \
7651 + {CT_VOLUME_ADD, "CT_VOLUME_ADD"}, \
7652 + {CT_VOLUME_ADD2, "CT_VOLUME_ADD2"}, \
7653 + {CT_MIRROR_STATUS, "CT_MIRROR_STATUS"}, \
7654 + {CT_COPY_STATUS, "CT_COPY_STATUS"}, \
7655 + {CT_COPY, "CT_COPY"}, \
7656 + {CT_UNLOCK_CONTAINER, "CT_UNLOCK_CONTAINER"}, \
7657 + {CT_LOCK_CONTAINER, "CT_LOCK_CONTAINER"}, \
7658 + {CT_MAKE_READ_ONLY, "CT_MAKE_READ_ONLY"}, \
7659 + {CT_MAKE_READ_WRITE, "CT_MAKE_READ_WRITE"}, \
7660 + {CT_CLEAN_DEAD, "CT_CLEAN_DEAD"}, \
7661 + {CT_ABORT_MIRROR_COMMAND, "CT_ABORT_MIRROR_COMMAND"}, \
7662 + {CT_SET, "CT_SET"}, \
7663 + {CT_GET, "CT_GET"}, \
7664 + {CT_GET_NVLOG_ENTRY, "CT_GET_NVLOG_ENTRY"}, \
7665 + {CT_GET_DELAY, "CT_GET_DELAY"}, \
7666 + {CT_ZERO_CONTAINER_SPACE, "CT_ZERO_CONTAINER_SPACE"}, \
7667 + {CT_GET_ZERO_STATUS, "CT_GET_ZERO_STATUS"}, \
7668 + {CT_SCRUB, "CT_SCRUB"}, \
7669 + {CT_GET_SCRUB_STATUS, "CT_GET_SCRUB_STATUS"}, \
7670 + {CT_GET_SLICE_INFO, "CT_GET_SLICE_INFO"}, \
7671 + {CT_GET_SCSI_METHOD, "CT_GET_SCSI_METHOD"}, \
7672 + {CT_PAUSE_IO, "CT_PAUSE_IO"}, \
7673 + {CT_RELEASE_IO, "CT_RELEASE_IO"}, \
7674 + {CT_SCRUB2, "CT_SCRUB2"}, \
7675 + {CT_MCHECK, "CT_MCHECK"}, \
7676 + {CT_CORRUPT, "CT_CORRUPT"}, \
7677 + {CT_GET_TASK_COUNT, "CT_GET_TASK_COUNT"}, \
7678 + {CT_PROMOTE, "CT_PROMOTE"}, \
7679 + {CT_SET_DEAD, "CT_SET_DEAD"}, \
7680 + {CT_CONTAINER_OPTIONS, "CT_CONTAINER_OPTIONS"}, \
7681 + {CT_GET_NV_PARAM, "CT_GET_NV_PARAM"}, \
7682 + {CT_GET_PARAM, "CT_GET_PARAM"}, \
7683 + {CT_NV_PARAM_SIZE, "CT_NV_PARAM_SIZE"}, \
7684 + {CT_COMMON_PARAM_SIZE, "CT_COMMON_PARAM_SIZE"}, \
7685 + {CT_PLATFORM_PARAM_SIZE, "CT_PLATFORM_PARAM_SIZE"}, \
7686 + {CT_SET_NV_PARAM, "CT_SET_NV_PARAM"}, \
7687 + {CT_ABORT_SCRUB, "CT_ABORT_SCRUB"}, \
7688 + {CT_GET_SCRUB_ERROR, "CT_GET_SCRUB_ERROR"}, \
7689 + {CT_LABEL_CONTAINER, "CT_LABEL_CONTAINER"}, \
7690 + {CT_CONTINUE_DATA, "CT_CONTINUE_DATA"}, \
7691 + {CT_STOP_DATA, "CT_STOP_DATA"}, \
7692 + {CT_GET_PARTITION_TABLE, "CT_GET_PARTITION_TABLE"}, \
7693 + {CT_GET_DISK_PARTITIONS, "CT_GET_DISK_PARTITIONS"}, \
7694 + {CT_GET_MISC_STATUS, "CT_GET_MISC_STATUS"}, \
7695 + {CT_GET_CONTAINER_PERF_INFO, "CT_GET_CONTAINER_PERF_INFO"}, \
7696 + {CT_GET_TIME, "CT_GET_TIME"}, \
7697 + {CT_READ_DATA, "CT_READ_DATA"}, \
7698 + {CT_CTR, "CT_CTR"}, \
7699 + {CT_CTL, "CT_CTL"}, \
7700 + {CT_DRAINIO, "CT_DRAINIO"}, \
7701 + {CT_RELEASEIO, "CT_RELEASEIO"}, \
7702 + {CT_GET_NVRAM, "CT_GET_NVRAM"}, \
7703 + {CT_GET_MEMORY, "CT_GET_MEMORY"}, \
7704 + {CT_PRINT_CT_LOG, "CT_PRINT_CT_LOG"}, \
7705 + {CT_ADD_LEVEL, "CT_ADD_LEVEL"}, \
7706 + {CT_NV_ZERO, "CT_NV_ZERO"}, \
7707 + {CT_READ_SIGNATURE, "CT_READ_SIGNATURE"}, \
7708 + {CT_THROTTLE_ON, "CT_THROTTLE_ON"}, \
7709 + {CT_THROTTLE_OFF, "CT_THROTTLE_OFF"}, \
7710 + {CT_GET_THROTTLE_STATS, "CT_GET_THROTTLE_STATS"}, \
7711 + {CT_MAKE_SNAPSHOT, "CT_MAKE_SNAPSHOT"}, \
7712 + {CT_REMOVE_SNAPSHOT, "CT_REMOVE_SNAPSHOT"}, \
7713 + {CT_WRITE_USER_FLAGS, "CT_WRITE_USER_FLAGS"}, \
7714 + {CT_READ_USER_FLAGS, "CT_READ_USER_FLAGS"}, \
7715 + {CT_MONITOR, "CT_MONITOR"}, \
7716 + {CT_GEN_MORPH, "CT_GEN_MORPH"}, \
7717 + {CT_GET_SNAPSHOT_INFO, "CT_GET_SNAPSHOT_INFO"}, \
7718 + {CT_CACHE_SET, "CT_CACHE_SET"}, \
7719 + {CT_CACHE_STAT, "CT_CACHE_STAT"}, \
7720 + {CT_TRACE_START, "CT_TRACE_START"}, \
7721 + {CT_TRACE_STOP, "CT_TRACE_STOP"}, \
7722 + {CT_TRACE_ENABLE, "CT_TRACE_ENABLE"}, \
7723 + {CT_TRACE_DISABLE, "CT_TRACE_DISABLE"}, \
7724 + {CT_FORCE_CORE_DUMP, "CT_FORCE_CORE_DUMP"}, \
7725 + {CT_SET_SERIAL_NUMBER, "CT_SET_SERIAL_NUMBER"}, \
7726 + {CT_RESET_SERIAL_NUMBER, "CT_RESET_SERIAL_NUMBER"}, \
7727 + {CT_ENABLE_RAID5, "CT_ENABLE_RAID5"}, \
7728 + {CT_CLEAR_VALID_DUMP_FLAG, "CT_CLEAR_VALID_DUMP_FLAG"}, \
7729 + {CT_GET_MEM_STATS, "CT_GET_MEM_STATS"}, \
7730 + {CT_GET_CORE_SIZE, "CT_GET_CORE_SIZE"}, \
7731 + {CT_CREATE_CONTAINER_OLD, "CT_CREATE_CONTAINER_OLD"}, \
7732 + {CT_STOP_DUMPS, "CT_STOP_DUMPS"}, \
7733 + {CT_PANIC_ON_TAKE_A_BREAK, "CT_PANIC_ON_TAKE_A_BREAK"}, \
7734 + {CT_GET_CACHE_STATS, "CT_GET_CACHE_STATS"}, \
7735 + {CT_MOVE_PARTITION, "CT_MOVE_PARTITION"}, \
7736 + {CT_FLUSH_CACHE, "CT_FLUSH_CACHE"}, \
7737 + {CT_READ_NAME, "CT_READ_NAME"}, \
7738 + {CT_WRITE_NAME, "CT_WRITE_NAME"}, \
7739 + {CT_TOSS_CACHE, "CT_TOSS_CACHE"}, \
7740 + {CT_LOCK_DRAINIO, "CT_LOCK_DRAINIO"}, \
7741 + {CT_CONTAINER_OFFLINE, "CT_CONTAINER_OFFLINE"}, \
7742 + {CT_SET_CACHE_SIZE, "CT_SET_CACHE_SIZE"}, \
7743 + {CT_CLEAN_SHUTDOWN_STATUS, "CT_CLEAN_SHUTDOWN_STATUS"}, \
7744 + {CT_CLEAR_DISKLOG_ON_DISK, "CT_CLEAR_DISKLOG_ON_DISK"}, \
7745 + {CT_CLEAR_ALL_DISKLOG, "CT_CLEAR_ALL_DISKLOG"}, \
7746 + {CT_CACHE_FAVOR, "CT_CACHE_FAVOR"}, \
7747 + {CT_READ_PASSTHRU_MBR, "CT_READ_PASSTHRU_MBR"}, \
7748 + {CT_SCRUB_NOFIX, "CT_SCRUB_NOFIX"}, \
7749 + {CT_SCRUB2_NOFIX, "CT_SCRUB2_NOFIX"}, \
7750 + {CT_FLUSH, "CT_FLUSH"}, \
7751 + {CT_REBUILD, "CT_REBUILD"}, \
7752 + {CT_FLUSH_CONTAINER, "CT_FLUSH_CONTAINER"}, \
7753 + {CT_RESTART, "CT_RESTART"}, \
7754 + {CT_GET_CONFIG_STATUS, "CT_GET_CONFIG_STATUS"}, \
7755 + {CT_TRACE_FLAG, "CT_TRACE_FLAG"}, \
7756 + {CT_RESTART_MORPH, "CT_RESTART_MORPH"}, \
7757 + {CT_GET_TRACE_INFO, "CT_GET_TRACE_INFO"}, \
7758 + {CT_GET_TRACE_ITEM, "CT_GET_TRACE_ITEM"}, \
7759 + {CT_COMMIT_CONFIG, "CT_COMMIT_CONFIG"}, \
7760 + {CT_CONTAINER_EXISTS, "CT_CONTAINER_EXISTS"}, \
7761 + {CT_GET_SLICE_FROM_DEVT, "CT_GET_SLICE_FROM_DEVT"}, \
7762 + {CT_OPEN_READ_WRITE, "CT_OPEN_READ_WRITE"}, \
7763 + {CT_WRITE_MEMORY_BLOCK, "CT_WRITE_MEMORY_BLOCK"}, \
7764 + {CT_GET_CACHE_PARAMS, "CT_GET_CACHE_PARAMS"}, \
7765 + {CT_CRAZY_CACHE, "CT_CRAZY_CACHE"}, \
7766 + {CT_GET_PROFILE_STRUCT, "CT_GET_PROFILE_STRUCT"}, \
7767 + {CT_SET_IO_TRACE_FLAG, "CT_SET_IO_TRACE_FLAG"}, \
7768 + {CT_GET_IO_TRACE_STRUCT, "CT_GET_IO_TRACE_STRUCT"}, \
7769 + {CT_CID_TO_64BITS_UID, "CT_CID_TO_64BITS_UID"}, \
7770 + {CT_64BITS_UID_TO_CID, "CT_64BITS_UID_TO_CID"}, \
7771 + {CT_PAR_TO_64BITS_UID, "CT_PAR_TO_64BITS_UID"}, \
7772 + {CT_CID_TO_32BITS_UID, "CT_CID_TO_32BITS_UID"}, \
7773 + {CT_32BITS_UID_TO_CID, "CT_32BITS_UID_TO_CID"}, \
7774 + {CT_PAR_TO_32BITS_UID, "CT_PAR_TO_32BITS_UID"}, \
7775 + {CT_SET_FAILOVER_OPTION, "CT_SET_FAILOVER_OPTION"}, \
7776 + {CT_GET_FAILOVER_OPTION, "CT_GET_FAILOVER_OPTION"}, \
7777 + {CT_STRIPE_ADD2, "CT_STRIPE_ADD2"}, \
7778 + {CT_CREATE_VOLUME_SET, "CT_CREATE_VOLUME_SET"}, \
7779 + {CT_CREATE_STRIPE_SET, "CT_CREATE_STRIPE_SET"}, \
7780 + {CT_VERIFY_CONTAINER, "CT_VERIFY_CONTAINER"}, \
7781 + {CT_IS_CONTAINER_DEAD, "CT_IS_CONTAINER_DEAD"}, \
7782 + {CT_GET_CONTAINER_OPTION, "CT_GET_CONTAINER_OPTION"}, \
7783 + {CT_GET_SNAPSHOT_UNUSED_STRUCT, "CT_GET_SNAPSHOT_UNUSED_STRUCT"}, \
7784 + {CT_CLEAR_SNAPSHOT_UNUSED_STRUCT, "CT_CLEAR_SNAPSHOT_UNUSED_STRUCT"}, \
7785 + {CT_GET_CONTAINER_INFO, "CT_GET_CONTAINER_INFO"}, \
7786 + {CT_CREATE_CONTAINER, "CT_CREATE_CONTAINER"}, \
7787 + {CT_CHANGE_CREATIONINFO, "CT_CHANGE_CREATIONINFO"}, \
7788 + {CT_CHECK_CONFLICT_UID, "CT_CHECK_CONFLICT_UID"}, \
7789 + {CT_CONTAINER_UID_CHECK, "CT_CONTAINER_UID_CHECK"}, \
7790 + {CT_IS_CONTAINER_MEATADATA_STANDARD, \
7791 + "CT_IS_CONTAINER_MEATADATA_STANDARD"}, \
7792 + {CT_IS_SLICE_METADATA_STANDARD, "CT_IS_SLICE_METADATA_STANDARD"}, \
7793 + {CT_GET_IMPORT_COUNT, "CT_GET_IMPORT_COUNT"}, \
7794 + {CT_CANCEL_ALL_IMPORTS, "CT_CANCEL_ALL_IMPORTS"}, \
7795 + {CT_GET_IMPORT_INFO, "CT_GET_IMPORT_INFO"}, \
7796 + {CT_IMPORT_ARRAY, "CT_IMPORT_ARRAY"}, \
7797 + {CT_GET_LOG_SIZE, "CT_GET_LOG_SIZE"}, \
7798 + {CT_ALARM_GET_STATE, "CT_ALARM_GET_STATE"}, \
7799 + {CT_ALARM_SET_STATE, "CT_ALARM_SET_STATE"}, \
7800 + {CT_ALARM_ON_OFF, "CT_ALARM_ON_OFF"}, \
7801 + {CT_GET_EE_OEM_ID, "CT_GET_EE_OEM_ID"}, \
7802 + {CT_GET_PPI_HEADERS, "CT_GET_PPI_HEADERS"}, \
7803 + {CT_GET_PPI_DATA, "CT_GET_PPI_DATA"}, \
7804 + {CT_GET_PPI_ENTRIES, "CT_GET_PPI_ENTRIES"}, \
7805 + {CT_DELETE_PPI_BUNDLE, "CT_DELETE_PPI_BUNDLE"}, \
7806 + {CT_GET_PARTITION_TABLE_2, "CT_GET_PARTITION_TABLE_2"}, \
7807 + {CT_GET_PARTITION_INFO_2, "CT_GET_PARTITION_INFO_2"}, \
7808 + {CT_GET_DISK_PARTITIONS_2, "CT_GET_DISK_PARTITIONS_2"}, \
7809 + {CT_QUIESCE_ADAPTER, "CT_QUIESCE_ADAPTER"}, \
7810 + {CT_CLEAR_PPI_TABLE, "CT_CLEAR_PPI_TABLE"}
7812 7811
7813 7812 #define AAC_CL_SUBCMD_KEY_STRINGS \
7814 - CL_NULL, "CL_NULL", \
7815 - DS_INIT, "DS_INIT", \
7816 - DS_RESCAN, "DS_RESCAN", \
7817 - DS_CREATE, "DS_CREATE", \
7818 - DS_DELETE, "DS_DELETE", \
7819 - DS_ADD_DISK, "DS_ADD_DISK", \
7820 - DS_REMOVE_DISK, "DS_REMOVE_DISK", \
7821 - DS_MOVE_DISK, "DS_MOVE_DISK", \
7822 - DS_TAKE_OWNERSHIP, "DS_TAKE_OWNERSHIP", \
7823 - DS_RELEASE_OWNERSHIP, "DS_RELEASE_OWNERSHIP", \
7824 - DS_FORCE_OWNERSHIP, "DS_FORCE_OWNERSHIP", \
7825 - DS_GET_DISK_SET_PARAM, "DS_GET_DISK_SET_PARAM", \
7826 - DS_GET_DRIVE_PARAM, "DS_GET_DRIVE_PARAM", \
7827 - DS_GET_SLICE_PARAM, "DS_GET_SLICE_PARAM", \
7828 - DS_GET_DISK_SETS, "DS_GET_DISK_SETS", \
7829 - DS_GET_DRIVES, "DS_GET_DRIVES", \
7830 - DS_SET_DISK_SET_PARAM, "DS_SET_DISK_SET_PARAM", \
7831 - DS_ONLINE, "DS_ONLINE", \
7832 - DS_OFFLINE, "DS_OFFLINE", \
7833 - DS_ONLINE_CONTAINERS, "DS_ONLINE_CONTAINERS", \
7834 - DS_FSAPRINT, "DS_FSAPRINT", \
7835 - CL_CFG_SET_HOST_IDS, "CL_CFG_SET_HOST_IDS", \
7836 - CL_CFG_SET_PARTNER_HOST_IDS, "CL_CFG_SET_PARTNER_HOST_IDS", \
7837 - CL_CFG_GET_CLUSTER_CONFIG, "CL_CFG_GET_CLUSTER_CONFIG", \
7838 - CC_CLI_CLEAR_MESSAGE_BUFFER, "CC_CLI_CLEAR_MESSAGE_BUFFER", \
7839 - CC_SRV_CLEAR_MESSAGE_BUFFER, "CC_SRV_CLEAR_MESSAGE_BUFFER", \
7840 - CC_CLI_SHOW_MESSAGE_BUFFER, "CC_CLI_SHOW_MESSAGE_BUFFER", \
7841 - CC_SRV_SHOW_MESSAGE_BUFFER, "CC_SRV_SHOW_MESSAGE_BUFFER", \
7842 - CC_CLI_SEND_MESSAGE, "CC_CLI_SEND_MESSAGE", \
7843 - CC_SRV_SEND_MESSAGE, "CC_SRV_SEND_MESSAGE", \
7844 - CC_CLI_GET_MESSAGE, "CC_CLI_GET_MESSAGE", \
7845 - CC_SRV_GET_MESSAGE, "CC_SRV_GET_MESSAGE", \
7846 - CC_SEND_TEST_MESSAGE, "CC_SEND_TEST_MESSAGE", \
7847 - CC_GET_BUSINFO, "CC_GET_BUSINFO", \
7848 - CC_GET_PORTINFO, "CC_GET_PORTINFO", \
7849 - CC_GET_NAMEINFO, "CC_GET_NAMEINFO", \
7850 - CC_GET_CONFIGINFO, "CC_GET_CONFIGINFO", \
7851 - CQ_QUORUM_OP, "CQ_QUORUM_OP"
7813 + {CL_NULL, "CL_NULL"}, \
7814 + {DS_INIT, "DS_INIT"}, \
7815 + {DS_RESCAN, "DS_RESCAN"}, \
7816 + {DS_CREATE, "DS_CREATE"}, \
7817 + {DS_DELETE, "DS_DELETE"}, \
7818 + {DS_ADD_DISK, "DS_ADD_DISK"}, \
7819 + {DS_REMOVE_DISK, "DS_REMOVE_DISK"}, \
7820 + {DS_MOVE_DISK, "DS_MOVE_DISK"}, \
7821 + {DS_TAKE_OWNERSHIP, "DS_TAKE_OWNERSHIP"}, \
7822 + {DS_RELEASE_OWNERSHIP, "DS_RELEASE_OWNERSHIP"}, \
7823 + {DS_FORCE_OWNERSHIP, "DS_FORCE_OWNERSHIP"}, \
7824 + {DS_GET_DISK_SET_PARAM, "DS_GET_DISK_SET_PARAM"}, \
7825 + {DS_GET_DRIVE_PARAM, "DS_GET_DRIVE_PARAM"}, \
7826 + {DS_GET_SLICE_PARAM, "DS_GET_SLICE_PARAM"}, \
7827 + {DS_GET_DISK_SETS, "DS_GET_DISK_SETS"}, \
7828 + {DS_GET_DRIVES, "DS_GET_DRIVES"}, \
7829 + {DS_SET_DISK_SET_PARAM, "DS_SET_DISK_SET_PARAM"}, \
7830 + {DS_ONLINE, "DS_ONLINE"}, \
7831 + {DS_OFFLINE, "DS_OFFLINE"}, \
7832 + {DS_ONLINE_CONTAINERS, "DS_ONLINE_CONTAINERS"}, \
7833 + {DS_FSAPRINT, "DS_FSAPRINT"}, \
7834 + {CL_CFG_SET_HOST_IDS, "CL_CFG_SET_HOST_IDS"}, \
7835 + {CL_CFG_SET_PARTNER_HOST_IDS, "CL_CFG_SET_PARTNER_HOST_IDS"}, \
7836 + {CL_CFG_GET_CLUSTER_CONFIG, "CL_CFG_GET_CLUSTER_CONFIG"}, \
7837 + {CC_CLI_CLEAR_MESSAGE_BUFFER, "CC_CLI_CLEAR_MESSAGE_BUFFER"}, \
7838 + {CC_SRV_CLEAR_MESSAGE_BUFFER, "CC_SRV_CLEAR_MESSAGE_BUFFER"}, \
7839 + {CC_CLI_SHOW_MESSAGE_BUFFER, "CC_CLI_SHOW_MESSAGE_BUFFER"}, \
7840 + {CC_SRV_SHOW_MESSAGE_BUFFER, "CC_SRV_SHOW_MESSAGE_BUFFER"}, \
7841 + {CC_CLI_SEND_MESSAGE, "CC_CLI_SEND_MESSAGE"}, \
7842 + {CC_SRV_SEND_MESSAGE, "CC_SRV_SEND_MESSAGE"}, \
7843 + {CC_CLI_GET_MESSAGE, "CC_CLI_GET_MESSAGE"}, \
7844 + {CC_SRV_GET_MESSAGE, "CC_SRV_GET_MESSAGE"}, \
7845 + {CC_SEND_TEST_MESSAGE, "CC_SEND_TEST_MESSAGE"}, \
7846 + {CC_GET_BUSINFO, "CC_GET_BUSINFO"}, \
7847 + {CC_GET_PORTINFO, "CC_GET_PORTINFO"}, \
7848 + {CC_GET_NAMEINFO, "CC_GET_NAMEINFO"}, \
7849 + {CC_GET_CONFIGINFO, "CC_GET_CONFIGINFO"}, \
7850 + {CQ_QUORUM_OP, "CQ_QUORUM_OP"}
7852 7851
7853 7852 #define AAC_AIF_SUBCMD_KEY_STRINGS \
7854 - AifCmdEventNotify, "AifCmdEventNotify", \
7855 - AifCmdJobProgress, "AifCmdJobProgress", \
7856 - AifCmdAPIReport, "AifCmdAPIReport", \
7857 - AifCmdDriverNotify, "AifCmdDriverNotify", \
7858 - AifReqJobList, "AifReqJobList", \
7859 - AifReqJobsForCtr, "AifReqJobsForCtr", \
7860 - AifReqJobsForScsi, "AifReqJobsForScsi", \
7861 - AifReqJobReport, "AifReqJobReport", \
7862 - AifReqTerminateJob, "AifReqTerminateJob", \
7863 - AifReqSuspendJob, "AifReqSuspendJob", \
7864 - AifReqResumeJob, "AifReqResumeJob", \
7865 - AifReqSendAPIReport, "AifReqSendAPIReport", \
7866 - AifReqAPIJobStart, "AifReqAPIJobStart", \
7867 - AifReqAPIJobUpdate, "AifReqAPIJobUpdate", \
7868 - AifReqAPIJobFinish, "AifReqAPIJobFinish"
7853 + {AifCmdEventNotify, "AifCmdEventNotify"}, \
7854 + {AifCmdJobProgress, "AifCmdJobProgress"}, \
7855 + {AifCmdAPIReport, "AifCmdAPIReport"}, \
7856 + {AifCmdDriverNotify, "AifCmdDriverNotify"}, \
7857 + {AifReqJobList, "AifReqJobList"}, \
7858 + {AifReqJobsForCtr, "AifReqJobsForCtr"}, \
7859 + {AifReqJobsForScsi, "AifReqJobsForScsi"}, \
7860 + {AifReqJobReport, "AifReqJobReport"}, \
7861 + {AifReqTerminateJob, "AifReqTerminateJob"}, \
7862 + {AifReqSuspendJob, "AifReqSuspendJob"}, \
7863 + {AifReqResumeJob, "AifReqResumeJob"}, \
7864 + {AifReqSendAPIReport, "AifReqSendAPIReport"}, \
7865 + {AifReqAPIJobStart, "AifReqAPIJobStart"}, \
7866 + {AifReqAPIJobUpdate, "AifReqAPIJobUpdate"}, \
7867 + {AifReqAPIJobFinish, "AifReqAPIJobFinish"}
7869 7868
7870 7869 #define AAC_IOCTL_SUBCMD_KEY_STRINGS \
7871 - Reserved_IOCTL, "Reserved_IOCTL", \
7872 - GetDeviceHandle, "GetDeviceHandle", \
7873 - BusTargetLun_to_DeviceHandle, "BusTargetLun_to_DeviceHandle", \
7874 - DeviceHandle_to_BusTargetLun, "DeviceHandle_to_BusTargetLun", \
7875 - RescanBus, "RescanBus", \
7876 - GetDeviceProbeInfo, "GetDeviceProbeInfo", \
7877 - GetDeviceCapacity, "GetDeviceCapacity", \
7878 - GetContainerProbeInfo, "GetContainerProbeInfo", \
7879 - GetRequestedMemorySize, "GetRequestedMemorySize", \
7880 - GetBusInfo, "GetBusInfo", \
7881 - GetVendorSpecific, "GetVendorSpecific", \
7882 - EnhancedGetDeviceProbeInfo, "EnhancedGetDeviceProbeInfo", \
7883 - EnhancedGetBusInfo, "EnhancedGetBusInfo", \
7884 - SetupExtendedCounters, "SetupExtendedCounters", \
7885 - GetPerformanceCounters, "GetPerformanceCounters", \
7886 - ResetPerformanceCounters, "ResetPerformanceCounters", \
7887 - ReadModePage, "ReadModePage", \
7888 - WriteModePage, "WriteModePage", \
7889 - ReadDriveParameter, "ReadDriveParameter", \
7890 - WriteDriveParameter, "WriteDriveParameter", \
7891 - ResetAdapter, "ResetAdapter", \
7892 - ResetBus, "ResetBus", \
7893 - ResetBusDevice, "ResetBusDevice", \
7894 - ExecuteSrb, "ExecuteSrb", \
7895 - Create_IO_Task, "Create_IO_Task", \
7896 - Delete_IO_Task, "Delete_IO_Task", \
7897 - Get_IO_Task_Info, "Get_IO_Task_Info", \
7898 - Check_Task_Progress, "Check_Task_Progress", \
7899 - InjectError, "InjectError", \
7900 - GetDeviceDefectCounts, "GetDeviceDefectCounts", \
7901 - GetDeviceDefectInfo, "GetDeviceDefectInfo", \
7902 - GetDeviceStatus, "GetDeviceStatus", \
7903 - ClearDeviceStatus, "ClearDeviceStatus", \
7904 - DiskSpinControl, "DiskSpinControl", \
7905 - DiskSmartControl, "DiskSmartControl", \
7906 - WriteSame, "WriteSame", \
7907 - ReadWriteLong, "ReadWriteLong", \
7908 - FormatUnit, "FormatUnit", \
7909 - TargetDeviceControl, "TargetDeviceControl", \
7910 - TargetChannelControl, "TargetChannelControl", \
7911 - FlashNewCode, "FlashNewCode", \
7912 - DiskCheck, "DiskCheck", \
7913 - RequestSense, "RequestSense", \
7914 - DiskPERControl, "DiskPERControl", \
7915 - Read10, "Read10", \
7916 - Write10, "Write10"
7870 + {Reserved_IOCTL, "Reserved_IOCTL"}, \
7871 + {GetDeviceHandle, "GetDeviceHandle"}, \
7872 + {BusTargetLun_to_DeviceHandle, "BusTargetLun_to_DeviceHandle"}, \
7873 + {DeviceHandle_to_BusTargetLun, "DeviceHandle_to_BusTargetLun"}, \
7874 + {RescanBus, "RescanBus"}, \
7875 + {GetDeviceProbeInfo, "GetDeviceProbeInfo"}, \
7876 + {GetDeviceCapacity, "GetDeviceCapacity"}, \
7877 + {GetContainerProbeInfo, "GetContainerProbeInfo"}, \
7878 + {GetRequestedMemorySize, "GetRequestedMemorySize"}, \
7879 + {GetBusInfo, "GetBusInfo"}, \
7880 + {GetVendorSpecific, "GetVendorSpecific"}, \
7881 + {EnhancedGetDeviceProbeInfo, "EnhancedGetDeviceProbeInfo"}, \
7882 + {EnhancedGetBusInfo, "EnhancedGetBusInfo"}, \
7883 + {SetupExtendedCounters, "SetupExtendedCounters"}, \
7884 + {GetPerformanceCounters, "GetPerformanceCounters"}, \
7885 + {ResetPerformanceCounters, "ResetPerformanceCounters"}, \
7886 + {ReadModePage, "ReadModePage"}, \
7887 + {WriteModePage, "WriteModePage"}, \
7888 + {ReadDriveParameter, "ReadDriveParameter"}, \
7889 + {WriteDriveParameter, "WriteDriveParameter"}, \
7890 + {ResetAdapter, "ResetAdapter"}, \
7891 + {ResetBus, "ResetBus"}, \
7892 + {ResetBusDevice, "ResetBusDevice"}, \
7893 + {ExecuteSrb, "ExecuteSrb"}, \
7894 + {Create_IO_Task, "Create_IO_Task"}, \
7895 + {Delete_IO_Task, "Delete_IO_Task"}, \
7896 + {Get_IO_Task_Info, "Get_IO_Task_Info"}, \
7897 + {Check_Task_Progress, "Check_Task_Progress"}, \
7898 + {InjectError, "InjectError"}, \
7899 + {GetDeviceDefectCounts, "GetDeviceDefectCounts"}, \
7900 + {GetDeviceDefectInfo, "GetDeviceDefectInfo"}, \
7901 + {GetDeviceStatus, "GetDeviceStatus"}, \
7902 + {ClearDeviceStatus, "ClearDeviceStatus"}, \
7903 + {DiskSpinControl, "DiskSpinControl"}, \
7904 + {DiskSmartControl, "DiskSmartControl"}, \
7905 + {WriteSame, "WriteSame"}, \
7906 + {ReadWriteLong, "ReadWriteLong"}, \
7907 + {FormatUnit, "FormatUnit"}, \
7908 + {TargetDeviceControl, "TargetDeviceControl"}, \
7909 + {TargetChannelControl, "TargetChannelControl"}, \
7910 + {FlashNewCode, "FlashNewCode"}, \
7911 + {DiskCheck, "DiskCheck"}, \
7912 + {RequestSense, "RequestSense"}, \
7913 + {DiskPERControl, "DiskPERControl"}, \
7914 + {Read10, "Read10"}, \
7915 + {Write10, "Write10"}
7917 7916
7918 7917 #define AAC_AIFEN_KEY_STRINGS \
7919 - AifEnGeneric, "Generic", \
7920 - AifEnTaskComplete, "TaskComplete", \
7921 - AifEnConfigChange, "Config change", \
7922 - AifEnContainerChange, "Container change", \
7923 - AifEnDeviceFailure, "device failed", \
7924 - AifEnMirrorFailover, "Mirror failover", \
7925 - AifEnContainerEvent, "container event", \
7926 - AifEnFileSystemChange, "File system changed", \
7927 - AifEnConfigPause, "Container pause event", \
7928 - AifEnConfigResume, "Container resume event", \
7929 - AifEnFailoverChange, "Failover space assignment changed", \
7930 - AifEnRAID5RebuildDone, "RAID5 rebuild finished", \
7931 - AifEnEnclosureManagement, "Enclosure management event", \
7932 - AifEnBatteryEvent, "battery event", \
7933 - AifEnAddContainer, "Add container", \
7934 - AifEnDeleteContainer, "Delete container", \
7935 - AifEnSMARTEvent, "SMART Event", \
7936 - AifEnBatteryNeedsRecond, "battery needs reconditioning", \
7937 - AifEnClusterEvent, "cluster event", \
7938 - AifEnDiskSetEvent, "disk set event occured", \
7939 - AifDenMorphComplete, "morph operation completed", \
7940 - AifDenVolumeExtendComplete, "VolumeExtendComplete"
7918 + {AifEnGeneric, "Generic"}, \
7919 + {AifEnTaskComplete, "TaskComplete"}, \
7920 + {AifEnConfigChange, "Config change"}, \
7921 + {AifEnContainerChange, "Container change"}, \
7922 + {AifEnDeviceFailure, "device failed"}, \
7923 + {AifEnMirrorFailover, "Mirror failover"}, \
7924 + {AifEnContainerEvent, "container event"}, \
7925 + {AifEnFileSystemChange, "File system changed"}, \
7926 + {AifEnConfigPause, "Container pause event"}, \
7927 + {AifEnConfigResume, "Container resume event"}, \
7928 + {AifEnFailoverChange, "Failover space assignment changed"}, \
7929 + {AifEnRAID5RebuildDone, "RAID5 rebuild finished"}, \
7930 + {AifEnEnclosureManagement, "Enclosure management event"}, \
7931 + {AifEnBatteryEvent, "battery event"}, \
7932 + {AifEnAddContainer, "Add container"}, \
7933 + {AifEnDeleteContainer, "Delete container"}, \
7934 + {AifEnSMARTEvent, "SMART Event"}, \
7935 + {AifEnBatteryNeedsRecond, "battery needs reconditioning"}, \
7936 + {AifEnClusterEvent, "cluster event"}, \
7937 + {AifEnDiskSetEvent, "disk set event occured"}, \
7938 + {AifDenMorphComplete, "morph operation completed"}, \
7939 + {AifDenVolumeExtendComplete, "VolumeExtendComplete"}
7941 7940
7942 7941 struct aac_key_strings {
7943 7942 int key;
7944 7943 char *message;
7945 7944 };
7946 7945
7947 7946 extern struct scsi_key_strings scsi_cmds[];
7948 7947
7949 7948 static struct aac_key_strings aac_fib_cmds[] = {
7950 7949 AAC_FIB_CMD_KEY_STRINGS,
7951 - -1, NULL
7950 + { -1, NULL }
7952 7951 };
7953 7952
7954 7953 static struct aac_key_strings aac_ctvm_subcmds[] = {
7955 7954 AAC_CTVM_SUBCMD_KEY_STRINGS,
7956 - -1, NULL
7955 + { -1, NULL }
7957 7956 };
7958 7957
7959 7958 static struct aac_key_strings aac_ct_subcmds[] = {
7960 7959 AAC_CT_SUBCMD_KEY_STRINGS,
7961 - -1, NULL
7960 + { -1, NULL }
7962 7961 };
7963 7962
7964 7963 static struct aac_key_strings aac_cl_subcmds[] = {
7965 7964 AAC_CL_SUBCMD_KEY_STRINGS,
7966 - -1, NULL
7965 + { -1, NULL }
7967 7966 };
7968 7967
7969 7968 static struct aac_key_strings aac_aif_subcmds[] = {
7970 7969 AAC_AIF_SUBCMD_KEY_STRINGS,
7971 - -1, NULL
7970 + { -1, NULL }
7972 7971 };
7973 7972
7974 7973 static struct aac_key_strings aac_ioctl_subcmds[] = {
7975 7974 AAC_IOCTL_SUBCMD_KEY_STRINGS,
7976 - -1, NULL
7975 + { -1, NULL }
7977 7976 };
7978 7977
7979 7978 static struct aac_key_strings aac_aifens[] = {
7980 7979 AAC_AIFEN_KEY_STRINGS,
7981 - -1, NULL
7980 + { -1, NULL }
7982 7981 };
7983 7982
7984 7983 /*
7985 7984 * The following function comes from Adaptec:
7986 7985 *
7987 7986 * Get the firmware print buffer parameters from the firmware,
7988 7987 * if the command was successful map in the address.
7989 7988 */
7990 7989 static int
7991 7990 aac_get_fw_debug_buffer(struct aac_softstate *softs)
7992 7991 {
7993 7992 if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP,
7994 7993 0, 0, 0, 0, NULL) == AACOK) {
7995 7994 uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1);
7996 7995 uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2);
7997 7996 uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3);
7998 7997 uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4);
7999 7998
8000 7999 if (mondrv_buf_size) {
8001 8000 uint32_t offset = mondrv_buf_paddrl - \
8002 8001 softs->pci_mem_base_paddr;
8003 8002
8004 8003 /*
8005 8004 * See if the address is already mapped in, and
8006 8005 * if so set it up from the base address
8007 8006 */
8008 8007 if ((mondrv_buf_paddrh == 0) &&
8009 8008 (offset + mondrv_buf_size < softs->map_size)) {
8010 8009 mutex_enter(&aac_prt_mutex);
8011 8010 softs->debug_buf_offset = offset;
8012 8011 softs->debug_header_size = mondrv_hdr_size;
8013 8012 softs->debug_buf_size = mondrv_buf_size;
8014 8013 softs->debug_fw_flags = 0;
8015 8014 softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
8016 8015 mutex_exit(&aac_prt_mutex);
8017 8016
8018 8017 return (AACOK);
8019 8018 }
8020 8019 }
8021 8020 }
8022 8021 return (AACERR);
8023 8022 }
8024 8023
8025 8024 int
8026 8025 aac_dbflag_on(struct aac_softstate *softs, int flag)
8027 8026 {
8028 8027 int debug_flags = softs ? softs->debug_flags : aac_debug_flags;
8029 8028
8030 8029 return ((debug_flags & (AACDB_FLAGS_FW_PRINT | \
8031 8030 AACDB_FLAGS_KERNEL_PRINT)) && (debug_flags & flag));
8032 8031 }
8033 8032
8034 8033 static void
8035 8034 aac_cmn_err(struct aac_softstate *softs, uint_t lev, char sl, int noheader)
8036 8035 {
8037 8036 if (noheader) {
8038 8037 if (sl) {
8039 8038 aac_fmt[0] = sl;
8040 8039 cmn_err(lev, aac_fmt, aac_prt_buf);
8041 8040 } else {
8042 8041 cmn_err(lev, &aac_fmt[1], aac_prt_buf);
8043 8042 }
8044 8043 } else {
8045 8044 if (sl) {
8046 8045 aac_fmt_header[0] = sl;
8047 8046 cmn_err(lev, aac_fmt_header,
8048 8047 softs->vendor_name, softs->instance,
8049 8048 aac_prt_buf);
8050 8049 } else {
8051 8050 cmn_err(lev, &aac_fmt_header[1],
8052 8051 softs->vendor_name, softs->instance,
8053 8052 aac_prt_buf);
8054 8053 }
8055 8054 }
8056 8055 }
8057 8056
8058 8057 /*
8059 8058 * The following function comes from Adaptec:
8060 8059 *
8061 8060 * Format and print out the data passed in to UART or console
8062 8061 * as specified by debug flags.
8063 8062 */
8064 8063 void
8065 8064 aac_printf(struct aac_softstate *softs, uint_t lev, const char *fmt, ...)
8066 8065 {
8067 8066 va_list args;
8068 8067 char sl; /* system log character */
8069 8068
8070 8069 mutex_enter(&aac_prt_mutex);
8071 8070 /* Set up parameters and call sprintf function to format the data */
8072 8071 if (strchr("^!?", fmt[0]) == NULL) {
8073 8072 sl = 0;
8074 8073 } else {
8075 8074 sl = fmt[0];
8076 8075 fmt++;
8077 8076 }
8078 8077 va_start(args, fmt);
8079 8078 (void) vsprintf(aac_prt_buf, fmt, args);
8080 8079 va_end(args);
8081 8080
8082 8081 /* Make sure the softs structure has been passed in for this section */
8083 8082 if (softs) {
8084 8083 if ((softs->debug_flags & AACDB_FLAGS_FW_PRINT) &&
8085 8084 /* If we are set up for a Firmware print */
8086 8085 (softs->debug_buf_size)) {
8087 8086 uint32_t count, i;
8088 8087
8089 8088 /* Make sure the string size is within boundaries */
8090 8089 count = strlen(aac_prt_buf);
8091 8090 if (count > softs->debug_buf_size)
8092 8091 count = (uint16_t)softs->debug_buf_size;
8093 8092
8094 8093 /*
8095 8094 * Wait for no more than AAC_PRINT_TIMEOUT for the
8096 8095 * previous message length to clear (the handshake).
8097 8096 */
8098 8097 for (i = 0; i < AAC_PRINT_TIMEOUT; i++) {
8099 8098 if (!PCI_MEM_GET32(softs,
8100 8099 softs->debug_buf_offset + \
8101 8100 AAC_FW_DBG_STRLEN_OFFSET))
8102 8101 break;
8103 8102
8104 8103 drv_usecwait(1000);
8105 8104 }
8106 8105
8107 8106 /*
8108 8107 * If the length is clear, copy over the message, the
8109 8108 * flags, and the length. Make sure the length is the
8110 8109 * last because that is the signal for the Firmware to
8111 8110 * pick it up.
8112 8111 */
8113 8112 if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \
8114 8113 AAC_FW_DBG_STRLEN_OFFSET)) {
8115 8114 PCI_MEM_REP_PUT8(softs,
8116 8115 softs->debug_buf_offset + \
8117 8116 softs->debug_header_size,
8118 8117 aac_prt_buf, count);
8119 8118 PCI_MEM_PUT32(softs,
8120 8119 softs->debug_buf_offset + \
8121 8120 AAC_FW_DBG_FLAGS_OFFSET,
8122 8121 softs->debug_fw_flags);
8123 8122 PCI_MEM_PUT32(softs,
8124 8123 softs->debug_buf_offset + \
8125 8124 AAC_FW_DBG_STRLEN_OFFSET, count);
8126 8125 } else {
8127 8126 cmn_err(CE_WARN, "UART output fail");
8128 8127 softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
8129 8128 }
8130 8129 }
8131 8130
8132 8131 /*
8133 8132 * If the Kernel Debug Print flag is set, send it off
8134 8133 * to the Kernel Debugger
8135 8134 */
8136 8135 if (softs->debug_flags & AACDB_FLAGS_KERNEL_PRINT)
8137 8136 aac_cmn_err(softs, lev, sl,
8138 8137 (softs->debug_flags & AACDB_FLAGS_NO_HEADERS));
8139 8138 } else {
8140 8139 /* Driver not initialized yet, no firmware or header output */
8141 8140 if (aac_debug_flags & AACDB_FLAGS_KERNEL_PRINT)
8142 8141 aac_cmn_err(softs, lev, sl, 1);
8143 8142 }
8144 8143 mutex_exit(&aac_prt_mutex);
8145 8144 }
8146 8145
8147 8146 /*
8148 8147 * Translate command number to description string
8149 8148 */
8150 8149 static char *
8151 8150 aac_cmd_name(int cmd, struct aac_key_strings *cmdlist)
8152 8151 {
8153 8152 int i;
8154 8153
8155 8154 for (i = 0; cmdlist[i].key != -1; i++) {
8156 8155 if (cmd == cmdlist[i].key)
8157 8156 return (cmdlist[i].message);
8158 8157 }
8159 8158 return (NULL);
8160 8159 }
8161 8160
8162 8161 static void
8163 8162 aac_print_scmd(struct aac_softstate *softs, struct aac_cmd *acp)
8164 8163 {
8165 8164 struct scsi_pkt *pkt = acp->pkt;
8166 8165 struct scsi_address *ap = &pkt->pkt_address;
8167 8166 int is_pd = 0;
8168 8167 int ctl = ddi_get_instance(softs->devinfo_p);
8169 8168 int tgt = ap->a_target;
8170 8169 int lun = ap->a_lun;
8171 8170 union scsi_cdb *cdbp = (void *)pkt->pkt_cdbp;
8172 8171 uchar_t cmd = cdbp->scc_cmd;
8173 8172 char *desc;
8174 8173
8175 8174 if (tgt >= AAC_MAX_LD) {
8176 8175 is_pd = 1;
8177 8176 ctl = ((struct aac_nondasd *)acp->dvp)->bus;
8178 8177 tgt = ((struct aac_nondasd *)acp->dvp)->tid;
8179 8178 lun = 0;
8180 8179 }
8181 8180
8182 8181 if ((desc = aac_cmd_name(cmd,
8183 8182 (struct aac_key_strings *)scsi_cmds)) == NULL) {
8184 8183 aac_printf(softs, CE_NOTE,
8185 8184 "SCMD> Unknown(0x%2x) --> c%dt%dL%d %s",
8186 8185 cmd, ctl, tgt, lun, is_pd ? "(pd)" : "");
8187 8186 return;
8188 8187 }
8189 8188
8190 8189 switch (cmd) {
8191 8190 case SCMD_READ:
8192 8191 case SCMD_WRITE:
8193 8192 aac_printf(softs, CE_NOTE,
8194 8193 "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
8195 8194 desc, GETG0ADDR(cdbp), GETG0COUNT(cdbp),
8196 8195 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
8197 8196 ctl, tgt, lun, is_pd ? "(pd)" : "");
8198 8197 break;
8199 8198 case SCMD_READ_G1:
8200 8199 case SCMD_WRITE_G1:
8201 8200 aac_printf(softs, CE_NOTE,
8202 8201 "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
8203 8202 desc, GETG1ADDR(cdbp), GETG1COUNT(cdbp),
8204 8203 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
8205 8204 ctl, tgt, lun, is_pd ? "(pd)" : "");
8206 8205 break;
8207 8206 case SCMD_READ_G4:
8208 8207 case SCMD_WRITE_G4:
8209 8208 aac_printf(softs, CE_NOTE,
8210 8209 "SCMD> %s 0x%x.%08x[%d] %s --> c%dt%dL%d %s",
8211 8210 desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp),
8212 8211 GETG4COUNT(cdbp),
8213 8212 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
8214 8213 ctl, tgt, lun, is_pd ? "(pd)" : "");
8215 8214 break;
8216 8215 case SCMD_READ_G5:
8217 8216 case SCMD_WRITE_G5:
8218 8217 aac_printf(softs, CE_NOTE,
8219 8218 "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s",
8220 8219 desc, GETG5ADDR(cdbp), GETG5COUNT(cdbp),
8221 8220 (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr",
8222 8221 ctl, tgt, lun, is_pd ? "(pd)" : "");
8223 8222 break;
8224 8223 default:
8225 8224 aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s",
8226 8225 desc, ctl, tgt, lun, is_pd ? "(pd)" : "");
8227 8226 }
8228 8227 }
8229 8228
8230 8229 void
8231 8230 aac_print_fib(struct aac_softstate *softs, struct aac_slot *slotp)
8232 8231 {
8233 8232 struct aac_cmd *acp = slotp->acp;
8234 8233 struct aac_fib *fibp = slotp->fibp;
8235 8234 ddi_acc_handle_t acc = slotp->fib_acc_handle;
8236 8235 uint16_t fib_size;
8237 8236 uint32_t fib_cmd, sub_cmd;
8238 8237 char *cmdstr, *subcmdstr;
8239 8238 char *caller;
8240 8239 int i;
8241 8240
8242 8241 if (acp) {
8243 8242 if (!(softs->debug_fib_flags & acp->fib_flags))
8244 8243 return;
8245 8244 if (acp->fib_flags & AACDB_FLAGS_FIB_SCMD)
8246 8245 caller = "SCMD";
8247 8246 else if (acp->fib_flags & AACDB_FLAGS_FIB_IOCTL)
8248 8247 caller = "IOCTL";
8249 8248 else if (acp->fib_flags & AACDB_FLAGS_FIB_SRB)
8250 8249 caller = "SRB";
8251 8250 else
8252 8251 return;
8253 8252 } else {
8254 8253 if (!(softs->debug_fib_flags & AACDB_FLAGS_FIB_SYNC))
8255 8254 return;
8256 8255 caller = "SYNC";
8257 8256 }
8258 8257
8259 8258 fib_cmd = ddi_get16(acc, &fibp->Header.Command);
8260 8259 cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds);
8261 8260 sub_cmd = (uint32_t)-1;
8262 8261 subcmdstr = NULL;
8263 8262
8264 8263 /* Print FIB header */
8265 8264 if (softs->debug_fib_flags & AACDB_FLAGS_FIB_HEADER) {
8266 8265 aac_printf(softs, CE_NOTE, "FIB> from %s", caller);
8267 8266 aac_printf(softs, CE_NOTE, " XferState %d",
8268 8267 ddi_get32(acc, &fibp->Header.XferState));
8269 8268 aac_printf(softs, CE_NOTE, " Command %d",
8270 8269 ddi_get16(acc, &fibp->Header.Command));
8271 8270 aac_printf(softs, CE_NOTE, " StructType %d",
8272 8271 ddi_get8(acc, &fibp->Header.StructType));
8273 8272 aac_printf(softs, CE_NOTE, " Flags 0x%x",
8274 8273 ddi_get8(acc, &fibp->Header.Flags));
8275 8274 aac_printf(softs, CE_NOTE, " Size %d",
8276 8275 ddi_get16(acc, &fibp->Header.Size));
8277 8276 aac_printf(softs, CE_NOTE, " SenderSize %d",
8278 8277 ddi_get16(acc, &fibp->Header.SenderSize));
8279 8278 aac_printf(softs, CE_NOTE, " SenderAddr 0x%x",
8280 8279 ddi_get32(acc, &fibp->Header.SenderFibAddress));
8281 8280 aac_printf(softs, CE_NOTE, " RcvrAddr 0x%x",
8282 8281 ddi_get32(acc, &fibp->Header.ReceiverFibAddress));
8283 8282 aac_printf(softs, CE_NOTE, " SenderData 0x%x",
8284 8283 ddi_get32(acc, &fibp->Header.SenderData));
8285 8284 }
8286 8285
8287 8286 /* Print FIB data */
8288 8287 switch (fib_cmd) {
8289 8288 case ContainerCommand:
8290 8289 sub_cmd = ddi_get32(acc,
8291 8290 (void *)&(((uint32_t *)(void *)&fibp->data[0])[0]));
8292 8291 subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds);
8293 8292 if (subcmdstr == NULL)
8294 8293 break;
8295 8294
8296 8295 switch (sub_cmd) {
8297 8296 case VM_ContainerConfig: {
8298 8297 struct aac_Container *pContainer =
8299 8298 (struct aac_Container *)fibp->data;
8300 8299
8301 8300 fib_cmd = sub_cmd;
8302 8301 cmdstr = subcmdstr;
8303 8302 sub_cmd = (uint32_t)-1;
8304 8303 subcmdstr = NULL;
8305 8304
8306 8305 sub_cmd = ddi_get32(acc,
8307 8306 &pContainer->CTCommand.command);
8308 8307 subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds);
8309 8308 if (subcmdstr == NULL)
8310 8309 break;
8311 8310 aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)",
8312 8311 subcmdstr,
8313 8312 ddi_get32(acc, &pContainer->CTCommand.param[0]),
8314 8313 ddi_get32(acc, &pContainer->CTCommand.param[1]),
8315 8314 ddi_get32(acc, &pContainer->CTCommand.param[2]));
8316 8315 return;
8317 8316 }
8318 8317
8319 8318 case VM_Ioctl:
8320 8319 fib_cmd = sub_cmd;
8321 8320 cmdstr = subcmdstr;
8322 8321 sub_cmd = (uint32_t)-1;
8323 8322 subcmdstr = NULL;
8324 8323
8325 8324 sub_cmd = ddi_get32(acc,
8326 8325 (void *)&(((uint32_t *)(void *)&fibp->data[0])[4]));
8327 8326 subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds);
8328 8327 break;
8329 8328
8330 8329 case VM_CtBlockRead:
8331 8330 case VM_CtBlockWrite: {
8332 8331 struct aac_blockread *br =
8333 8332 (struct aac_blockread *)fibp->data;
8334 8333 struct aac_sg_table *sg = &br->SgMap;
8335 8334 uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
8336 8335
8337 8336 aac_printf(softs, CE_NOTE,
8338 8337 "FIB> %s Container %d 0x%x/%d", subcmdstr,
8339 8338 ddi_get32(acc, &br->ContainerId),
8340 8339 ddi_get32(acc, &br->BlockNumber),
8341 8340 ddi_get32(acc, &br->ByteCount));
8342 8341 for (i = 0; i < sgcount; i++)
8343 8342 aac_printf(softs, CE_NOTE,
8344 8343 " %d: 0x%08x/%d", i,
8345 8344 ddi_get32(acc, &sg->SgEntry[i].SgAddress),
8346 8345 ddi_get32(acc, &sg->SgEntry[i]. \
8347 8346 SgByteCount));
8348 8347 return;
8349 8348 }
8350 8349 }
8351 8350 break;
8352 8351
8353 8352 case ContainerCommand64: {
8354 8353 struct aac_blockread64 *br =
8355 8354 (struct aac_blockread64 *)fibp->data;
8356 8355 struct aac_sg_table64 *sg = &br->SgMap64;
8357 8356 uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
8358 8357 uint64_t sgaddr;
8359 8358
8360 8359 sub_cmd = br->Command;
8361 8360 subcmdstr = NULL;
8362 8361 if (sub_cmd == VM_CtHostRead64)
8363 8362 subcmdstr = "VM_CtHostRead64";
8364 8363 else if (sub_cmd == VM_CtHostWrite64)
8365 8364 subcmdstr = "VM_CtHostWrite64";
8366 8365 else
8367 8366 break;
8368 8367
8369 8368 aac_printf(softs, CE_NOTE,
8370 8369 "FIB> %s Container %d 0x%x/%d", subcmdstr,
8371 8370 ddi_get16(acc, &br->ContainerId),
8372 8371 ddi_get32(acc, &br->BlockNumber),
8373 8372 ddi_get16(acc, &br->SectorCount));
8374 8373 for (i = 0; i < sgcount; i++) {
8375 8374 sgaddr = ddi_get64(acc,
8376 8375 &sg->SgEntry64[i].SgAddress);
8377 8376 aac_printf(softs, CE_NOTE,
8378 8377 " %d: 0x%08x.%08x/%d", i,
8379 8378 AAC_MS32(sgaddr), AAC_LS32(sgaddr),
8380 8379 ddi_get32(acc, &sg->SgEntry64[i]. \
8381 8380 SgByteCount));
8382 8381 }
8383 8382 return;
8384 8383 }
8385 8384
8386 8385 case RawIo: {
8387 8386 struct aac_raw_io *io = (struct aac_raw_io *)fibp->data;
8388 8387 struct aac_sg_tableraw *sg = &io->SgMapRaw;
8389 8388 uint32_t sgcount = ddi_get32(acc, &sg->SgCount);
8390 8389 uint64_t sgaddr;
8391 8390
8392 8391 aac_printf(softs, CE_NOTE,
8393 8392 "FIB> RawIo Container %d 0x%llx/%d 0x%x",
8394 8393 ddi_get16(acc, &io->ContainerId),
8395 8394 ddi_get64(acc, &io->BlockNumber),
8396 8395 ddi_get32(acc, &io->ByteCount),
8397 8396 ddi_get16(acc, &io->Flags));
8398 8397 for (i = 0; i < sgcount; i++) {
8399 8398 sgaddr = ddi_get64(acc, &sg->SgEntryRaw[i].SgAddress);
8400 8399 aac_printf(softs, CE_NOTE, " %d: 0x%08x.%08x/%d", i,
8401 8400 AAC_MS32(sgaddr), AAC_LS32(sgaddr),
8402 8401 ddi_get32(acc, &sg->SgEntryRaw[i].SgByteCount));
8403 8402 }
8404 8403 return;
8405 8404 }
8406 8405
8407 8406 case ClusterCommand:
8408 8407 sub_cmd = ddi_get32(acc,
8409 8408 (void *)&(((uint32_t *)(void *)fibp->data)[0]));
8410 8409 subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds);
8411 8410 break;
8412 8411
8413 8412 case AifRequest:
8414 8413 sub_cmd = ddi_get32(acc,
8415 8414 (void *)&(((uint32_t *)(void *)fibp->data)[0]));
8416 8415 subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds);
8417 8416 break;
8418 8417
8419 8418 default:
8420 8419 break;
8421 8420 }
8422 8421
8423 8422 fib_size = ddi_get16(acc, &(fibp->Header.Size));
8424 8423 if (subcmdstr)
8425 8424 aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
8426 8425 subcmdstr, fib_size);
8427 8426 else if (cmdstr && sub_cmd == (uint32_t)-1)
8428 8427 aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d",
8429 8428 cmdstr, fib_size);
8430 8429 else if (cmdstr)
8431 8430 aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d",
8432 8431 cmdstr, sub_cmd, fib_size);
8433 8432 else
8434 8433 aac_printf(softs, CE_NOTE, "FIB> Unknown(0x%x), sz=%d",
8435 8434 fib_cmd, fib_size);
8436 8435 }
8437 8436
8438 8437 static void
8439 8438 aac_print_aif(struct aac_softstate *softs, struct aac_aif_command *aif)
8440 8439 {
8441 8440 int aif_command;
8442 8441 uint32_t aif_seqnumber;
8443 8442 int aif_en_type;
8444 8443 char *str;
8445 8444
8446 8445 aif_command = LE_32(aif->command);
8447 8446 aif_seqnumber = LE_32(aif->seqNumber);
8448 8447 aif_en_type = LE_32(aif->data.EN.type);
8449 8448
8450 8449 switch (aif_command) {
8451 8450 case AifCmdEventNotify:
8452 8451 str = aac_cmd_name(aif_en_type, aac_aifens);
8453 8452 if (str)
8454 8453 aac_printf(softs, CE_NOTE, "AIF! %s", str);
8455 8454 else
8456 8455 aac_printf(softs, CE_NOTE, "AIF! Unknown(0x%x)",
8457 8456 aif_en_type);
8458 8457 break;
8459 8458
8460 8459 case AifCmdJobProgress:
8461 8460 switch (LE_32(aif->data.PR[0].status)) {
8462 8461 case AifJobStsSuccess:
8463 8462 str = "success"; break;
8464 8463 case AifJobStsFinished:
8465 8464 str = "finished"; break;
8466 8465 case AifJobStsAborted:
8467 8466 str = "aborted"; break;
8468 8467 case AifJobStsFailed:
8469 8468 str = "failed"; break;
8470 8469 case AifJobStsSuspended:
8471 8470 str = "suspended"; break;
8472 8471 case AifJobStsRunning:
8473 8472 str = "running"; break;
8474 8473 default:
8475 8474 str = "unknown"; break;
8476 8475 }
8477 8476 aac_printf(softs, CE_NOTE,
8478 8477 "AIF! JobProgress (%d) - %s (%d, %d)",
8479 8478 aif_seqnumber, str,
8480 8479 LE_32(aif->data.PR[0].currentTick),
8481 8480 LE_32(aif->data.PR[0].finalTick));
8482 8481 break;
8483 8482
8484 8483 case AifCmdAPIReport:
8485 8484 aac_printf(softs, CE_NOTE, "AIF! APIReport (%d)",
8486 8485 aif_seqnumber);
8487 8486 break;
8488 8487
8489 8488 case AifCmdDriverNotify:
8490 8489 aac_printf(softs, CE_NOTE, "AIF! DriverNotify (%d)",
8491 8490 aif_seqnumber);
8492 8491 break;
8493 8492
8494 8493 default:
8495 8494 aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)",
8496 8495 aif_command, aif_seqnumber);
8497 8496 break;
8498 8497 }
8499 8498 }
8500 8499
8501 8500 #endif /* DEBUG */
↓ open down ↓ |
510 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX