Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c
+++ new/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14 14 */
15 15
16 16 /*
17 17 * This module contains routines that program the controller. All
18 18 * operations viz., initialization of controller, submision &
19 19 * retrieval of commands, enabling & disabling of interrupts,
20 20 * checking interrupt status are performed here.
21 21 */
22 22
23 23 #include <sys/sdt.h>
24 24 #include "cpqary3.h"
25 25
26 26 /*
27 27 * Local Functions Definitions
28 28 */
29 29 uint8_t cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p);
30 30 uint8_t cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p);
31 31 uint8_t cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p);
32 32 uint8_t cpqary3_check_ctlr_init(cpqary3_t *);
33 33
34 34 /*
35 35 * Function : cpqary3_check_simple_ctlr_intr
36 36 * Description : This routine determines if the controller did interrupt.
37 37 * Called By : cpqary3_hw_isr()
38 38 * Parameters : per-controller
39 39 * Calls : None
40 40 * Return Values: SUCCESS : This controller did interrupt.
41 41 * FAILURE : It did not.
42 42 */
43 43 uint8_t
44 44 cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p)
45 45 {
46 46 uint32_t intr_pending_mask = 0;
47 47
48 48 /*
49 49 * Read the Interrupt Status Register and
50 50 * if bit 3 is set, it indicates that we have completed commands
51 51 * in the controller
52 52 */
53 53 intr_pending_mask = cpqary3p->bddef->bd_intrpendmask;
54 54
55 55 if (intr_pending_mask &
56 56 (ddi_get32(cpqary3p->isr_handle, (uint32_t *)cpqary3p->isr)))
57 57 return (CPQARY3_SUCCESS);
58 58
59 59 return (CPQARY3_FAILURE);
60 60 }
61 61
62 62 /*
63 63 * Function : cpqary3_check_perf_ctlr_intr
64 64 * Description : This routine determines if the
65 65 * controller did interrupt.
66 66 * Called By : cpqary3_hw_isr()
67 67 * Parameters : per-controller
68 68 * Calls : None
69 69 * Return Values: SUCCESS : This controller did interrupt.
70 70 * FAILURE : It did not.
71 71 */
72 72 uint8_t
73 73 cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p)
74 74 {
75 75 /*
76 76 * Read the Interrupt Status Register and
77 77 * if bit 3 is set, it indicates that we have completed commands
78 78 * in the controller
79 79 */
80 80 if (0x1 & (ddi_get32(cpqary3p->isr_handle,
81 81 (uint32_t *)cpqary3p->isr))) {
82 82 return (CPQARY3_SUCCESS);
83 83 }
84 84
85 85 return (CPQARY3_FAILURE);
86 86 }
87 87
88 88 /*
89 89 * Function : cpqary3_check_perf_e200_intr
90 90 * Description : This routine determines if the controller
91 91 * did interrupt.
92 92 * Called By : cpqary3_hw_isr()
93 93 * Parameters : per-controller
94 94 * Calls : None
95 95 * Return Values: SUCCESS : This controller did interrupt.
96 96 * FAILURE : It did not.
97 97 */
98 98 uint8_t
99 99 cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p)
100 100 {
101 101 /*
102 102 * Read the Interrupt Status Register and
103 103 * if bit 3 is set, it indicates that we have completed commands
104 104 * in the controller
105 105 */
106 106 if (0x4 & (ddi_get32(cpqary3p->isr_handle,
107 107 (uint32_t *)cpqary3p->isr))) {
108 108 return (CPQARY3_SUCCESS);
109 109 }
110 110
111 111 return (CPQARY3_FAILURE);
112 112 }
113 113
114 114
115 115 /*
116 116 * Function : cpqary3_retrieve
117 117 * Description : This routine retrieves the completed command from the
118 118 * controller reply queue.
119 119 * and processes the completed commands.
120 120 * Called By : cpqary3_sw_isr(), cpqary3_handle_flag_nointr()
121 121 * Parameters : per-controller
122 122 * Calls : packet completion routines
123 123 * Return Values: SUCCESS : A completed command has been retrieved
124 124 * and processed.
125 125 * FAILURE : No completed command was in the controller.
126 126 */
127 127 uint8_t
128 128 cpqary3_retrieve(cpqary3_t *cpqary3p)
129 129 {
130 130 uint32_t tag;
131 131 uint32_t CmdsOutMax;
132 132 cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
133 133 cpqary3_drvr_replyq_t *replyq_ptr;
134 134
135 135 /*
136 136 * Get the Reply Command List Addr
137 137 * Update the returned Tag in that particular command structure.
138 138 * If a valid one, de-q that from the SUBMITTED Q and
139 139 * enqueue that to the RETRIEVED Q.
140 140 */
141 141
142 142 RETURN_FAILURE_IF_NULL(cpqary3p);
143 143
144 144 /* PERF */
145 145 replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
146 146 CmdsOutMax = cpqary3p->ctlr_maxcmds;
147 147
148 148 while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
149 149 replyq_ptr->cyclic_indicator) {
150 150 /* command has completed */
151 151 /* Get the tag */
152 152
153 153 tag = replyq_ptr->replyq_headptr[0];
154 154 if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax / 3) * 3) {
155 155 cmn_err(CE_WARN,
156 156 "CPQary3 : HBA returned Spurious Tag");
157 157 return (CPQARY3_FAILURE);
158 158 }
159 159
160 160 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
161 161 tag >> CPQARY3_GET_MEM_TAG];
162 162 cpqary3_cmdpvtp->cmdlist_memaddr->
163 163 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
164 164 mutex_enter(&cpqary3p->sw_mutex);
165 165 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
166 166 mutex_exit(&cpqary3p->sw_mutex);
167 167
168 168 /* Traverse to the next command in reply queue */
169 169
170 170 ++replyq_ptr->index;
171 171 if (replyq_ptr->index == replyq_ptr->max_index) {
172 172 replyq_ptr->index = 0;
173 173 /* Toggle at wraparound */
174 174 replyq_ptr->cyclic_indicator =
175 175 (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
176 176 replyq_ptr->replyq_headptr =
177 177 /* LINTED: alignment */
178 178 (uint32_t *)(replyq_ptr->replyq_start_addr);
179 179 } else {
180 180 replyq_ptr->replyq_headptr += 2;
181 181 }
182 182 }
183 183 /* PERF */
184 184
185 185 return (CPQARY3_SUCCESS);
186 186 }
187 187
188 188
189 189 /*
190 190 * Function : cpqary3_poll_retrieve
191 191 * Description : This routine retrieves the completed command from the
192 192 * controller reply queue in poll mode.
193 193 * and processes the completed commands.
194 194 * Called By : cpqary3_poll
195 195 * Parameters : per-controller
196 196 * Calls : packet completion routines
197 197 * Return Values: If the polled command is completed, send back a success.
198 198 * If not return failure.
199 199 */
200 200 uint8_t
201 201 cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag)
202 202 {
203 203 uint32_t tag;
204 204 uint32_t CmdsOutMax;
205 205 cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
206 206 cpqary3_drvr_replyq_t *replyq_ptr;
207 207 uint32_t temp_tag;
208 208 uint8_t tag_flag = 0;
209 209
210 210 RETURN_FAILURE_IF_NULL(cpqary3p);
211 211
212 212 /* PERF */
213 213 replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
214 214 CmdsOutMax = cpqary3p->cmdmemlistp->max_memcnt;
215 215
216 216 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
217 217 while ((tag = ddi_get32(cpqary3p->opq_handle,
218 218 (uint32_t *)cpqary3p->opq)) != 0xFFFFFFFF) {
219 219 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
220 220 tag >> CPQARY3_GET_MEM_TAG];
221 221 cpqary3_cmdpvtp->cmdlist_memaddr->
222 222 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
223 223 temp_tag = cpqary3_cmdpvtp->tag.tag_value;
224 224
225 225 if (temp_tag == poll_tag)
226 226 tag_flag = 1;
227 227 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
228 228 }
229 229 } else {
230 230 while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
231 231 replyq_ptr->cyclic_indicator) {
232 232 /* command has completed */
233 233 /* Get the tag */
234 234 tag = replyq_ptr->replyq_headptr[0];
235 235
236 236 if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax/3)*3) {
237 237 cmn_err(CE_WARN,
238 238 "CPQary3 : HBA returned Spurious Tag");
239 239 return (CPQARY3_FAILURE);
240 240 }
241 241
242 242 cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
243 243 tag >> CPQARY3_GET_MEM_TAG];
244 244 cpqary3_cmdpvtp->cmdlist_memaddr->
245 245 Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
246 246 temp_tag = cpqary3_cmdpvtp->tag.tag_value;
247 247
248 248 if (temp_tag == poll_tag)
249 249 tag_flag = 1;
250 250
251 251 cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
252 252
253 253 /* Traverse to the next command in reply queue */
254 254 ++replyq_ptr->index;
255 255 if (replyq_ptr->index == replyq_ptr->max_index) {
256 256 replyq_ptr->index = 0;
257 257 /* Toggle at wraparound */
258 258 replyq_ptr->cyclic_indicator =
259 259 (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
260 260 replyq_ptr->replyq_headptr =
261 261 /* LINTED: alignment */
262 262 (uint32_t *)(replyq_ptr->replyq_start_addr);
263 263 } else {
264 264 replyq_ptr->replyq_headptr += 2;
265 265 }
266 266 }
267 267 }
268 268 /* PERF */
269 269 if (tag_flag) {
270 270 return (CPQARY3_SUCCESS);
271 271 }
272 272
273 273 return (CPQARY3_FAILURE);
274 274 }
275 275
276 276 /*
277 277 * Function : cpqary3_submit
278 278 * Description : This routine submits the command to the Inbound Post Q.
279 279 * Called By : cpqary3_transport(), cpqary3_send_NOE_command(),
280 280 * cpqary3_disable_NOE_command(),
281 281 * cpqary3_handle_flag_nointr(),
282 282 * cpqary3_tick_hdlr(), cpqary3_synccmd_send()
283 283 * Parameters : per-controller, physical address
284 284 * Calls : None
285 285 * Return Values: None
286 286 */
287 287 int32_t
288 288 cpqary3_submit(cpqary3_t *cpqary3p, uint32_t cmd_phyaddr)
289 289 {
290 290 uint32_t phys_addr = 0;
291 291 uint8_t retval = 0;
292 292
293 293 /*
294 294 * Write the Physical Address of the command-to-be-submitted
295 295 * into the Controller's Inbound Post Q.
296 296 */
297 297
298 298 ASSERT(cpqary3p != NULL);
299 299
300 300 #ifdef AMD64_DEBUG
301 301 {
302 302 char debug_char;
303 303 uint32_t tmp_cmd_phyaddr;
304 304
305 305 tmp_cmd_phyaddr = (uint32_t)(cmd_phyaddr & 0XFFFFFFFF);
306 306
307 307 cmn_err(CE_WARN, "CPQary3: cmd_phyaddr = %lX\n tmp_cmd_phyaddr = %lX",
308 308 cmd_phyaddr, tmp_cmd_phyaddr);
309 309
310 310 debug_enter(&debug_char);
311 311 ddi_put32(cpqary3p->ipq_handle, (uint32_t *)cpqary3p->ipq, cmd_phyaddr);
312 312 }
313 313 #endif
314 314
315 315
316 316 /* CONTROLLER_LOCKUP */
317 317 if (cpqary3p->controller_lockup == CPQARY3_TRUE) {
318 318 retval = EIO;
319 319 return (retval);
320 320 }
321 321 /* CONTROLLER_LOCKUP */
322 322
323 323 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
324 324 ddi_put32(cpqary3p->ipq_handle,
325 325 (uint32_t *)cpqary3p->ipq, cmd_phyaddr);
326 326 } else {
327 327 /* The driver always uses the 0th block fetch count always */
328 328 phys_addr = cmd_phyaddr | 0 | 0x1;
329 329 ddi_put32(cpqary3p->ipq_handle,
330 330 (uint32_t *)cpqary3p->ipq, phys_addr);
331 331 }
332 332
333 333 /* PERF */
334 334
335 335 /*
336 336 * Command submission can NEVER FAIL since the number of commands that
337 337 * can reside in the controller at any time is 1024 and our memory
338 338 * allocation is for 225 commands ONLY. Thus, at any given time the
339 339 * maximum number of commands in the controller is 225.
340 340 */
341 341
342 342 /* CONTROLLER_LOCKUP */
343 343 return (retval);
344 344 /* CONTROLLER_LOCKUP */
345 345
346 346 }
347 347
348 348
349 349 /*
350 350 * Function : cpqary3_intr_onoff
351 351 * Description : This routine enables/disables the HBA interrupt.
352 352 * Called By : cpqary3_attach(), ry3_handle_flag_nointr(),
353 353 * cpqary3_tick_hdlr(), cpqary3_init_ctlr_resource()
354 354 * Parameters : per-controller, flag stating enable/disable
355 355 * Calls : None
356 356 * Return Values: None
357 357 */
358 358 void
359 359 cpqary3_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag)
360 360 {
361 361 uint32_t intr = 0;
362 362 uint32_t intr_mask = 0;
363 363
364 364 /*
365 365 * Enable or disable the interrupt based on the flag
366 366 * Read the Interrupt Mask Register first and then update it
367 367 * accordingly
368 368 */
369 369
370 370 ASSERT(cpqary3p != NULL);
371 371
372 372 intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr);
373 373 intr_mask = cpqary3p->bddef->bd_intrmask;
374 374
375 375 if (flag == CPQARY3_INTR_ENABLE) {
376 376 ddi_put32(cpqary3p->imr_handle,
377 377 (uint32_t *)cpqary3p->imr, intr & ~(intr_mask));
378 378 } else {
379 379 ddi_put32(cpqary3p->imr_handle,
380 380 (uint32_t *)cpqary3p->imr, (intr | intr_mask));
381 381 }
382 382 }
383 383
384 384
385 385 /*
386 386 * Function : cpqary3_lockup_intr_onoff
387 387 * Description : This routine enables/disables the lockup interrupt.
388 388 * Called By : cpqary3_attach(), cpqary3_handle_flag_nointr(),
389 389 * cpqary3_tick_hdlr(), cpqary3_hw_isr,
390 390 * cpqary3_init_ctlr_resource()
391 391 * Parameters : per-controller, flag stating enable/disable
392 392 * Calls : None
393 393 * Return Values: None
394 394 */
395 395 void
396 396 cpqary3_lockup_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag)
397 397 {
398 398 uint32_t intr = 0;
399 399 uint32_t intr_lockup_mask = 0;
400 400
401 401 /*
402 402 * Enable or disable the interrupt based on the flag
403 403 * Read the Interrupt Mask Register first and then update it
404 404 * accordingly
405 405 */
406 406
407 407 ASSERT(cpqary3p != NULL);
408 408
409 409 intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr);
410 410 intr_lockup_mask = cpqary3p->bddef->bd_lockup_intrmask;
411 411
412 412 if (flag == CPQARY3_INTR_ENABLE) {
413 413 ddi_put32(cpqary3p->imr_handle,
414 414 (uint32_t *)cpqary3p->imr, intr & ~(intr_lockup_mask));
415 415 } else {
416 416 ddi_put32(cpqary3p->imr_handle,
417 417 (uint32_t *)cpqary3p->imr, (intr | intr_lockup_mask));
418 418 }
419 419 }
420 420
421 421 /*
422 422 * Function : cpqary3_init_ctlr
423 423 * Description : This routine initialises the HBA to Simple Transport
424 424 * Method. Refer to CISS for more information.
425 425 * It checks the readiness of the HBA.
426 426 * Called By : cpqary3_init_ctlr_resource()
427 427 * Parameters : per-controller(), physical address()
428 428 * Calls : cpqary3_check_ctlr_init
429 429 * Return Values: SUCCESS / FAILURE
430 430 * [Shall return failure if the initialization of the
431 431 * controller to the Simple Transport Method fails]
432 432 */
433 433 uint8_t
434 434 cpqary3_init_ctlr(cpqary3_t *cpqary3p)
435 435 {
436 436 uint8_t cntr;
437 437 uint8_t signature[4] = { 'C', 'I', 'S', 'S' };
438 438 volatile CfgTable_t *ctp;
439 439 volatile CfgTrans_Perf_t *perf_cfg;
440 440 cpqary3_phyctg_t *cpqary3_phyctgp;
441 441 uint32_t phy_addr;
442 442 size_t cmd_size;
443 443 uint32_t queue_depth;
444 444 uint32_t CmdsOutMax;
445 445 uint32_t BlockFetchCnt[8];
446 446 caddr_t replyq_start_addr = NULL;
447 447 /* SG */
448 448 uint32_t max_blk_fetch_cnt = 0;
449 449 uint32_t max_sg_cnt = 0;
450 450 uint32_t optimal_sg = 0;
451 451 uint32_t optimal_sg_size = 0;
452 452 /* Header + Request + Error */
453 453 uint32_t size_of_HRE = 0;
454 454 uint32_t size_of_cmdlist = 0;
455 455 /* SG */
456 456
457 457 RETURN_FAILURE_IF_NULL(cpqary3p);
458 458 ctp = (CfgTable_t *)cpqary3p->ct;
459 459 perf_cfg = (CfgTrans_Perf_t *)cpqary3p->cp;
460 460
461 461 /* QUEUE CHANGES */
462 462 cpqary3p->drvr_replyq =
463 463 (cpqary3_drvr_replyq_t *)MEM_ZALLOC(sizeof (cpqary3_drvr_replyq_t));
464 464 /* QUEUE CHANGES */
465 465
466 466 if (!cpqary3_check_ctlr_init(cpqary3p))
467 467 return (CPQARY3_FAILURE);
468 468
469 469 DTRACE_PROBE1(ctlr_init_start, CfgTable_t *, ctp);
470 470
471 471 /*
472 472 * Validate the signature - should be "CISS"
473 473 * Use of cntr in the for loop does not suggest a counter - it just
474 474 * saves declaration of another variable.
475 475 */
476 476
477 477 for (cntr = 0; cntr < 4; cntr++) {
478 478 if (DDI_GET8(cpqary3p, &ctp->Signature[cntr]) !=
479 479 signature[cntr]) {
480 480 cmn_err(CE_WARN, "CPQary3 : Controller NOT ready");
481 481 cmn_err(CE_WARN, "CPQary3 : _cpqary3_init_ctlr : "
482 482 "Signature not stamped");
483 483 return (CPQARY3_FAILURE);
484 484 }
485 485 }
486 486
487 487
488 488 if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
489 489 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
490 490
491 491 if (CmdsOutMax == 0) {
492 492 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
493 493 "Commands set to Zero\n");
494 494 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
495 495 "initialization \n");
496 496 return (CPQARY3_FAILURE);
497 497 }
498 498
499 499 cpqary3p->ctlr_maxcmds = CmdsOutMax;
500 500 cpqary3p->sg_cnt = CPQARY3_SG_CNT;
501 501
502 502 queue_depth = cpqary3p->ctlr_maxcmds;
503 503 cmd_size = (8 * queue_depth);
504 504 /* QUEUE CHANGES */
505 505 cpqary3p->drvr_replyq->cyclic_indicator =
506 506 CPQARY3_REPLYQ_INIT_CYCLIC_IND;
507 507 cpqary3p->drvr_replyq->simple_cyclic_indicator =
508 508 CPQARY3_REPLYQ_INIT_CYCLIC_IND;
509 509 cpqary3p->drvr_replyq->max_index = cpqary3p->ctlr_maxcmds;
510 510 cpqary3p->drvr_replyq->simple_index = 0;
511 511 replyq_start_addr = MEM_ZALLOC(cmd_size);
512 512 bzero(replyq_start_addr, cmd_size);
513 513 cpqary3p->drvr_replyq->replyq_headptr =
514 514 /* LINTED: alignment */
515 515 (uint32_t *)replyq_start_addr;
516 516 cpqary3p->drvr_replyq->replyq_simple_ptr =
517 517 /* LINTED: alignment */
518 518 (uint32_t *)replyq_start_addr;
519 519 cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
520 520
521 521 /* PERF */
522 522
523 523 /*
524 524 * Check for support of SIMPLE Transport Method
525 525 */
526 526 if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport) &
527 527 CFGTBL_XPORT_SIMPLE)) {
528 528 cmn_err(CE_WARN, "CPQary3 : Controller "
529 529 "NOT YET INITIALIZED");
530 530 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
531 531 "try again later \n");
532 532 return (CPQARY3_FAILURE);
533 533 }
534 534
535 535 /*
536 536 * Configuration Table Initialization
537 537 * Set bit 0 of InBound Door Bell Reg to inform the controller
538 538 * about the changes related to the Configuration table
539 539 */
540 540 DTRACE_PROBE(cfgtable_init_start);
541 541
542 542 DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest,
543 543 CFGTBL_XPORT_SIMPLE);
544 544 ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr,
545 545 ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) |
546 546 CFGTBL_CHANGE_REQ);
547 547
548 548 /*
549 549 * Check whether the controller is ready
550 550 */
551 551
552 552 cntr = 0;
553 553 while (ddi_get32(cpqary3p->idr_handle,
554 554 (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) {
555 555 drv_usecwait(1000000); /* Wait for 1 Sec. */
556 556 cntr++;
557 557
558 558 /*
559 559 * Wait for a maximum of 90 seconds. No f/w should take
560 560 * more than 90 secs to initialize. If the controller
561 561 * is not ready even after 90 secs, it suggests that
562 562 * something is wrong
563 563 * (wrt the controller, what else) !!!
564 564 */
565 565
566 566 if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ {
567 567 cmn_err(CE_CONT, "CPQary3 : Controller "
568 568 "Initialization Failed \n");
569 569 return (CPQARY3_FAILURE);
570 570 }
571 571 }
572 572
573 573 DTRACE_PROBE(cfgtable_init_done);
574 574
575 575 /*
576 576 * Check whether controller accepts the requested method of
577 577 * transport
578 578 */
579 579 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
580 580 CFGTBL_XPORT_SIMPLE)) {
581 581 cmn_err(CE_CONT, "CPQary3 : Failed to Initialize "
582 582 "Controller \n");
583 583 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
584 584 "try again later\n");
585 585 return (CPQARY3_FAILURE);
586 586 }
587 587
588 588 DTRACE_PROBE(ctlr_init_simple);
589 589
590 590 /*
591 591 * Check if Controller is ready to accept Commands
592 592 */
593 593
594 594 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
595 595 CFGTBL_ACC_CMDS)) {
596 596 cmn_err(CE_CONT, "CPQary3: Controller NOT ready to "
597 597 "accept Commands \n");
598 598 return (CPQARY3_FAILURE);
599 599 }
600 600
601 601 DTRACE_PROBE(ctlr_init_ready);
602 602
603 603 /*
604 604 * Check if the maximum number of oustanding commands for the
605 605 * initialized controller is something greater than Zero.
606 606 */
607 607
608 608 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
609 609
610 610 if (CmdsOutMax == 0) {
611 611 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
612 612 "Commands set to Zero\n");
613 613 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
614 614 "initialization \n");
615 615 return (CPQARY3_FAILURE);
616 616 }
617 617 cpqary3p->ctlr_maxcmds = CmdsOutMax;
618 618
619 619 /*
620 620 * Zero the Upper 32 Address in the Controller
621 621 */
622 622
623 623 DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
624 624 cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat);
625 625
626 626 /* Set the controller interrupt check routine */
627 627 cpqary3p->check_ctlr_intr = cpqary3_check_simple_ctlr_intr;
628 628
629 629 cpqary3p->host_support =
630 630 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
631 631 DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
632 632 (cpqary3p->host_support | 0x4));
633 633 cpqary3p->host_support =
634 634 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
635 635
636 636 cpqary3p->lockup_logged = CPQARY3_FALSE;
637 637 } else {
638 638 /* PERF */
639 639
640 640 /*
641 641 * Check for support of PERF Transport Method
642 642 */
643 643 if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport)
644 644 & CFGTBL_XPORT_PERFORMANT)) {
645 645 cmn_err(CE_WARN, "CPQary3 : Controller "
646 646 "NOT YET INITIALIZED");
647 647 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
648 648 "try again later \n");
649 649 return (CPQARY3_FAILURE);
650 650 }
651 651
652 652 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
653 653 if (CmdsOutMax == 0)
654 654 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
655 655 if (CmdsOutMax == 0) {
656 656 cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
657 657 "Commands set to Zero\n");
658 658 cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
659 659 "initialization \n");
660 660 return (CPQARY3_FAILURE);
661 661 }
662 662
663 663 cpqary3p->ctlr_maxcmds = CmdsOutMax;
664 664
665 665
666 666 /* Initialize the Performant Method Transport Method Table */
667 667
668 668 queue_depth = cpqary3p->ctlr_maxcmds;
669 669
670 670 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQSize, queue_depth);
671 671 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCount, 1);
672 672 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrLow32, 0);
673 673 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrHigh32, 0);
674 674
675 675 cpqary3_phyctgp =
676 676 (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (cpqary3_phyctg_t));
677 677
678 678 if (!cpqary3_phyctgp) {
679 679 cmn_err(CE_NOTE,
680 680 "CPQary3: Initial mem zalloc failed");
681 681 return (CPQARY3_FAILURE);
682 682 }
683 683 cmd_size = (8 * queue_depth);
684 684 phy_addr = 0;
685 685 replyq_start_addr = cpqary3_alloc_phyctgs_mem(cpqary3p,
686 686 cmd_size, &phy_addr, cpqary3_phyctgp);
687 687
688 688 if (!replyq_start_addr) {
689 689 cmn_err(CE_WARN, "MEMALLOC returned failure");
690 690 return (CPQARY3_FAILURE);
691 691 }
692 692
693 693 bzero(replyq_start_addr, cmd_size);
694 694 cpqary3p->drvr_replyq->replyq_headptr =
695 695 /* LINTED: alignment */
696 696 (uint32_t *)replyq_start_addr;
697 697 cpqary3p->drvr_replyq->index = 0;
698 698 cpqary3p->drvr_replyq->max_index = queue_depth;
699 699 cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
700 700 cpqary3p->drvr_replyq->cyclic_indicator =
701 701 CPQARY3_REPLYQ_INIT_CYCLIC_IND;
702 702 cpqary3p->drvr_replyq->replyq_start_paddr = phy_addr;
703 703
704 704 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0Low32, phy_addr);
705 705 DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0High32, 0);
706 706
707 707 max_blk_fetch_cnt =
708 708 DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
709 709
710 710 /*
711 711 * For non-proton FW controllers, max_blk_fetch_count is not
712 712 * implemented in the firmware
713 713 */
714 714
715 715 /*
716 716 * When blk fetch count is 0, FW auto fetches 564 bytes
717 717 * corresponding to an optimal S/G of 31
718 718 */
719 719 if (max_blk_fetch_cnt == 0) {
720 720 BlockFetchCnt[0] = 35;
721 721 } else {
722 722 /*
723 723 * With MAX_PERF_SG_CNT set to 64, block fetch count
724 724 * is got by:(sizeof (CommandList_t) + 15)/16
725 725 */
726 726 if (max_blk_fetch_cnt > 68)
727 727 BlockFetchCnt[0] = 68;
728 728 else
729 729 BlockFetchCnt[0] = max_blk_fetch_cnt;
730 730 }
731 731
732 732 DDI_PUT32_CP(cpqary3p, &perf_cfg->BlockFetchCnt[0],
733 733 BlockFetchCnt[0]);
734 734 DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest,
735 735 CFGTBL_XPORT_PERFORMANT);
736 736 ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr,
737 737 ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) |
738 738 CFGTBL_CHANGE_REQ);
739 739
740 740 /*
741 741 * Check whether the controller is ready
742 742 */
743 743
744 744 cntr = 0;
745 745 while (ddi_get32(cpqary3p->idr_handle,
746 746 (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) {
747 747 drv_usecwait(1000000); /* Wait for 1 Sec. */
748 748 cntr++;
749 749
750 750
751 751 /*
752 752 * Wait for a maximum of 90 seconds. No f/w should take
753 753 * more than 90 secs to initialize. If the controller
754 754 * is not ready even after 90 secs, it suggests that
755 755 * something is wrong
756 756 * (wrt the controller, what else) !!!
757 757 */
758 758
759 759 if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ {
760 760 cmn_err(CE_CONT, "CPQary3 : Controller "
761 761 "Initialization Failed \n");
762 762 return (CPQARY3_FAILURE);
763 763 }
764 764 }
765 765
766 766 /*
767 767 * Check whether controller accepts the requested method of
768 768 * transport
769 769 */
770 770
771 771 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
772 772 CFGTBL_XPORT_PERFORMANT)) {
773 773 cmn_err(CE_NOTE, "CPQary3 : Failed to Initialize "
774 774 "Controller");
775 775 cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
776 776 "try again later\n");
777 777 DTRACE_PROBE1(ctlr_init_perf_fail, CfgTable_t *, ctp);
778 778 return (CPQARY3_FAILURE);
779 779 }
780 780
781 781 DTRACE_PROBE(ctlr_init_simple);
782 782
783 783 /*
784 784 * Check if Controller is ready to accept Commands
785 785 */
786 786
787 787 if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
788 788 CFGTBL_ACC_CMDS)) {
789 789 cmn_err(CE_NOTE, "CPQary3: Controller NOT ready to "
790 790 "accept Commands");
791 791 return (CPQARY3_FAILURE);
792 792 }
793 793
794 794 /*
795 795 * Check if the maximum number of oustanding commands for the
796 796 * initialized controller is something greater than Zero.
797 797 */
798 798
799 799 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
800 800 if (CmdsOutMax == 0)
801 801 CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
802 802
803 803 if (CmdsOutMax == 0) {
804 804 cmn_err(CE_NOTE, "CPQary3 : HBA Maximum Outstanding "
805 805 "Commands set to Zero");
806 806 cmn_err(CE_NOTE, "CPQary3 : Cannot continue driver "
807 807 "initialization");
808 808 return (CPQARY3_FAILURE);
809 809 }
810 810
811 811 cpqary3p->ctlr_maxcmds = CmdsOutMax;
812 812
813 813 /* SG */
814 814 max_sg_cnt = DDI_GET32(cpqary3p, &ctp->MaxSGElements);
815 815 max_blk_fetch_cnt =
816 816 DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
817 817
818 818 /* 32 byte aligned - size_of_cmdlist */
819 819 size_of_cmdlist = ((sizeof (CommandList_t) + 31) / 32) * 32;
820 820 size_of_HRE = size_of_cmdlist -
821 821 (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
822 822
823 823 if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) ||
824 824 ((max_blk_fetch_cnt * 16) <= size_of_HRE)) {
825 825 cpqary3p->sg_cnt = CPQARY3_PERF_SG_CNT;
826 826 } else {
827 827 /*
828 828 * Get the optimal_sg - no of the SG's that will fit
829 829 * into the max_blk_fetch_cnt
830 830 */
831 831
832 832 optimal_sg_size =
833 833 (max_blk_fetch_cnt * 16) - size_of_HRE;
834 834
835 835 if (optimal_sg_size < sizeof (SGDescriptor_t)) {
836 836 optimal_sg = CPQARY3_PERF_SG_CNT;
837 837 } else {
838 838 optimal_sg =
839 839 optimal_sg_size / sizeof (SGDescriptor_t);
840 840 }
841 841
842 842 cpqary3p->sg_cnt = MIN(max_sg_cnt, optimal_sg);
843 843
844 844 if (cpqary3p->sg_cnt > MAX_PERF_SG_CNT)
845 845 cpqary3p->sg_cnt = MAX_PERF_SG_CNT;
846 846 }
847 847
848 848 /* SG */
849 849
850 850 /*
851 851 * Zero the Upper 32 Address in the Controller
852 852 */
853 853
854 854 DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
855 855 cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat);
856 856
857 857 /* Set the controller interrupt check routine */
858 858
859 859 if (cpqary3p->bddef->bd_is_e200) {
860 860 cpqary3p->check_ctlr_intr =
861 861 cpqary3_check_perf_e200_intr;
862 862 } else {
863 863 cpqary3p->check_ctlr_intr =
864 864 cpqary3_check_perf_ctlr_intr;
865 865 }
866 866
867 867 if ((!cpqary3p->bddef->bd_is_e200) &&
868 868 (!cpqary3p->bddef->bd_is_ssll)) {
869 869 cpqary3p->host_support =
870 870 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
871 871 DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
872 872 (cpqary3p->host_support | 0x4));
873 873 }
874 874 cpqary3p->host_support =
875 875 DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
876 876 cpqary3p->lockup_logged = CPQARY3_FALSE;
877 877 }
878 878
879 879 return (CPQARY3_SUCCESS);
880 880 }
881 881
882 882 /*
883 883 * Function : cpqary3_check_ctlr_init
884 884 * Description : This routine checks to see if the HBA is initialized.
885 885 * Called By : cpqary3_init_ctlr()
886 886 * Parameters : per-controller
887 887 * Calls : None
888 888 * Return Values: SUCCESS / FAILURE
889 889 */
890 890 uint8_t
891 891 cpqary3_check_ctlr_init(cpqary3_t *cpqary3p)
892 892 {
893 893 int8_t retvalue;
894 894 uint16_t i;
895 895 uint32_t *ctlr_init;
896 896 ddi_acc_handle_t ctlr_init_handle;
897 897 extern ddi_device_acc_attr_t cpqary3_dev_attributes;
898 898
899 899 RETURN_FAILURE_IF_NULL(cpqary3p);
900 900
901 901 /*
902 902 * Set up the mapping for a Register at offset 0xB0 from I2O Bar
903 903 * The value 0xB0 taken from the CONFIGM utility.
904 904 * It should read 0xffff0000 if the controller is initialized.
905 905 * if not yet initialized, read it every second for 300 secs.
906 906 * If not set even after 300 secs, return FAILURE.
907 907 * If set, free the mapping and continue
908 908 */
909 909 retvalue = ddi_regs_map_setup(cpqary3p->dip, INDEX_PCI_BASE0,
910 910 (caddr_t *)&ctlr_init, (offset_t)I2O_CTLR_INIT, 4,
911 911 &cpqary3_dev_attributes, &ctlr_init_handle);
912 912
913 913 if (retvalue != DDI_SUCCESS) {
914 914 if (DDI_REGS_ACC_CONFLICT == retvalue)
915 915 cmn_err(CE_WARN,
916 916 "CPQary3 : HBA Init Register Mapping Conflict");
917 917 cmn_err(CE_WARN,
918 918 "CPQary3 : HBA Init Regsiter Mapping Failed");
↓ open down ↓ |
918 lines elided |
↑ open up ↑ |
919 919 return (CPQARY3_FAILURE);
920 920 }
921 921
922 922 for (i = 0; i < 300; i++) { /* loop for 300 seconds */
923 923 if (CISS_CTLR_INIT == ddi_get32(ctlr_init_handle, ctlr_init)) {
924 924 DTRACE_PROBE(ctlr_init_check_ready);
925 925 ddi_regs_map_free(&ctlr_init_handle);
926 926 break;
927 927 } else {
928 928 DTRACE_PROBE(ctlr_init_check_notready);
929 - delay(drv_usectohz(1000000));
929 + delay(drv_sectohz(1));
930 930 }
931 931 }
932 932
933 933 if (i >= 300) { /* HBA not initialized even after 300 seconds !!! */
934 934 ddi_regs_map_free(&ctlr_init_handle);
935 935 cmn_err(CE_WARN, "CPQary3 : %s NOT initialized !!! HBA may not "
936 936 "function properly. Please replace the hardware or check "
937 937 "the connections", cpqary3p->hba_name);
938 938 return (CPQARY3_FAILURE);
939 939 }
940 940
941 941 return (CPQARY3_SUCCESS);
942 942 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX