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