1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2011 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_PKT_C);
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
33*8f23e9faSHans Rosenfeld typedef struct
34291a2b48SSukumar Swaminathan {
35fcf3ce44SJohn Forte 	ddi_dma_cookie_t pkt_cmd_cookie;
36fcf3ce44SJohn Forte 	ddi_dma_cookie_t pkt_resp_cookie;
37fcf3ce44SJohn Forte 	ddi_dma_cookie_t pkt_data_cookie;
38fcf3ce44SJohn Forte 
39fcf3ce44SJohn Forte } emlxs_pkt_cookie_t;
40291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
41fcf3ce44SJohn Forte 
42fcf3ce44SJohn Forte 
43bb63f56eSSukumar Swaminathan /* ARGSUSED */
44fcf3ce44SJohn Forte static void
emlxs_pkt_thread(emlxs_hba_t * hba,void * arg1,void * arg2)45bb63f56eSSukumar Swaminathan emlxs_pkt_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
46fcf3ce44SJohn Forte {
47fcf3ce44SJohn Forte 	emlxs_port_t *port;
48bb63f56eSSukumar Swaminathan 	fc_packet_t *pkt = (fc_packet_t *)arg1;
49fcf3ce44SJohn Forte 	int32_t rval;
50fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
51fcf3ce44SJohn Forte 
52fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
53fcf3ce44SJohn Forte 	port = sbp->port;
54fcf3ce44SJohn Forte 
55fcf3ce44SJohn Forte 	/* Send the pkt now */
56fcf3ce44SJohn Forte 	rval = emlxs_pkt_send(pkt, 1);
57fcf3ce44SJohn Forte 
58fcf3ce44SJohn Forte 	if (rval != FC_SUCCESS) {
59fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg,
60*8f23e9faSHans Rosenfeld 		    "Deferred pkt_send failed: status=%x pkt=%p", rval,
61291a2b48SSukumar Swaminathan 		    pkt);
62fcf3ce44SJohn Forte 
63fcf3ce44SJohn Forte 		if (pkt->pkt_comp) {
64fcf3ce44SJohn Forte 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT, 0, 1);
65fcf3ce44SJohn Forte 
6682527734SSukumar Swaminathan 			((CHANNEL *)sbp->channel)->ulpCmplCmd++;
67fcf3ce44SJohn Forte 			(*pkt->pkt_comp) (pkt);
68fcf3ce44SJohn Forte 		} else {
69fcf3ce44SJohn Forte 			emlxs_pkt_free(pkt);
70fcf3ce44SJohn Forte 		}
71fcf3ce44SJohn Forte 	}
72291a2b48SSukumar Swaminathan 
73fcf3ce44SJohn Forte 	return;
74fcf3ce44SJohn Forte 
7582527734SSukumar Swaminathan } /* emlxs_pkt_thread() */
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte extern int32_t
emlxs_pkt_send(fc_packet_t * pkt,uint32_t now)79fcf3ce44SJohn Forte emlxs_pkt_send(fc_packet_t *pkt, uint32_t now)
80fcf3ce44SJohn Forte {
81bb63f56eSSukumar Swaminathan 	emlxs_port_t *port = (emlxs_port_t *)pkt->pkt_ulp_private;
82bb63f56eSSukumar Swaminathan 	emlxs_hba_t *hba = HBA;
83fcf3ce44SJohn Forte 	int32_t rval;
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte 	if (now) {
86a9800bebSGarrett D'Amore 		rval = emlxs_fca_transport((opaque_t)port, pkt);
87fcf3ce44SJohn Forte 	} else {
88fcf3ce44SJohn Forte 		/* Spawn a thread to send the pkt */
89bb63f56eSSukumar Swaminathan 		emlxs_thread_spawn(hba, emlxs_pkt_thread, (char *)pkt, NULL);
90fcf3ce44SJohn Forte 
91fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
92fcf3ce44SJohn Forte 	}
93fcf3ce44SJohn Forte 
94fcf3ce44SJohn Forte 	return (rval);
95fcf3ce44SJohn Forte 
9682527734SSukumar Swaminathan } /* emlxs_pkt_send() */
97fcf3ce44SJohn Forte 
98fcf3ce44SJohn Forte 
99fcf3ce44SJohn Forte extern void
emlxs_pkt_free(fc_packet_t * pkt)100fcf3ce44SJohn Forte emlxs_pkt_free(fc_packet_t *pkt)
101fcf3ce44SJohn Forte {
102fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)pkt->pkt_ulp_private;
103fcf3ce44SJohn Forte 
104a9800bebSGarrett D'Amore 	(void) emlxs_fca_pkt_uninit((opaque_t)port, pkt);
105fcf3ce44SJohn Forte 
106fcf3ce44SJohn Forte 	if (pkt->pkt_datalen) {
107fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_data_dma);
108fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_data_acc);
109fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_data_dma);
110fcf3ce44SJohn Forte 	}
111291a2b48SSukumar Swaminathan 
112fcf3ce44SJohn Forte 	if (pkt->pkt_rsplen) {
113fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_resp_dma);
114fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_resp_acc);
115fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_resp_dma);
116fcf3ce44SJohn Forte 	}
117291a2b48SSukumar Swaminathan 
118fcf3ce44SJohn Forte 	if (pkt->pkt_cmdlen) {
119fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_cmd_dma);
120fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_cmd_acc);
121fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_cmd_dma);
122fcf3ce44SJohn Forte 	}
123fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
124fcf3ce44SJohn Forte 	kmem_free(pkt, (sizeof (fc_packet_t) + sizeof (emlxs_buf_t) +
125fcf3ce44SJohn Forte 	    sizeof (emlxs_pkt_cookie_t)));
126fcf3ce44SJohn Forte #else
127fcf3ce44SJohn Forte 	kmem_free(pkt, (sizeof (fc_packet_t) + sizeof (emlxs_buf_t)));
128291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
129fcf3ce44SJohn Forte 
130fcf3ce44SJohn Forte 	return;
131fcf3ce44SJohn Forte 
13282527734SSukumar Swaminathan } /* emlxs_pkt_free() */
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 
135fcf3ce44SJohn Forte /* Default pkt callback routine */
136fcf3ce44SJohn Forte extern void
emlxs_pkt_callback(fc_packet_t * pkt)137fcf3ce44SJohn Forte emlxs_pkt_callback(fc_packet_t *pkt)
138fcf3ce44SJohn Forte {
139fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
140fcf3ce44SJohn Forte 
141fcf3ce44SJohn Forte 	return;
142fcf3ce44SJohn Forte 
14382527734SSukumar Swaminathan } /* emlxs_pkt_callback() */
144fcf3ce44SJohn Forte 
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte 
147fcf3ce44SJohn Forte extern fc_packet_t *
emlxs_pkt_alloc(emlxs_port_t * port,uint32_t cmdlen,uint32_t rsplen,uint32_t datalen,int32_t sleep)148fcf3ce44SJohn Forte emlxs_pkt_alloc(emlxs_port_t *port, uint32_t cmdlen, uint32_t rsplen,
149fcf3ce44SJohn Forte     uint32_t datalen, int32_t sleep)
150fcf3ce44SJohn Forte {
151fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
152fcf3ce44SJohn Forte 	fc_packet_t *pkt;
153fcf3ce44SJohn Forte 	int32_t(*cb) (caddr_t);
154fcf3ce44SJohn Forte 	unsigned long real_len;
155fcf3ce44SJohn Forte 	uint32_t pkt_size;
156fcf3ce44SJohn Forte 	emlxs_buf_t *sbp;
157fcf3ce44SJohn Forte 
158fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
159fcf3ce44SJohn Forte 	emlxs_pkt_cookie_t *pkt_cookie;
160fcf3ce44SJohn Forte 
161291a2b48SSukumar Swaminathan 	pkt_size =
162291a2b48SSukumar Swaminathan 	    sizeof (fc_packet_t) + sizeof (emlxs_buf_t) +
163fcf3ce44SJohn Forte 	    sizeof (emlxs_pkt_cookie_t);
164fcf3ce44SJohn Forte #else
165fcf3ce44SJohn Forte 	uint32_t num_cookie;
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 	pkt_size = sizeof (fc_packet_t) + sizeof (emlxs_buf_t);
168291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
169fcf3ce44SJohn Forte 
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte 	/* Allocate some space */
172fcf3ce44SJohn Forte 	if (!(pkt = (fc_packet_t *)kmem_alloc(pkt_size, sleep))) {
173fcf3ce44SJohn Forte 		return (NULL);
174fcf3ce44SJohn Forte 	}
175291a2b48SSukumar Swaminathan 
176fcf3ce44SJohn Forte 	bzero(pkt, pkt_size);
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte 	cb = (sleep == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 	pkt->pkt_ulp_private = (opaque_t)port;
181291a2b48SSukumar Swaminathan 	pkt->pkt_fca_private =
182291a2b48SSukumar Swaminathan 	    (opaque_t)((uintptr_t)pkt + sizeof (fc_packet_t));
183fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_pkt_callback;
184fcf3ce44SJohn Forte 	pkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
185fcf3ce44SJohn Forte 	pkt->pkt_cmdlen = cmdlen;
186fcf3ce44SJohn Forte 	pkt->pkt_rsplen = rsplen;
187fcf3ce44SJohn Forte 	pkt->pkt_datalen = datalen;
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
190291a2b48SSukumar Swaminathan 	pkt_cookie =
191291a2b48SSukumar Swaminathan 	    (emlxs_pkt_cookie_t *)((uintptr_t)pkt + sizeof (fc_packet_t) +
192291a2b48SSukumar Swaminathan 	    sizeof (emlxs_buf_t));
193fcf3ce44SJohn Forte 	pkt->pkt_cmd_cookie = &pkt_cookie->pkt_cmd_cookie;
194fcf3ce44SJohn Forte 	pkt->pkt_resp_cookie = &pkt_cookie->pkt_resp_cookie;
195fcf3ce44SJohn Forte 	pkt->pkt_data_cookie = &pkt_cookie->pkt_data_cookie;
196291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
197fcf3ce44SJohn Forte 
198fcf3ce44SJohn Forte 	if (cmdlen) {
199fcf3ce44SJohn Forte 		/* Allocate the cmd buf */
20062379b58SSukumar Swaminathan 		if (ddi_dma_alloc_handle(hba->dip, &hba->dma_attr_1sg, cb,
201fcf3ce44SJohn Forte 		    NULL, &pkt->pkt_cmd_dma) != DDI_SUCCESS) {
202fcf3ce44SJohn Forte 			cmdlen = 0;
203fcf3ce44SJohn Forte 			rsplen = 0;
204fcf3ce44SJohn Forte 			datalen = 0;
205fcf3ce44SJohn Forte 			goto failed;
206fcf3ce44SJohn Forte 		}
207291a2b48SSukumar Swaminathan 
208fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(pkt->pkt_cmd_dma, cmdlen,
209fcf3ce44SJohn Forte 		    &emlxs_data_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
210291a2b48SSukumar Swaminathan 		    (caddr_t *)&pkt->pkt_cmd, &real_len,
211291a2b48SSukumar Swaminathan 		    &pkt->pkt_cmd_acc) != DDI_SUCCESS) {
212fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_cmd_dma);
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 			cmdlen = 0;
215fcf3ce44SJohn Forte 			rsplen = 0;
216fcf3ce44SJohn Forte 			datalen = 0;
217fcf3ce44SJohn Forte 			goto failed;
218fcf3ce44SJohn Forte 		}
219291a2b48SSukumar Swaminathan 
220fcf3ce44SJohn Forte 		if (real_len < cmdlen) {
221fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_cmd_acc);
222fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_cmd_dma);
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte 			cmdlen = 0;
225fcf3ce44SJohn Forte 			rsplen = 0;
226fcf3ce44SJohn Forte 			datalen = 0;
227fcf3ce44SJohn Forte 			goto failed;
228fcf3ce44SJohn Forte 		}
229fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
230fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_cmd_dma, NULL,
231291a2b48SSukumar Swaminathan 		    pkt->pkt_cmd, real_len,
232291a2b48SSukumar Swaminathan 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
233291a2b48SSukumar Swaminathan 		    pkt->pkt_cmd_cookie,
234291a2b48SSukumar Swaminathan 		    &pkt->pkt_cmd_cookie_cnt) != DDI_DMA_MAPPED)
235fcf3ce44SJohn Forte #else
236fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_cmd_dma, NULL,
237291a2b48SSukumar Swaminathan 		    pkt->pkt_cmd, real_len,
238291a2b48SSukumar Swaminathan 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
239291a2b48SSukumar Swaminathan 		    &pkt->pkt_cmd_cookie, &num_cookie) != DDI_DMA_MAPPED)
240291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
241fcf3ce44SJohn Forte 		{
242fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_cmd_acc);
243fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_cmd_dma);
244fcf3ce44SJohn Forte 
245fcf3ce44SJohn Forte 			cmdlen = 0;
246fcf3ce44SJohn Forte 			rsplen = 0;
247fcf3ce44SJohn Forte 			datalen = 0;
248fcf3ce44SJohn Forte 			goto failed;
249fcf3ce44SJohn Forte 		}
250fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
251fcf3ce44SJohn Forte 		if (pkt->pkt_cmd_cookie_cnt != 1)
252fcf3ce44SJohn Forte #else
253fcf3ce44SJohn Forte 		if (num_cookie != 1)
254291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
255fcf3ce44SJohn Forte 		{
256fcf3ce44SJohn Forte 			rsplen = 0;
257fcf3ce44SJohn Forte 			datalen = 0;
258fcf3ce44SJohn Forte 			goto failed;
259fcf3ce44SJohn Forte 		}
260291a2b48SSukumar Swaminathan 
261fcf3ce44SJohn Forte 		bzero(pkt->pkt_cmd, cmdlen);
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	}
264291a2b48SSukumar Swaminathan 
265fcf3ce44SJohn Forte 	if (rsplen) {
266fcf3ce44SJohn Forte 		/* Allocate the rsp buf */
26762379b58SSukumar Swaminathan 		if (ddi_dma_alloc_handle(hba->dip, &hba->dma_attr_1sg, cb,
268fcf3ce44SJohn Forte 		    NULL, &pkt->pkt_resp_dma) != DDI_SUCCESS) {
269fcf3ce44SJohn Forte 			rsplen = 0;
270fcf3ce44SJohn Forte 			datalen = 0;
271fcf3ce44SJohn Forte 			goto failed;
272fcf3ce44SJohn Forte 
273fcf3ce44SJohn Forte 		}
274291a2b48SSukumar Swaminathan 
275fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(pkt->pkt_resp_dma, rsplen,
276fcf3ce44SJohn Forte 		    &emlxs_data_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
277291a2b48SSukumar Swaminathan 		    (caddr_t *)&pkt->pkt_resp, &real_len,
278291a2b48SSukumar Swaminathan 		    &pkt->pkt_resp_acc) != DDI_SUCCESS) {
279fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_resp_dma);
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 			rsplen = 0;
282fcf3ce44SJohn Forte 			datalen = 0;
283fcf3ce44SJohn Forte 			goto failed;
284fcf3ce44SJohn Forte 		}
285291a2b48SSukumar Swaminathan 
286fcf3ce44SJohn Forte 		if (real_len < rsplen) {
287fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_resp_acc);
288fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_resp_dma);
289fcf3ce44SJohn Forte 
290fcf3ce44SJohn Forte 			rsplen = 0;
291fcf3ce44SJohn Forte 			datalen = 0;
292fcf3ce44SJohn Forte 			goto failed;
293fcf3ce44SJohn Forte 		}
294fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
295fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_resp_dma, NULL,
296291a2b48SSukumar Swaminathan 		    pkt->pkt_resp, real_len,
297291a2b48SSukumar Swaminathan 		    DDI_DMA_READ | DDI_DMA_CONSISTENT, cb, NULL,
298291a2b48SSukumar Swaminathan 		    pkt->pkt_resp_cookie,
299291a2b48SSukumar Swaminathan 		    &pkt->pkt_resp_cookie_cnt) != DDI_DMA_MAPPED)
300fcf3ce44SJohn Forte #else
301fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_resp_dma, NULL,
302291a2b48SSukumar Swaminathan 		    pkt->pkt_resp, real_len,
303291a2b48SSukumar Swaminathan 		    DDI_DMA_READ | DDI_DMA_CONSISTENT, cb, NULL,
304291a2b48SSukumar Swaminathan 		    &pkt->pkt_resp_cookie, &num_cookie) != DDI_DMA_MAPPED)
305291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
306fcf3ce44SJohn Forte 		{
307fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_resp_acc);
308fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_resp_dma);
309fcf3ce44SJohn Forte 
310fcf3ce44SJohn Forte 			rsplen = 0;
311fcf3ce44SJohn Forte 			datalen = 0;
312fcf3ce44SJohn Forte 			goto failed;
313fcf3ce44SJohn Forte 		}
314fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
315fcf3ce44SJohn Forte 		if (pkt->pkt_resp_cookie_cnt != 1)
316fcf3ce44SJohn Forte #else
317fcf3ce44SJohn Forte 		if (num_cookie != 1)
318291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
319fcf3ce44SJohn Forte 		{
320fcf3ce44SJohn Forte 			datalen = 0;
321fcf3ce44SJohn Forte 			goto failed;
322fcf3ce44SJohn Forte 		}
323291a2b48SSukumar Swaminathan 
324fcf3ce44SJohn Forte 		bzero(pkt->pkt_resp, rsplen);
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 	}
327291a2b48SSukumar Swaminathan 
328fcf3ce44SJohn Forte 	/* Allocate the data buf */
329fcf3ce44SJohn Forte 	if (datalen) {
330fcf3ce44SJohn Forte 		/* Allocate the rsp buf */
33162379b58SSukumar Swaminathan 		if (ddi_dma_alloc_handle(hba->dip, &hba->dma_attr_1sg, cb,
332fcf3ce44SJohn Forte 		    NULL, &pkt->pkt_data_dma) != DDI_SUCCESS) {
333fcf3ce44SJohn Forte 			datalen = 0;
334fcf3ce44SJohn Forte 			goto failed;
335fcf3ce44SJohn Forte 		}
336291a2b48SSukumar Swaminathan 
337fcf3ce44SJohn Forte 		if (ddi_dma_mem_alloc(pkt->pkt_data_dma, datalen,
338fcf3ce44SJohn Forte 		    &emlxs_data_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
339291a2b48SSukumar Swaminathan 		    (caddr_t *)&pkt->pkt_data, &real_len,
340291a2b48SSukumar Swaminathan 		    &pkt->pkt_data_acc) != DDI_SUCCESS) {
341fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_data_dma);
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 			datalen = 0;
344fcf3ce44SJohn Forte 			goto failed;
345fcf3ce44SJohn Forte 		}
346291a2b48SSukumar Swaminathan 
347fcf3ce44SJohn Forte 		if (real_len < datalen) {
348fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_data_acc);
349fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_data_dma);
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 			datalen = 0;
352fcf3ce44SJohn Forte 			goto failed;
353fcf3ce44SJohn Forte 		}
354fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
355fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_data_dma, NULL,
356291a2b48SSukumar Swaminathan 		    pkt->pkt_data, real_len,
357291a2b48SSukumar Swaminathan 		    DDI_DMA_READ | DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb,
358291a2b48SSukumar Swaminathan 		    NULL, pkt->pkt_data_cookie,
359fcf3ce44SJohn Forte 		    &pkt->pkt_data_cookie_cnt) != DDI_DMA_MAPPED)
360fcf3ce44SJohn Forte #else
361fcf3ce44SJohn Forte 		if (ddi_dma_addr_bind_handle(pkt->pkt_data_dma, NULL,
362291a2b48SSukumar Swaminathan 		    pkt->pkt_data, real_len,
363291a2b48SSukumar Swaminathan 		    DDI_DMA_READ | DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb,
364291a2b48SSukumar Swaminathan 		    NULL, &pkt->pkt_data_cookie,
365fcf3ce44SJohn Forte 		    &num_cookie) != DDI_DMA_MAPPED)
366291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
367fcf3ce44SJohn Forte 		{
368fcf3ce44SJohn Forte 			(void) ddi_dma_mem_free(&pkt->pkt_data_acc);
369fcf3ce44SJohn Forte 			(void) ddi_dma_free_handle(&pkt->pkt_data_dma);
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 			datalen = 0;
372fcf3ce44SJohn Forte 			goto failed;
373fcf3ce44SJohn Forte 		}
374fcf3ce44SJohn Forte #if (EMLXS_MODREV >= EMLXS_MODREV3)
375fcf3ce44SJohn Forte 		if (pkt->pkt_data_cookie_cnt != 1)
376fcf3ce44SJohn Forte #else
377fcf3ce44SJohn Forte 		if (num_cookie != 1)
378291a2b48SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */
379fcf3ce44SJohn Forte 		{
380fcf3ce44SJohn Forte 			goto failed;
381fcf3ce44SJohn Forte 		}
382291a2b48SSukumar Swaminathan 
383fcf3ce44SJohn Forte 		bzero(pkt->pkt_data, datalen);
384fcf3ce44SJohn Forte 	}
385728bdc9bSSukumar Swaminathan 
386fcf3ce44SJohn Forte 	sbp = PKT2PRIV(pkt);
387728bdc9bSSukumar Swaminathan 	bzero((void *)sbp, sizeof (emlxs_buf_t));
388728bdc9bSSukumar Swaminathan 
389a9800bebSGarrett D'Amore 	mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, DDI_INTR_PRI(hba->intr_arg));
39082527734SSukumar Swaminathan 	sbp->pkt_flags = PACKET_VALID | PACKET_ULP_OWNED | PACKET_ALLOCATED;
391728bdc9bSSukumar Swaminathan 	sbp->port = port;
392728bdc9bSSukumar Swaminathan 	sbp->pkt = pkt;
393728bdc9bSSukumar Swaminathan 	sbp->iocbq.sbp = sbp;
394fcf3ce44SJohn Forte 
395fcf3ce44SJohn Forte 	return (pkt);
396fcf3ce44SJohn Forte 
397fcf3ce44SJohn Forte failed:
398fcf3ce44SJohn Forte 
399fcf3ce44SJohn Forte 	if (datalen) {
400fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_data_dma);
401fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_data_acc);
402fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_data_dma);
403fcf3ce44SJohn Forte 	}
404291a2b48SSukumar Swaminathan 
405fcf3ce44SJohn Forte 	if (rsplen) {
406fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_resp_dma);
407fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_resp_acc);
408fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_resp_dma);
409fcf3ce44SJohn Forte 	}
410291a2b48SSukumar Swaminathan 
411fcf3ce44SJohn Forte 	if (cmdlen) {
412fcf3ce44SJohn Forte 		(void) ddi_dma_unbind_handle(pkt->pkt_cmd_dma);
413fcf3ce44SJohn Forte 		(void) ddi_dma_mem_free(&pkt->pkt_cmd_acc);
414fcf3ce44SJohn Forte 		(void) ddi_dma_free_handle(&pkt->pkt_cmd_dma);
415fcf3ce44SJohn Forte 	}
416291a2b48SSukumar Swaminathan 
417fcf3ce44SJohn Forte 	if (pkt) {
418fcf3ce44SJohn Forte 		kmem_free(pkt, pkt_size);
419fcf3ce44SJohn Forte 	}
420291a2b48SSukumar Swaminathan 
421fcf3ce44SJohn Forte 	return (NULL);
422fcf3ce44SJohn Forte 
42382527734SSukumar Swaminathan } /* emlxs_pkt_alloc() */
424