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