1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 14 */ 15 16 #include <sys/sdt.h> 17 #include "cpqary3.h" 18 19 /* 20 * Local Functions Definitions 21 */ 22 uint8_t cleanstatus = 0; 23 24 /* 25 * The Driver DMA Limit structure. 26 */ 27 static ddi_dma_attr_t cpqary3_ctlr_dma_attr = { 28 DMA_ATTR_V0, /* ddi_dma_attr version */ 29 0, /* low address */ 30 0xFFFFFFFF, /* high address */ 31 0x00FFFFFF, /* Max DMA Counter register */ 32 0x20, /* Byte Alignment */ 33 0x20, /* burst sizes */ 34 DMA_UNIT_8, /* minimum DMA xfer Size */ 35 0xFFFFFFFF, /* maximum DMA xfer Size */ 36 0x0000FFFF, /* segment boundary restrictions */ 37 1, /* scatter/gather list length */ 38 512, /* device granularity */ 39 0 /* DMA flags */ 40 }; 41 42 /* 43 * Driver device access attr struct 44 */ 45 extern ddi_device_acc_attr_t cpqary3_dev_attributes; 46 47 /* 48 * Function : cpqary3_meminit 49 * Description : This routine initialises memory for the command list. 50 * Allocation of Physical contigous blocks and maintenance 51 * of lists to these. 52 * Called By : cpqary3_init_ctlr_resource() 53 * Parameters : per_controller 54 * Calls : cpqary3_alloc_phyctgs_mem, cpqary3_memfini 55 * Return Values: SUCCESS / FAILURE 56 * [If the required initialization and setup of memory 57 * is successful, send back a success. Else, failure] 58 */ 59 int16_t 60 cpqary3_meminit(cpqary3_t *cpqary3p) 61 { 62 size_t mempool_size; 63 caddr_t mempool_addr; 64 uint16_t i = 0; 65 uint32_t mem_size = 0; 66 uint32_t no_cmds = 0; 67 uint32_t cntr; 68 uint32_t maxmemcnt; 69 uint32_t phyaddr; 70 uint32_t temp_phyaddr; 71 uint32_t size_of_cmdlist = 0; 72 uint32_t size_of_HRE = 0; /* Header + Request + Error */ 73 uint32_t unused_mem = 0; 74 uint32_t mempoolnum; 75 uint32_t CmdsOutMax; 76 CommandList_t *cmdlist_memaddr; 77 cpqary3_phyctg_t *cpqary3_phyctgp; 78 cpqary3_cmdpvt_t *ptr; 79 cpqary3_cmdpvt_t *head_pvtp; 80 cpqary3_cmdpvt_t *tail_pvtp; 81 cpqary3_cmdmemlist_t *memlistp = NULL; 82 cpqary3_phys_hdl_addr_t *blk_ptr = NULL; 83 84 RETURN_FAILURE_IF_NULL(cpqary3p); 85 86 CmdsOutMax = cpqary3p->ctlr_maxcmds; 87 88 89 /* 90 * Allocate memory for the Structure to hold details about the 91 * Command Memory Pool. 92 * Update per_controller pointer to this. 93 */ 94 95 cpqary3p->cmdmemlistp = memlistp = 96 MEM_ZALLOC(sizeof (cpqary3_cmdmemlist_t)); 97 98 if (!cpqary3p->cmdmemlistp) { 99 cmn_err(CE_NOTE, "CPQary3: Memory Initialization: " 100 "Low Kernel Memory"); 101 return (CPQARY3_FAILURE); 102 } 103 cleanstatus |= CPQARY3_MEMLIST_DONE; /* For cleaning purpose. */ 104 105 /* 106 * Allocate a Virtual Memory Pool of size 107 * NO_OF_CMDLIST_BLKS * NO_OF_CMDLIST_IN_A_BLK * sizeof (cmdmem_pvt_t) 108 * to store details of the above allocated Memory for 109 * NO_OF_CMDLIST_BLKS * NO_OF_CMDLIST_IN_A_BLK Commands 110 * Initialize this memory to act as a linked list to parse 111 * thru the entire list 112 * Initialize the Memory Mutex 113 */ 114 no_cmds = (uint32_t)((CmdsOutMax / 3) * NO_OF_CMDLIST_IN_A_BLK); 115 mem_size = (uint32_t)(no_cmds * sizeof (cpqary3_cmdpvt_t)); 116 117 head_pvtp = ptr = (cpqary3_cmdpvt_t *)(MEM_ZALLOC(mem_size)); 118 if (NULL == head_pvtp) { 119 MEM_SFREE(cpqary3p->cmdmemlistp, sizeof (cpqary3_cmdmemlist_t)); 120 cpqary3p->cmdmemlistp = NULL; 121 cleanstatus &= ~CPQARY3_MEMLIST_DONE; /* For cleaning. */ 122 cmn_err(CE_NOTE, "CPQary3: Memory Initialization: " 123 "Low Kernel Memory"); 124 return (CPQARY3_FAILURE); 125 } 126 127 tail_pvtp = &ptr[no_cmds - 1]; 128 cleanstatus |= CPQARY3_CMDMEM_DONE; /* For cleaning purpose. */ 129 130 DTRACE_PROBE4(cmd_init_start, uint32_t, no_cmds, uint32_t, mem_size, 131 cpqary3_cmdpvt_t *, head_pvtp, cpqary3_cmdpvt_t *, tail_pvtp); 132 133 for (i = 0; i < no_cmds; i++) { 134 ptr = &head_pvtp[i]; 135 ptr->occupied = CPQARY3_FREE; 136 ptr->tag.tag_value = i; 137 ptr->cmdlist_phyaddr = 0; 138 ptr->cmdlist_erraddr = 0; 139 ptr->cmdpvt_flag = 0; 140 ptr->cmdlist_memaddr = (CommandList_t *)NULL; 141 ptr->errorinfop = (ErrorInfo_t *)NULL; 142 ptr->next = (cpqary3_cmdpvt_t *)((i == (no_cmds - 1)) ? 143 NULL : &head_pvtp[i+1]); 144 ptr->prev = (cpqary3_cmdpvt_t *)((i == 0) ? 145 NULL : &head_pvtp[i-1]); 146 ptr->ctlr = cpqary3p; 147 ptr->pvt_pkt = (cpqary3_pkt_t *)NULL; 148 ptr->sprev = (cpqary3_cmdpvt_t *)NULL; 149 ptr->snext = (cpqary3_cmdpvt_t *)NULL; 150 } 151 cpqary3p->cmdmemlistp->head = head_pvtp; /* head Command Memory List */ 152 cpqary3p->cmdmemlistp->tail = tail_pvtp; /* tail Command Memory List */ 153 cpqary3p->cmdmemlistp->pool = head_pvtp; /* head Command Memory List */ 154 cpqary3p->cmdmemlistp->max_memcnt = 0; /* Maximum commands for ctlr */ 155 156 ptr = head_pvtp; 157 158 DTRACE_PROBE(memlist_init_done); 159 160 /* 161 * We require the size of the commandlist and the combined 162 * size of the Command Header, Request Block and the Error Desriptor 163 * In CPQary3, it is 564 and 52 respectively. 164 */ 165 size_of_cmdlist = sizeof (CommandList_t); 166 size_of_HRE = size_of_cmdlist - 167 (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES); 168 169 /* 170 * uint32_t alignment of cmdlist 171 * In CPQary3, after alignment, the size of each commandlist is 576 172 */ 173 if (size_of_cmdlist & 0x1F) 174 size_of_cmdlist = ((size_of_cmdlist + 31) / 32) * 32; 175 176 /* 177 * The CmdsOutMax member in the Configuration Table states the maximum 178 * outstanding commands supported by this controller. 179 * The following code allocates memory in blocks; each block holds 180 * 3 commands. 181 */ 182 183 for (mempoolnum = 0; mempoolnum < ((CmdsOutMax / 3)); mempoolnum++) { 184 /* Allocate Memory for handle to maintain the Cmd Lists */ 185 cpqary3_phyctgp = (cpqary3_phyctg_t *) 186 MEM_ZALLOC(sizeof (cpqary3_phyctg_t)); 187 if (!cpqary3_phyctgp) { 188 cpqary3_memfini(cpqary3p, cleanstatus); 189 cmn_err(CE_NOTE, "CPQary3: Mem Initialization: " 190 "Low Kernel Memory"); 191 return (CPQARY3_FAILURE); 192 } 193 194 /* 195 * Get the Physically Contiguous Memory 196 * Allocate 32 extra bytes of memory such as to get atleast 197 * 2 Command Blocks from every allocation even if we add any 198 * extra bytes after the initial allocation to make it 32 bit 199 * aligned. 200 */ 201 if (mempoolnum == 0) { /* Head of Memory Blocks' Linked List */ 202 memlistp->cpqary3_phyctgp = blk_ptr = 203 (cpqary3_phys_hdl_addr_t *) 204 MEM_ZALLOC(sizeof (cpqary3_phys_hdl_addr_t)); 205 blk_ptr->blk_addr = cpqary3_phyctgp; 206 blk_ptr->next = NULL; 207 } else { 208 blk_ptr->next = (cpqary3_phys_hdl_addr_t *) 209 MEM_ZALLOC(sizeof (cpqary3_phys_hdl_addr_t)); 210 blk_ptr = blk_ptr->next; 211 blk_ptr->blk_addr = cpqary3_phyctgp; 212 blk_ptr->next = NULL; 213 } 214 215 phyaddr = 0; 216 mempool_size = (size_of_cmdlist * NO_OF_CMDLIST_IN_A_BLK) + 32; 217 mempool_addr = cpqary3_alloc_phyctgs_mem(cpqary3p, 218 mempool_size, &phyaddr, cpqary3_phyctgp); 219 220 if (!mempool_addr) { 221 if (!mempoolnum) { /* Failue in the first attempt */ 222 MEM_SFREE(blk_ptr, 223 sizeof (cpqary3_phys_hdl_addr_t)); 224 memlistp->cpqary3_phyctgp = NULL; 225 cmn_err(CE_WARN, "CPQary3 : Memory " 226 "Initialization : Low Kernel Memory"); 227 return (CPQARY3_FAILURE); 228 } 229 230 /* 231 * Some memory allocation has already been suucessful. 232 * The driver shall continue its initialization and 233 * working with whatever memory has been allocated. 234 * 235 * Free the latest virtual memory allocated. 236 * NULLify the last node created to maintain the memory 237 * block list. 238 * Terminate the Memory Q here by marking the Tail. 239 */ 240 blk_ptr->blk_addr = NULL; 241 ptr--; 242 ptr->next = NULL; 243 memlistp->tail = ptr; 244 return (CPQARY3_SUCCESS); 245 } 246 cleanstatus |= CPQARY3_PHYCTGS_DONE; 247 248 bzero(mempool_addr, cpqary3_phyctgp->real_size); 249 250 /* 251 * The 32 bit alignment is stated in the attribute structure. 252 * In case, it is not aligned as per requirement, we align it. 253 * uint32_t alignment of the first CMDLIST in the memory list 254 */ 255 temp_phyaddr = phyaddr; 256 if (phyaddr & 0x1F) { 257 phyaddr = (uint32_t)(((phyaddr + 31) / 32) * 32); 258 unused_mem = (uint32_t)(phyaddr - temp_phyaddr); 259 } 260 261 /* 262 * If the memory allocated is not 32 byte aligned then unused 263 * will give the total no of bytes that must remain unused to 264 * make it 32 byte aligned memory 265 */ 266 mempool_addr = (char *)((char *)mempool_addr + unused_mem); 267 268 /* 269 * Update Counter for no. of Command Blocks. 270 */ 271 maxmemcnt = 0; 272 maxmemcnt = ((uint32_t) 273 (cpqary3_phyctgp->real_size - (uint32_t)unused_mem)) / 274 size_of_cmdlist; 275 memlistp->max_memcnt = memlistp->max_memcnt + maxmemcnt; 276 277 /* 278 * Get the base of mempool which is 32 Byte aligned 279 * Initialize each Command Block with its corresponding 280 * Physical Address, Virtual address and the Physical Addres 281 * of the Error Info Descriptor 282 */ 283 cmdlist_memaddr = (CommandList_t *)mempool_addr; 284 285 for (cntr = 0; cntr < maxmemcnt; cntr++) { 286 ptr->cmdlist_phyaddr = phyaddr; 287 ptr->cmdlist_memaddr = cmdlist_memaddr; 288 ptr->cmdlist_erraddr = phyaddr + size_of_HRE; 289 ptr->errorinfop = (ErrorInfo_t *) 290 ((ulong_t)cmdlist_memaddr + size_of_HRE); 291 phyaddr += size_of_cmdlist; 292 cmdlist_memaddr = (CommandList_t *) 293 ((ulong_t)cmdlist_memaddr + size_of_cmdlist); 294 ptr++; 295 } 296 } 297 298 #ifdef MEM_DEBUG 299 ptr = memlistp->head; 300 cmn_err(CE_CONT, "CPQary3 : _meminit : max_memcnt = %d \n", 301 memlistp->max_memcnt); 302 for (cntr = 0; cntr <= memlistp->max_memcnt; cntr++) { 303 cmn_err(CE_CONT, "CPQary3: %d %x |", 304 cntr, ptr->cmdlist_phyaddr); 305 if (cntr == 0) 306 debug_enter(""); 307 ptr++; 308 } 309 cmn_err(CE_CONT, "\nCPQary3 : _meminit : " 310 "cpqary3_cmdpvt starts at %x \n", memlistp->head); 311 cmn_err(CE_CONT, "CPQary3 : _meminit : cpqary3_cmdpvt ends at %x \n", 312 memlistp->tail); 313 cmn_err(CE_CONT, "CPQary3 : _meminit : Leaving Successfully \n"); 314 #endif 315 316 return (CPQARY3_SUCCESS); 317 } 318 319 /* 320 * Function : cpqary3_cmdlist_occupy 321 * Description : This routine fetches a command block from the 322 * initialised memory pool. 323 * Called By : cpqary3_transport(), cpqary3_send_NOE_command(), 324 * cpqary3_disable_NOE_command(), cpqary3_synccmd_alloc() 325 * Parameters : per_controller 326 * Calls : None 327 * Return Values: pointer to a valid Command Block / 328 * NULL if none is available 329 */ 330 cpqary3_cmdpvt_t * 331 cpqary3_cmdlist_occupy(cpqary3_t *ctlr) 332 { 333 cpqary3_cmdpvt_t *memp = NULL; 334 cpqary3_cmdmemlist_t *memlistp; 335 336 RETURN_NULL_IF_NULL(ctlr); 337 memlistp = ctlr->cmdmemlistp; 338 339 /* 340 * If pointer is NULL, we have no Command Memory Blocks available now. 341 * Else, occupy it and 342 * zero the commandlist so that old data is not existent. 343 * update tag, Error descriptor address & length in the CommandList 344 */ 345 346 mutex_enter(&ctlr->sw_mutex); 347 memp = memlistp->head; 348 if (NULL == memp) { 349 mutex_exit(&ctlr->sw_mutex); 350 return ((cpqary3_cmdpvt_t *)NULL); 351 } 352 353 memp->occupied = CPQARY3_OCCUPIED; 354 bzero(memp->cmdlist_memaddr, sizeof (CommandList_t)); 355 memp->cmdlist_memaddr->Header.Tag.tag_value = memp->tag.tag_value; 356 memp->cmdlist_memaddr->ErrDesc.Addr = memp->cmdlist_erraddr; 357 memp->cmdlist_memaddr->ErrDesc.Len = sizeof (ErrorInfo_t); 358 memlistp->head = memp->next; 359 360 DTRACE_PROBE1(cmdlist_occupy, cpqary3_cmdpvt_t *, memp); 361 362 if (memlistp->head) /* Atleast one more item is left in the Memory Q */ 363 memp->next->prev = NULL; 364 else /* No more items left in the Memory q */ 365 memlistp->tail = NULL; 366 367 mutex_exit(&ctlr->sw_mutex); 368 return (memp); 369 } 370 371 /* 372 * Function : cpqary3_cmdlist_release 373 * Description : This routine releases a command block back to the 374 * initialised memory pool. 375 * Called By : cpqary3_transport(), cpqary3_process_pkt(), 376 * cpqary3_send_NOE_command(), cpqary3_NOE_handler() 377 * cpqary3_transport(), cpqary3_handle_flag_nointr() 378 * cpqary3_synccmd_cleanup() 379 * Parameters : pointer to Command Memory 380 * flag to specify if mutex is to be held 381 * Calls : None 382 * Return Values: None 383 */ 384 void 385 cpqary3_cmdlist_release(cpqary3_cmdpvt_t *memp, uint8_t flag) 386 { 387 cpqary3_cmdmemlist_t *memlistp; 388 389 if (memp == NULL) 390 return; 391 392 /* 393 * Hold The mutex ONLY if asked to (Else it means it is already held!) 394 * If both head & tail of the per-controller-memory-list are NULL, 395 * add this command list to the Available Q and Update head & tail. 396 * Else, append it to the Available Q. 397 */ 398 399 memlistp = 400 (cpqary3_cmdmemlist_t *)((cpqary3_t *)memp->ctlr)->cmdmemlistp; 401 402 if (CPQARY3_HOLD_SW_MUTEX == flag) 403 mutex_enter(&memp->ctlr->sw_mutex); 404 405 if (memlistp->head == NULL) { /* obviously, tail is also NULL */ 406 memlistp->head = memp; 407 memlistp->tail = memp; 408 memp->next = NULL; 409 memp->prev = NULL; 410 } else { 411 memlistp->tail->next = memp; 412 memp->prev = memlistp->tail; 413 memp->next = NULL; 414 memlistp->tail = memp; 415 } 416 417 memp->occupied = CPQARY3_FREE; 418 memp->cmdpvt_flag = 0; 419 memp->pvt_pkt = NULL; 420 421 if (CPQARY3_HOLD_SW_MUTEX == flag) 422 mutex_exit(&memp->ctlr->sw_mutex); 423 } 424 425 /* 426 * Function : cpqary3_memfini 427 * Description : This routine frees all command blocks that was 428 * initialised for the Command Memory Pool. 429 * It also fress any related memory that was occupied. 430 * Called By : cpqary3_cleanup(), cpqary3_meminit(), 431 * cpqary3_init_ctlr_resource() 432 * Parameters : per-controller, identifier(what all to clean up) 433 * Calls : cpqary3_free_phyctgs_mem 434 * Return Values: None 435 */ 436 void 437 cpqary3_memfini(cpqary3_t *ctlr, uint8_t level) 438 { 439 uint32_t mem_size; 440 uint32_t CmdsOutMax; 441 cpqary3_cmdpvt_t *memp; 442 cpqary3_phys_hdl_addr_t *blk_ptr; 443 cpqary3_phys_hdl_addr_t *tptr; 444 445 ASSERT(ctlr != NULL); 446 blk_ptr = (cpqary3_phys_hdl_addr_t *)ctlr->cmdmemlistp->cpqary3_phyctgp; 447 448 CmdsOutMax = ctlr->ctlr_maxcmds; 449 450 DTRACE_PROBE1(memfini_start, uint32_t, CmdsOutMax); 451 452 /* 453 * Depending upon the identifier, 454 * Free Physical memory & Memory allocated to hold Block Details 455 * Virtual Memory used to maintain linked list of Command Memory Pool 456 * Memory which stores data relating to the Command Memory Pool 457 */ 458 459 mutex_enter(&ctlr->sw_mutex); 460 if (level & CPQARY3_PHYCTGS_DONE) { 461 if (blk_ptr) { 462 while (blk_ptr->next) { 463 tptr = blk_ptr; 464 blk_ptr = blk_ptr->next; 465 cpqary3_free_phyctgs_mem( 466 tptr->blk_addr, CPQARY3_FREE_PHYCTG_MEM); 467 MEM_SFREE(tptr, 468 sizeof (cpqary3_phys_hdl_addr_t)); 469 } 470 cpqary3_free_phyctgs_mem( 471 blk_ptr->blk_addr, CPQARY3_FREE_PHYCTG_MEM); 472 MEM_SFREE(blk_ptr, sizeof (cpqary3_phys_hdl_addr_t)); 473 } 474 } 475 476 if (level & CPQARY3_CMDMEM_DONE) { 477 mem_size = (uint32_t)((CmdsOutMax / 3) * 478 NO_OF_CMDLIST_IN_A_BLK * sizeof (cpqary3_cmdpvt_t)); 479 memp = ctlr->cmdmemlistp->pool; 480 481 DTRACE_PROBE2(memfini, uint32_t, mem_size, void *, memp); 482 MEM_SFREE(memp, mem_size); 483 } 484 mutex_exit(&ctlr->sw_mutex); 485 486 if (level & CPQARY3_MEMLIST_DONE) { 487 mutex_enter(&ctlr->hw_mutex); 488 MEM_SFREE(ctlr->cmdmemlistp, sizeof (cpqary3_cmdmemlist_t)); 489 mutex_exit(&ctlr->hw_mutex); 490 } 491 } 492 493 /* 494 * Function : cpqary3_alloc_phyctgs_mem 495 * Description : This routine allocates Physically Contiguous Memory 496 * for Commands or Scatter/Gather. 497 * Called By : cpqary3_meminit(), cpqary3_send_NOE_command() 498 * cpqary3_synccmd_alloc() 499 * Parameters : per-controller, size, 500 * physical address that is sent back, per-physical 501 * Calls : cpqary3_free_phyctgs_mem(), ddi_dma_addr_bind_handle(), 502 * ddi_dma_alloc_handle(), ddi_dma_mem_alloc() 503 * Return Values: Actually, this function sends back 2 values, one as an 504 * explicit return and the other by updating a 505 * pointer-parameter: 506 * Virtual Memory Pointer to the allocated Memory(caddr_t), 507 * Physical Address of the allocated Memory(phyaddr) 508 */ 509 caddr_t 510 cpqary3_alloc_phyctgs_mem(cpqary3_t *ctlr, size_t size_mempool, 511 uint32_t *phyaddr, cpqary3_phyctg_t *phyctgp) 512 { 513 size_t real_len; 514 int32_t retvalue; 515 caddr_t mempool = NULL; 516 uint8_t cleanstat = 0; 517 uint32_t cookiecnt; 518 519 RETURN_NULL_IF_NULL(ctlr); 520 RETURN_NULL_IF_NULL(phyctgp); 521 522 /* 523 * Allocation of Physical Contigous Memory follws: 524 * allocate a handle for this memory 525 * Use this handle in allocating memory 526 * bind the handle to this memory 527 * If any of the above fails, return a FAILURE. 528 * If all succeed, update phyaddr to the physical address of the 529 * allocated memory and return the pointer to the virtul allocated 530 * memory. 531 */ 532 533 if (DDI_SUCCESS != 534 (retvalue = ddi_dma_alloc_handle((dev_info_t *)ctlr->dip, 535 &cpqary3_ctlr_dma_attr, DDI_DMA_DONTWAIT, 0, 536 &phyctgp->cpqary3_dmahandle))) { 537 switch (retvalue) { 538 case DDI_DMA_NORESOURCES: 539 cmn_err(CE_CONT, "CPQary3: No resources are available " 540 "to allocate the DMA Handle\n"); 541 break; 542 543 case DDI_DMA_BADATTR: 544 cmn_err(CE_CONT, "CPQary3: Bad attributes in " 545 "ddi_dma_attr cannot allocate the DMA Handle \n"); 546 break; 547 548 default: 549 cmn_err(CE_CONT, "CPQary3: Unexpected Value %x from " 550 "call to allocate the DMA Handle \n", retvalue); 551 } 552 /* Calling MEM_SFREE to free the memory */ 553 MEM_SFREE(phyctgp, sizeof (cpqary3_phyctg_t)); 554 return (NULL); 555 } 556 557 cleanstat |= CPQARY3_DMA_ALLOC_HANDLE_DONE; 558 559 retvalue = ddi_dma_mem_alloc(phyctgp->cpqary3_dmahandle, 560 size_mempool, &cpqary3_dev_attributes, 561 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0, &mempool, &real_len, 562 &phyctgp->cpqary3_acchandle); 563 564 if (DDI_SUCCESS != retvalue) { 565 cmn_err(CE_WARN, "CPQary3: Memory Allocation Failed: " 566 "Increase System Memory"); 567 cpqary3_free_phyctgs_mem(phyctgp, cleanstat); 568 return (NULL); 569 } 570 571 phyctgp->real_size = real_len; 572 573 cleanstat |= CPQARY3_DMA_ALLOC_MEM_DONE; 574 575 retvalue = ddi_dma_addr_bind_handle(phyctgp->cpqary3_dmahandle, 576 NULL, mempool, real_len, 577 DDI_DMA_CONSISTENT | DDI_DMA_RDWR, DDI_DMA_DONTWAIT, 0, 578 &phyctgp->cpqary3_dmacookie, &cookiecnt); 579 580 if (DDI_DMA_MAPPED == retvalue) { 581 *phyaddr = phyctgp->cpqary3_dmacookie.dmac_address; 582 return (mempool); 583 } 584 585 switch (retvalue) { 586 case DDI_DMA_PARTIAL_MAP: 587 cmn_err(CE_CONT, "CPQary3: Allocated the resources for part " 588 "of the object\n"); 589 break; 590 591 case DDI_DMA_INUSE: 592 cmn_err(CE_CONT, "CPQary3: Another I/O transaction is using " 593 "the DMA handle cannot bind to the DMA Handle\n"); 594 break; 595 596 case DDI_DMA_NORESOURCES: 597 cmn_err(CE_CONT, "CPQary3: No resources are available cannot " 598 "bind to the DMA Handle\n"); 599 break; 600 601 case DDI_DMA_NOMAPPING: 602 cmn_err(CE_CONT, "CPQary3: Object cannot be reached by the " 603 "device cannot bind to the DMA Handle\n"); 604 break; 605 606 case DDI_DMA_TOOBIG: 607 cmn_err(CE_CONT, "CPQary3: The object is too big cannot bind " 608 "to the DMA Handle\n"); 609 cmn_err(CE_WARN, "CPQary3: Mem Scarce : " 610 "Increase System Memory/lomempages"); 611 break; 612 613 default: 614 cmn_err(CE_WARN, "CPQary3 : Unexpected Return Value %x " 615 "from call to bind the DMA Handle", retvalue); 616 } 617 618 cpqary3_free_phyctgs_mem(phyctgp, cleanstat); 619 620 mempool = NULL; 621 return (mempool); 622 } 623 624 /* 625 * Function : cpqary3_free_phyctg_mem () 626 * Description : This routine frees the Physically contigous memory 627 * that was allocated using ddi_dma operations. 628 * It also fress any related memory that was occupied. 629 * Called By : cpqary3_alloc_phyctgs_mem(), cpqary3_memfini(), 630 * cpqary3_send_NOE_command(), cpqary3_NOE_handler(), 631 * cpqary3_synccmd_alloc(), cpqary3_synccmd_cleanup() 632 * Parameters : per-physical, identifier(what all to free) 633 * Calls : None 634 */ 635 void 636 cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *cpqary3_phyctgp, uint8_t cleanstat) 637 { 638 639 if (cpqary3_phyctgp == NULL) 640 return; 641 642 /* 643 * Following the reverse prcess that was followed 644 * in allocating physical contigous memory 645 */ 646 647 if (cleanstat & CPQARY3_DMA_BIND_ADDR_DONE) { 648 (void) ddi_dma_unbind_handle( 649 cpqary3_phyctgp->cpqary3_dmahandle); 650 } 651 652 if (cleanstat & CPQARY3_DMA_ALLOC_MEM_DONE) { 653 ddi_dma_mem_free(&cpqary3_phyctgp->cpqary3_acchandle); 654 } 655 656 if (cleanstat & CPQARY3_DMA_ALLOC_HANDLE_DONE) { 657 ddi_dma_free_handle(&cpqary3_phyctgp->cpqary3_dmahandle); 658 } 659 660 MEM_SFREE(cpqary3_phyctgp, sizeof (cpqary3_phyctg_t)); 661 } 662