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  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
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 
22*eb82ff87SDaniel Beauregard /* Copyright 2010 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
2516dd44c2SDaniel Beauregard  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26fcf3ce44SJohn Forte  * Use is subject to license terms.
27fcf3ce44SJohn Forte  */
28fcf3ce44SJohn Forte 
29*eb82ff87SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_iocb.c"
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte /*
32fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33fcf3ce44SJohn Forte  *
34fcf3ce44SJohn Forte  * ***********************************************************************
35fcf3ce44SJohn Forte  * *									**
36fcf3ce44SJohn Forte  * *				NOTICE					**
37*eb82ff87SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
38fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
39fcf3ce44SJohn Forte  * *									**
40fcf3ce44SJohn Forte  * ***********************************************************************
41fcf3ce44SJohn Forte  *
42fcf3ce44SJohn Forte  */
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte #include <ql_apps.h>
45fcf3ce44SJohn Forte #include <ql_api.h>
46fcf3ce44SJohn Forte #include <ql_debug.h>
47fcf3ce44SJohn Forte #include <ql_iocb.h>
48fcf3ce44SJohn Forte #include <ql_isr.h>
49fcf3ce44SJohn Forte #include <ql_xioctl.h>
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte /*
52fcf3ce44SJohn Forte  * Local Function Prototypes.
53fcf3ce44SJohn Forte  */
545dfd244aSDaniel Beauregard static int ql_req_pkt(ql_adapter_state_t *, request_t **);
55fcf3ce44SJohn Forte static void ql_continuation_iocb(ql_adapter_state_t *, ddi_dma_cookie_t *,
56fcf3ce44SJohn Forte     uint16_t, boolean_t);
57fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *);
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte /*
60fcf3ce44SJohn Forte  * ql_start_iocb
61fcf3ce44SJohn Forte  *	The start IOCB is responsible for building request packets
62fcf3ce44SJohn Forte  *	on request ring and modifying ISP input pointer.
63fcf3ce44SJohn Forte  *
64fcf3ce44SJohn Forte  * Input:
65fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
66fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
67fcf3ce44SJohn Forte  *
68fcf3ce44SJohn Forte  * Context:
69fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
70fcf3ce44SJohn Forte  */
71fcf3ce44SJohn Forte void
72fcf3ce44SJohn Forte ql_start_iocb(ql_adapter_state_t *vha, ql_srb_t *sp)
73fcf3ce44SJohn Forte {
74fcf3ce44SJohn Forte 	ql_link_t		*link;
75fcf3ce44SJohn Forte 	request_t		*pkt;
76fcf3ce44SJohn Forte 	uint64_t		*ptr64;
77fcf3ce44SJohn Forte 	uint32_t		cnt;
78fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
81fcf3ce44SJohn Forte 
82fcf3ce44SJohn Forte 	/* Acquire ring lock. */
83fcf3ce44SJohn Forte 	REQUEST_RING_LOCK(ha);
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte 	if (sp != NULL) {
86fcf3ce44SJohn Forte 		/*
8716dd44c2SDaniel Beauregard 		 * If the pending queue is not empty maintain order
8816dd44c2SDaniel Beauregard 		 * by puting this srb at the tail and geting the head.
89fcf3ce44SJohn Forte 		 */
90fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) != NULL) {
91fcf3ce44SJohn Forte 			ql_add_link_b(&ha->pending_cmds, &sp->cmd);
92fcf3ce44SJohn Forte 			/* Remove command from pending command queue */
93fcf3ce44SJohn Forte 			sp = link->base_address;
94fcf3ce44SJohn Forte 			ql_remove_link(&ha->pending_cmds, &sp->cmd);
95fcf3ce44SJohn Forte 		}
96fcf3ce44SJohn Forte 	} else {
97fcf3ce44SJohn Forte 		/* Get command from pending command queue if not empty. */
98fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) == NULL) {
99fcf3ce44SJohn Forte 			/* Release ring specific lock */
100fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
101fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): empty done\n",
102fcf3ce44SJohn Forte 			    ha->instance);
103fcf3ce44SJohn Forte 			return;
104fcf3ce44SJohn Forte 		}
105fcf3ce44SJohn Forte 		/* Remove command from pending command queue */
106fcf3ce44SJohn Forte 		sp = link->base_address;
107fcf3ce44SJohn Forte 		ql_remove_link(&ha->pending_cmds, &sp->cmd);
108fcf3ce44SJohn Forte 	}
109fcf3ce44SJohn Forte 
11016dd44c2SDaniel Beauregard 	/* start this request and as many others as possible */
111fcf3ce44SJohn Forte 	for (;;) {
112fcf3ce44SJohn Forte 		if (ha->req_q_cnt < sp->req_cnt) {
113fcf3ce44SJohn Forte 			/* Calculate number of free request entries. */
114fcf3ce44SJohn Forte 			cnt = RD16_IO_REG(ha, req_out);
115fcf3ce44SJohn Forte 			if (ha->req_ring_index < cnt)  {
116fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)
117fcf3ce44SJohn Forte 				    (cnt - ha->req_ring_index);
118fcf3ce44SJohn Forte 			} else {
119fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)(REQUEST_ENTRY_CNT -
120fcf3ce44SJohn Forte 				    (ha->req_ring_index - cnt));
121fcf3ce44SJohn Forte 			}
122fcf3ce44SJohn Forte 			if (ha->req_q_cnt != 0) {
123fcf3ce44SJohn Forte 				ha->req_q_cnt--;
124fcf3ce44SJohn Forte 			}
125fcf3ce44SJohn Forte 
12616dd44c2SDaniel Beauregard 			/*
12716dd44c2SDaniel Beauregard 			 * If no room in request ring put this srb at
12816dd44c2SDaniel Beauregard 			 * the head of the pending queue and exit.
12916dd44c2SDaniel Beauregard 			 */
130fcf3ce44SJohn Forte 			if (ha->req_q_cnt < sp->req_cnt) {
131fcf3ce44SJohn Forte 				QL_PRINT_8(CE_CONT, "(%d): request ring full,"
132fcf3ce44SJohn Forte 				    " req_q_cnt=%d, req_ring_index=%d\n",
133fcf3ce44SJohn Forte 				    ha->instance, ha->req_q_cnt,
134fcf3ce44SJohn Forte 				    ha->req_ring_index);
135fcf3ce44SJohn Forte 				ql_add_link_t(&ha->pending_cmds, &sp->cmd);
136fcf3ce44SJohn Forte 				break;
137fcf3ce44SJohn Forte 			}
138fcf3ce44SJohn Forte 		}
139fcf3ce44SJohn Forte 
140fcf3ce44SJohn Forte 		/* Check for room in outstanding command list. */
141fcf3ce44SJohn Forte 		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
142fcf3ce44SJohn Forte 			ha->osc_index++;
143fcf3ce44SJohn Forte 			if (ha->osc_index == MAX_OUTSTANDING_COMMANDS) {
144fcf3ce44SJohn Forte 				ha->osc_index = 1;
145fcf3ce44SJohn Forte 			}
146fcf3ce44SJohn Forte 			if (ha->outstanding_cmds[ha->osc_index] == NULL) {
147fcf3ce44SJohn Forte 				break;
148fcf3ce44SJohn Forte 			}
149fcf3ce44SJohn Forte 		}
15016dd44c2SDaniel Beauregard 		/*
15116dd44c2SDaniel Beauregard 		 * If no room in outstanding array put this srb at
15216dd44c2SDaniel Beauregard 		 * the head of the pending queue and exit.
15316dd44c2SDaniel Beauregard 		 */
154fcf3ce44SJohn Forte 		if (cnt == MAX_OUTSTANDING_COMMANDS) {
155fcf3ce44SJohn Forte 			QL_PRINT_8(CE_CONT, "(%d): no room in outstanding "
156fcf3ce44SJohn Forte 			    "array\n", ha->instance);
157fcf3ce44SJohn Forte 			ql_add_link_t(&ha->pending_cmds, &sp->cmd);
158fcf3ce44SJohn Forte 			break;
159fcf3ce44SJohn Forte 		}
160fcf3ce44SJohn Forte 
16116dd44c2SDaniel Beauregard 		/* nothing to stop us now. */
162fcf3ce44SJohn Forte 		ha->outstanding_cmds[ha->osc_index] = sp;
16316dd44c2SDaniel Beauregard 		/* create and save a unique response identifier in the srb */
164fcf3ce44SJohn Forte 		sp->handle = ha->adapter_stats->ncmds << OSC_INDEX_SHIFT |
165fcf3ce44SJohn Forte 		    ha->osc_index;
166fcf3ce44SJohn Forte 		ha->req_q_cnt -= sp->req_cnt;
16716dd44c2SDaniel Beauregard 
16816dd44c2SDaniel Beauregard 		/* build the iocb in the request ring */
169fcf3ce44SJohn Forte 		pkt = ha->request_ring_ptr;
170fcf3ce44SJohn Forte 		sp->flags |= SRB_IN_TOKEN_ARRAY;
171fcf3ce44SJohn Forte 
172fcf3ce44SJohn Forte 		/* Zero out packet. */
173fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
174fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
175fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
176fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
177fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
178fcf3ce44SJohn Forte 
179fcf3ce44SJohn Forte 		/* Setup IOCB common data. */
180fcf3ce44SJohn Forte 		pkt->entry_count = (uint8_t)sp->req_cnt;
181fcf3ce44SJohn Forte 		pkt->sys_define = (uint8_t)ha->req_ring_index;
18216dd44c2SDaniel Beauregard 		/* mark the iocb with the response identifier */
183fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, &pkt->handle,
184fcf3ce44SJohn Forte 		    (uint32_t)sp->handle);
185fcf3ce44SJohn Forte 
18616dd44c2SDaniel Beauregard 		/* Setup IOCB unique data. */
187fcf3ce44SJohn Forte 		(sp->iocb)(vha, sp, pkt);
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_STARTED;
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d,%d): req packet, sp=%p\n",
192fcf3ce44SJohn Forte 		    ha->instance, vha->vp_index, (void *)sp);
193fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
194fcf3ce44SJohn Forte 
195fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
196fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
197fcf3ce44SJohn Forte 		    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
198fcf3ce44SJohn Forte 		    REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE,
199fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
200fcf3ce44SJohn Forte 
201fcf3ce44SJohn Forte 		/* Adjust ring index. */
202fcf3ce44SJohn Forte 		ha->req_ring_index++;
203fcf3ce44SJohn Forte 		if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
204fcf3ce44SJohn Forte 			ha->req_ring_index = 0;
205fcf3ce44SJohn Forte 			ha->request_ring_ptr = ha->request_ring_bp;
206fcf3ce44SJohn Forte 		} else {
207fcf3ce44SJohn Forte 			ha->request_ring_ptr++;
208fcf3ce44SJohn Forte 		}
209fcf3ce44SJohn Forte 
210fcf3ce44SJohn Forte 		/* Reset watchdog timer */
211fcf3ce44SJohn Forte 		sp->wdg_q_time = sp->init_wdg_q_time;
212fcf3ce44SJohn Forte 
21316dd44c2SDaniel Beauregard 		/*
21416dd44c2SDaniel Beauregard 		 * Send it by setting the new ring index in the ISP Request
21516dd44c2SDaniel Beauregard 		 * Ring In Pointer register.  This is the mechanism
21616dd44c2SDaniel Beauregard 		 * used to notify the isp that a new iocb has been
21716dd44c2SDaniel Beauregard 		 * placed on the request ring.
21816dd44c2SDaniel Beauregard 		 */
219*eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_8021)) {
220*eb82ff87SDaniel Beauregard 			uint32_t	w32;
221*eb82ff87SDaniel Beauregard 
222*eb82ff87SDaniel Beauregard 			w32 = ha->req_ring_index << 16 |
223*eb82ff87SDaniel Beauregard 			    ha->function_number << 5 | 4;
224*eb82ff87SDaniel Beauregard 			do {
225*eb82ff87SDaniel Beauregard 				ddi_put32(ha->db_dev_handle, ha->nx_req_in,
226*eb82ff87SDaniel Beauregard 				    w32);
227*eb82ff87SDaniel Beauregard 			} while (RD_REG_DWORD(ha, ha->db_read) != w32);
228*eb82ff87SDaniel Beauregard 
229*eb82ff87SDaniel Beauregard 		} else {
230*eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, req_in, ha->req_ring_index);
231*eb82ff87SDaniel Beauregard 		}
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 		/* Update outstanding command count statistic. */
234fcf3ce44SJohn Forte 		ha->adapter_stats->ncmds++;
235fcf3ce44SJohn Forte 
23616dd44c2SDaniel Beauregard 		/* if there is a pending command, try to start it. */
237fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) == NULL) {
238fcf3ce44SJohn Forte 			break;
239fcf3ce44SJohn Forte 		}
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 		/* Remove command from pending command queue */
242fcf3ce44SJohn Forte 		sp = link->base_address;
243fcf3ce44SJohn Forte 		ql_remove_link(&ha->pending_cmds, &sp->cmd);
244fcf3ce44SJohn Forte 	}
245fcf3ce44SJohn Forte 
246fcf3ce44SJohn Forte 	/* Release ring specific lock */
247fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
248fcf3ce44SJohn Forte 
249fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
250fcf3ce44SJohn Forte }
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte /*
253fcf3ce44SJohn Forte  * ql_req_pkt
254fcf3ce44SJohn Forte  *	Function is responsible for locking ring and
255fcf3ce44SJohn Forte  *	getting a zeroed out request packet.
256fcf3ce44SJohn Forte  *
257fcf3ce44SJohn Forte  * Input:
258fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
259fcf3ce44SJohn Forte  *	pkt:	address for packet pointer.
260fcf3ce44SJohn Forte  *
261fcf3ce44SJohn Forte  * Returns:
262fcf3ce44SJohn Forte  *	ql local function return status code.
263fcf3ce44SJohn Forte  *
264fcf3ce44SJohn Forte  * Context:
265fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
266fcf3ce44SJohn Forte  */
2675dfd244aSDaniel Beauregard static int
268fcf3ce44SJohn Forte ql_req_pkt(ql_adapter_state_t *vha, request_t **pktp)
269fcf3ce44SJohn Forte {
270fcf3ce44SJohn Forte 	uint16_t		cnt;
271fcf3ce44SJohn Forte 	uint32_t		*long_ptr;
272fcf3ce44SJohn Forte 	uint32_t		timer;
273fcf3ce44SJohn Forte 	int			rval = QL_FUNCTION_TIMEOUT;
274fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
275fcf3ce44SJohn Forte 
276fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
277fcf3ce44SJohn Forte 
278fcf3ce44SJohn Forte 	/* Wait for 30 seconds for slot. */
279fcf3ce44SJohn Forte 	for (timer = 30000; timer != 0; timer--) {
280fcf3ce44SJohn Forte 		/* Acquire ring lock. */
281fcf3ce44SJohn Forte 		REQUEST_RING_LOCK(ha);
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 		if (ha->req_q_cnt == 0) {
284fcf3ce44SJohn Forte 			/* Calculate number of free request entries. */
285fcf3ce44SJohn Forte 			cnt = RD16_IO_REG(ha, req_out);
286fcf3ce44SJohn Forte 			if (ha->req_ring_index < cnt) {
287fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)
288fcf3ce44SJohn Forte 				    (cnt - ha->req_ring_index);
289fcf3ce44SJohn Forte 			} else {
290fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)
291fcf3ce44SJohn Forte 				    (REQUEST_ENTRY_CNT -
292fcf3ce44SJohn Forte 				    (ha->req_ring_index - cnt));
293fcf3ce44SJohn Forte 			}
294fcf3ce44SJohn Forte 			if (ha->req_q_cnt != 0) {
295fcf3ce44SJohn Forte 				ha->req_q_cnt--;
296fcf3ce44SJohn Forte 			}
297fcf3ce44SJohn Forte 		}
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 		/* Found empty request ring slot? */
300fcf3ce44SJohn Forte 		if (ha->req_q_cnt != 0) {
301fcf3ce44SJohn Forte 			ha->req_q_cnt--;
302fcf3ce44SJohn Forte 			*pktp = ha->request_ring_ptr;
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte 			/* Zero out packet. */
305fcf3ce44SJohn Forte 			long_ptr = (uint32_t *)ha->request_ring_ptr;
306fcf3ce44SJohn Forte 			for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) {
307fcf3ce44SJohn Forte 				*long_ptr++ = 0;
308fcf3ce44SJohn Forte 			}
309fcf3ce44SJohn Forte 
310fcf3ce44SJohn Forte 			/* Setup IOCB common data. */
311fcf3ce44SJohn Forte 			ha->request_ring_ptr->entry_count = 1;
312fcf3ce44SJohn Forte 			ha->request_ring_ptr->sys_define =
313fcf3ce44SJohn Forte 			    (uint8_t)ha->req_ring_index;
314fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle,
315fcf3ce44SJohn Forte 			    &ha->request_ring_ptr->handle,
316fcf3ce44SJohn Forte 			    (uint32_t)QL_FCA_BRAND);
317fcf3ce44SJohn Forte 
318fcf3ce44SJohn Forte 			rval = QL_SUCCESS;
319fcf3ce44SJohn Forte 
320fcf3ce44SJohn Forte 			break;
321fcf3ce44SJohn Forte 		}
322fcf3ce44SJohn Forte 
323fcf3ce44SJohn Forte 		/* Release request queue lock. */
324fcf3ce44SJohn Forte 		REQUEST_RING_UNLOCK(ha);
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 		/* Check for pending interrupts. */
329fcf3ce44SJohn Forte 		/*
330fcf3ce44SJohn Forte 		 * XXX protect interrupt routine from calling itself.
331fcf3ce44SJohn Forte 		 * Need to revisit this routine. So far we never
332fcf3ce44SJohn Forte 		 * hit this case as req slot was available
333fcf3ce44SJohn Forte 		 */
334fcf3ce44SJohn Forte 		if ((!(curthread->t_flag & T_INTR_THREAD)) &&
335*eb82ff87SDaniel Beauregard 		    INTERRUPT_PENDING(ha)) {
336fcf3ce44SJohn Forte 			(void) ql_isr((caddr_t)ha);
337fcf3ce44SJohn Forte 			INTR_LOCK(ha);
338fcf3ce44SJohn Forte 			ha->intr_claimed = TRUE;
339fcf3ce44SJohn Forte 			INTR_UNLOCK(ha);
340fcf3ce44SJohn Forte 		}
341fcf3ce44SJohn Forte 	}
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
344fcf3ce44SJohn Forte 		ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
345fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval);
346fcf3ce44SJohn Forte 	} else {
347fcf3ce44SJohn Forte 		/*EMPTY*/
348fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
349fcf3ce44SJohn Forte 	}
350fcf3ce44SJohn Forte 	return (rval);
351fcf3ce44SJohn Forte }
352fcf3ce44SJohn Forte 
353fcf3ce44SJohn Forte /*
354fcf3ce44SJohn Forte  * ql_isp_cmd
355fcf3ce44SJohn Forte  *	Function is responsible for modifying ISP input pointer.
35616dd44c2SDaniel Beauregard  *	This action notifies the isp that a new request has been
35716dd44c2SDaniel Beauregard  *	added to the request ring.
35816dd44c2SDaniel Beauregard  *
359fcf3ce44SJohn Forte  *	Releases ring lock.
360fcf3ce44SJohn Forte  *
361fcf3ce44SJohn Forte  * Input:
362fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
363fcf3ce44SJohn Forte  *
364fcf3ce44SJohn Forte  * Context:
365fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
366fcf3ce44SJohn Forte  */
367fcf3ce44SJohn Forte void
368fcf3ce44SJohn Forte ql_isp_cmd(ql_adapter_state_t *vha)
369fcf3ce44SJohn Forte {
370fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 	QL_PRINT_5(CE_CONT, "(%d): req packet:\n", ha->instance);
375fcf3ce44SJohn Forte 	QL_DUMP_5((uint8_t *)ha->request_ring_ptr, 8, REQUEST_ENTRY_SIZE);
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte 	/* Sync DMA buffer. */
378fcf3ce44SJohn Forte 	(void) ddi_dma_sync(ha->hba_buf.dma_handle,
379fcf3ce44SJohn Forte 	    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
380fcf3ce44SJohn Forte 	    REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE,
381fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
382fcf3ce44SJohn Forte 
383fcf3ce44SJohn Forte 	/* Adjust ring index. */
384fcf3ce44SJohn Forte 	ha->req_ring_index++;
385fcf3ce44SJohn Forte 	if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
386fcf3ce44SJohn Forte 		ha->req_ring_index = 0;
387fcf3ce44SJohn Forte 		ha->request_ring_ptr = ha->request_ring_bp;
388fcf3ce44SJohn Forte 	} else {
389fcf3ce44SJohn Forte 		ha->request_ring_ptr++;
390fcf3ce44SJohn Forte 	}
391fcf3ce44SJohn Forte 
392fcf3ce44SJohn Forte 	/* Set chip new ring index. */
393*eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
394*eb82ff87SDaniel Beauregard 		uint32_t	w32;
395*eb82ff87SDaniel Beauregard 
396*eb82ff87SDaniel Beauregard 		w32 = ha->req_ring_index << 16 |
397*eb82ff87SDaniel Beauregard 		    ha->function_number << 5 | 4;
398*eb82ff87SDaniel Beauregard 		do {
399*eb82ff87SDaniel Beauregard 			ddi_put32(ha->db_dev_handle, ha->nx_req_in, w32);
400*eb82ff87SDaniel Beauregard 		} while (RD_REG_DWORD(ha, ha->db_read) != w32);
401*eb82ff87SDaniel Beauregard 
402*eb82ff87SDaniel Beauregard 	} else {
403*eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, req_in, ha->req_ring_index);
404*eb82ff87SDaniel Beauregard 	}
405fcf3ce44SJohn Forte 
406fcf3ce44SJohn Forte 	/* Release ring lock. */
407fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
408fcf3ce44SJohn Forte 
409fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
410fcf3ce44SJohn Forte }
411fcf3ce44SJohn Forte 
412fcf3ce44SJohn Forte /*
413fcf3ce44SJohn Forte  * ql_command_iocb
414fcf3ce44SJohn Forte  *	Setup of command IOCB.
415fcf3ce44SJohn Forte  *
416fcf3ce44SJohn Forte  * Input:
417fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
418fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
419fcf3ce44SJohn Forte  *
420fcf3ce44SJohn Forte  *	arg:	request queue packet.
421fcf3ce44SJohn Forte  *
422fcf3ce44SJohn Forte  * Context:
423fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
424fcf3ce44SJohn Forte  */
425fcf3ce44SJohn Forte void
426fcf3ce44SJohn Forte ql_command_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
427fcf3ce44SJohn Forte {
428fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
429fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
430fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
431fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
432fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
433fcf3ce44SJohn Forte 	cmd_entry_t		*pkt = arg;
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
436fcf3ce44SJohn Forte 
437fcf3ce44SJohn Forte 	/* Set LUN number */
438fcf3ce44SJohn Forte 	pkt->lun_l = LSB(sp->lun_queue->lun_no);
439fcf3ce44SJohn Forte 	pkt->lun_h = MSB(sp->lun_queue->lun_no);
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 	/* Set target ID */
442fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
443fcf3ce44SJohn Forte 		pkt->target_l = LSB(tq->loop_id);
444fcf3ce44SJohn Forte 		pkt->target_h = MSB(tq->loop_id);
445fcf3ce44SJohn Forte 	} else {
446fcf3ce44SJohn Forte 		pkt->target_h = LSB(tq->loop_id);
447fcf3ce44SJohn Forte 	}
448fcf3ce44SJohn Forte 
449fcf3ce44SJohn Forte 	/* Set tag queue control flags */
450fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
451fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
452fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_HTAG);
453fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
454fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
455fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_OTAG);
456fcf3ce44SJohn Forte 	/* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */
457fcf3ce44SJohn Forte 	} else {
458fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
459fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_STAG);
460fcf3ce44SJohn Forte 	}
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
463fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout);
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte 	/* Load SCSI CDB */
466fcf3ce44SJohn Forte 	ddi_rep_put8(ha->hba_buf.acc_handle, fcp->fcp_cdb,
467fcf3ce44SJohn Forte 	    pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR);
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
470fcf3ce44SJohn Forte 		pkt->entry_type = IOCB_CMD_TYPE_3;
471fcf3ce44SJohn Forte 		cnt = CMD_TYPE_3_DATA_SEGMENTS;
472fcf3ce44SJohn Forte 	} else {
473fcf3ce44SJohn Forte 		pkt->entry_type = IOCB_CMD_TYPE_2;
474fcf3ce44SJohn Forte 		cnt = CMD_TYPE_2_DATA_SEGMENTS;
475fcf3ce44SJohn Forte 	}
476fcf3ce44SJohn Forte 
477fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
478fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
479fcf3ce44SJohn Forte 		ha->xioctl->IOControlRequests++;
480fcf3ce44SJohn Forte 		return;
481fcf3ce44SJohn Forte 	}
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 	/*
484fcf3ce44SJohn Forte 	 * Set transfer direction. Load Data segments.
485fcf3ce44SJohn Forte 	 */
486fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
487fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
488fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_OUT);
489fcf3ce44SJohn Forte 		ha->xioctl->IOOutputRequests++;
490fcf3ce44SJohn Forte 		ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
491fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
492fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
493fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_IN);
494fcf3ce44SJohn Forte 		ha->xioctl->IOInputRequests++;
495fcf3ce44SJohn Forte 		ha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
496fcf3ce44SJohn Forte 	}
497fcf3ce44SJohn Forte 
498fcf3ce44SJohn Forte 	/* Set data segment count. */
499fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
500fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
501fcf3ce44SJohn Forte 
502fcf3ce44SJohn Forte 	/* Load total byte count. */
503fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, fcp->fcp_data_len);
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	/* Load command data segment. */
506fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
507fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
508fcf3ce44SJohn Forte 	while (cnt && seg_cnt) {
509fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
510fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
511fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle, ptr32++,
512fcf3ce44SJohn Forte 			    cp->dmac_notused);
513fcf3ce44SJohn Forte 		}
514fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++,
515fcf3ce44SJohn Forte 		    (uint32_t)cp->dmac_size);
516fcf3ce44SJohn Forte 		seg_cnt--;
517fcf3ce44SJohn Forte 		cnt--;
518fcf3ce44SJohn Forte 		cp++;
519fcf3ce44SJohn Forte 	}
520fcf3ce44SJohn Forte 
521fcf3ce44SJohn Forte 	/*
522fcf3ce44SJohn Forte 	 * Build continuation packets.
523fcf3ce44SJohn Forte 	 */
524fcf3ce44SJohn Forte 	if (seg_cnt) {
525fcf3ce44SJohn Forte 		ql_continuation_iocb(ha, cp, seg_cnt,
526fcf3ce44SJohn Forte 		    (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
527fcf3ce44SJohn Forte 	}
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
530fcf3ce44SJohn Forte }
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte /*
533fcf3ce44SJohn Forte  * ql_continuation_iocb
534fcf3ce44SJohn Forte  *	Setup of continuation IOCB.
535fcf3ce44SJohn Forte  *
536fcf3ce44SJohn Forte  * Input:
537fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
538fcf3ce44SJohn Forte  *	cp:		cookie list pointer.
539fcf3ce44SJohn Forte  *	seg_cnt:	number of segments.
540fcf3ce44SJohn Forte  *	addr64:		64 bit addresses.
541fcf3ce44SJohn Forte  *
542fcf3ce44SJohn Forte  * Context:
543fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
544fcf3ce44SJohn Forte  */
545fcf3ce44SJohn Forte static void
546fcf3ce44SJohn Forte ql_continuation_iocb(ql_adapter_state_t *ha, ddi_dma_cookie_t *cp,
547fcf3ce44SJohn Forte     uint16_t seg_cnt, boolean_t addr64)
548fcf3ce44SJohn Forte {
549fcf3ce44SJohn Forte 	cont_entry_t	*pkt;
550fcf3ce44SJohn Forte 	uint64_t	*ptr64;
551fcf3ce44SJohn Forte 	uint32_t	*ptr32, cnt;
552fcf3ce44SJohn Forte 
553fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 	/*
556fcf3ce44SJohn Forte 	 * Build continuation packets.
557fcf3ce44SJohn Forte 	 */
558fcf3ce44SJohn Forte 	while (seg_cnt) {
559fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
560fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
561fcf3ce44SJohn Forte 		    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
562fcf3ce44SJohn Forte 		    REQUEST_Q_BUFFER_OFFSET), REQUEST_ENTRY_SIZE,
563fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
564fcf3ce44SJohn Forte 
565fcf3ce44SJohn Forte 		/* Adjust ring pointer, and deal with wrap. */
566fcf3ce44SJohn Forte 		ha->req_ring_index++;
567fcf3ce44SJohn Forte 		if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
568fcf3ce44SJohn Forte 			ha->req_ring_index = 0;
569fcf3ce44SJohn Forte 			ha->request_ring_ptr = ha->request_ring_bp;
570fcf3ce44SJohn Forte 		} else {
571fcf3ce44SJohn Forte 			ha->request_ring_ptr++;
572fcf3ce44SJohn Forte 		}
573fcf3ce44SJohn Forte 		pkt = (cont_entry_t *)ha->request_ring_ptr;
574fcf3ce44SJohn Forte 
575fcf3ce44SJohn Forte 		/* Zero out packet. */
576fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
577fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
578fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
579fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
580fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
581fcf3ce44SJohn Forte 
582fcf3ce44SJohn Forte 		/*
583fcf3ce44SJohn Forte 		 * Build continuation packet.
584fcf3ce44SJohn Forte 		 */
585fcf3ce44SJohn Forte 		pkt->entry_count = 1;
586fcf3ce44SJohn Forte 		pkt->sys_define = (uint8_t)ha->req_ring_index;
587fcf3ce44SJohn Forte 		if (addr64) {
588fcf3ce44SJohn Forte 			pkt->entry_type = CONTINUATION_TYPE_1;
589fcf3ce44SJohn Forte 			cnt = CONT_TYPE_1_DATA_SEGMENTS;
590fcf3ce44SJohn Forte 			ptr32 = (uint32_t *)
591fcf3ce44SJohn Forte 			    &((cont_type_1_entry_t *)pkt)->dseg_0_address;
592fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
593fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
594fcf3ce44SJohn Forte 				    cp->dmac_address);
595fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
596fcf3ce44SJohn Forte 				    cp->dmac_notused);
597fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
598fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
599fcf3ce44SJohn Forte 				seg_cnt--;
600fcf3ce44SJohn Forte 				cnt--;
601fcf3ce44SJohn Forte 				cp++;
602fcf3ce44SJohn Forte 			}
603fcf3ce44SJohn Forte 		} else {
604fcf3ce44SJohn Forte 			pkt->entry_type = CONTINUATION_TYPE_0;
605fcf3ce44SJohn Forte 			cnt = CONT_TYPE_0_DATA_SEGMENTS;
606fcf3ce44SJohn Forte 			ptr32 = (uint32_t *)&pkt->dseg_0_address;
607fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
608fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
609fcf3ce44SJohn Forte 				    cp->dmac_address);
610fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
611fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
612fcf3ce44SJohn Forte 				seg_cnt--;
613fcf3ce44SJohn Forte 				cnt--;
614fcf3ce44SJohn Forte 				cp++;
615fcf3ce44SJohn Forte 			}
616fcf3ce44SJohn Forte 		}
617fcf3ce44SJohn Forte 
618fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d): packet:\n", ha->instance);
619fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
620fcf3ce44SJohn Forte 	}
621fcf3ce44SJohn Forte 
622fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
623fcf3ce44SJohn Forte }
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte /*
626fcf3ce44SJohn Forte  * ql_command_24xx_iocb
627fcf3ce44SJohn Forte  *	Setup of ISP24xx command IOCB.
628fcf3ce44SJohn Forte  *
629fcf3ce44SJohn Forte  * Input:
630fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
631fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
632fcf3ce44SJohn Forte  *	arg:	request queue packet.
633fcf3ce44SJohn Forte  *
634fcf3ce44SJohn Forte  * Context:
635fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
636fcf3ce44SJohn Forte  */
637fcf3ce44SJohn Forte void
638fcf3ce44SJohn Forte ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
639fcf3ce44SJohn Forte {
640fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
641fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
642fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
643fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
644fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
645fcf3ce44SJohn Forte 	cmd_24xx_entry_t	*pkt = arg;
646fcf3ce44SJohn Forte 	ql_adapter_state_t	*pha = ha->pha;
647fcf3ce44SJohn Forte 
648fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
649fcf3ce44SJohn Forte 
650fcf3ce44SJohn Forte 	pkt->entry_type = IOCB_CMD_TYPE_7;
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte 	/* Set LUN number */
653fcf3ce44SJohn Forte 	pkt->fcp_lun[2] = LSB(sp->lun_queue->lun_no);
654fcf3ce44SJohn Forte 	pkt->fcp_lun[3] = MSB(sp->lun_queue->lun_no);
655fcf3ce44SJohn Forte 
656fcf3ce44SJohn Forte 	/* Set N_port handle */
657fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id);
658fcf3ce44SJohn Forte 
659fcf3ce44SJohn Forte 	/* Set target ID */
660fcf3ce44SJohn Forte 	pkt->target_id[0] = tq->d_id.b.al_pa;
661fcf3ce44SJohn Forte 	pkt->target_id[1] = tq->d_id.b.area;
662fcf3ce44SJohn Forte 	pkt->target_id[2] = tq->d_id.b.domain;
663fcf3ce44SJohn Forte 
664fcf3ce44SJohn Forte 	pkt->vp_index = ha->vp_index;
665fcf3ce44SJohn Forte 
666fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
667fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
668fcf3ce44SJohn Forte 		ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout,
669fcf3ce44SJohn Forte 		    sp->isp_timeout);
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	/* Load SCSI CDB */
673fcf3ce44SJohn Forte 	ddi_rep_put8(pha->hba_buf.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb,
674fcf3ce44SJohn Forte 	    MAX_CMDSZ, DDI_DEV_AUTOINCR);
675fcf3ce44SJohn Forte 	for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
676fcf3ce44SJohn Forte 		ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4);
677fcf3ce44SJohn Forte 	}
678fcf3ce44SJohn Forte 
679fcf3ce44SJohn Forte 	/*
680fcf3ce44SJohn Forte 	 * Set tag queue control flags
681fcf3ce44SJohn Forte 	 * Note:
682fcf3ce44SJohn Forte 	 *	Cannot copy fcp->fcp_cntl.cntl_qtype directly,
683fcf3ce44SJohn Forte 	 *	problem with x86 in 32bit kernel mode
684fcf3ce44SJohn Forte 	 */
685fcf3ce44SJohn Forte 	switch (fcp->fcp_cntl.cntl_qtype) {
686fcf3ce44SJohn Forte 	case FCP_QTYPE_SIMPLE:
687fcf3ce44SJohn Forte 		pkt->task = TA_STAG;
688fcf3ce44SJohn Forte 		break;
689fcf3ce44SJohn Forte 	case FCP_QTYPE_HEAD_OF_Q:
690fcf3ce44SJohn Forte 		pkt->task = TA_HTAG;
691fcf3ce44SJohn Forte 		break;
692fcf3ce44SJohn Forte 	case FCP_QTYPE_ORDERED:
693fcf3ce44SJohn Forte 		pkt->task = TA_OTAG;
694fcf3ce44SJohn Forte 		break;
695fcf3ce44SJohn Forte 	case FCP_QTYPE_ACA_Q_TAG:
696fcf3ce44SJohn Forte 		pkt->task = TA_ACA;
697fcf3ce44SJohn Forte 		break;
698fcf3ce44SJohn Forte 	case FCP_QTYPE_UNTAGGED:
699fcf3ce44SJohn Forte 		pkt->task = TA_UNTAGGED;
700fcf3ce44SJohn Forte 		break;
701fcf3ce44SJohn Forte 	default:
702fcf3ce44SJohn Forte 		break;
703fcf3ce44SJohn Forte 	}
704fcf3ce44SJohn Forte 
705fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
706fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
707fcf3ce44SJohn Forte 		pha->xioctl->IOControlRequests++;
708fcf3ce44SJohn Forte 		return;
709fcf3ce44SJohn Forte 	}
710fcf3ce44SJohn Forte 
711fcf3ce44SJohn Forte 	/* Set transfer direction. */
712fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
713fcf3ce44SJohn Forte 		pkt->control_flags = CF_WR;
714fcf3ce44SJohn Forte 		pha->xioctl->IOOutputRequests++;
715fcf3ce44SJohn Forte 		pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
716fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
717fcf3ce44SJohn Forte 		pkt->control_flags = CF_RD;
718fcf3ce44SJohn Forte 		pha->xioctl->IOInputRequests++;
719fcf3ce44SJohn Forte 		pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
720fcf3ce44SJohn Forte 	}
721fcf3ce44SJohn Forte 
722fcf3ce44SJohn Forte 	/* Set data segment count. */
723fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
724fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 	/* Load total byte count. */
727fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count,
728fcf3ce44SJohn Forte 	    fcp->fcp_data_len);
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 	/* Load command data segment. */
731fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
732fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
733fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
734fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
735fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size);
736fcf3ce44SJohn Forte 	seg_cnt--;
737fcf3ce44SJohn Forte 	cp++;
738fcf3ce44SJohn Forte 
739fcf3ce44SJohn Forte 	/*
740fcf3ce44SJohn Forte 	 * Build continuation packets.
741fcf3ce44SJohn Forte 	 */
742fcf3ce44SJohn Forte 	if (seg_cnt) {
743fcf3ce44SJohn Forte 		ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE);
744fcf3ce44SJohn Forte 	}
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
747fcf3ce44SJohn Forte }
748fcf3ce44SJohn Forte 
749fcf3ce44SJohn Forte /*
750fcf3ce44SJohn Forte  * ql_marker
751fcf3ce44SJohn Forte  *	Function issues marker IOCB.
752fcf3ce44SJohn Forte  *
753fcf3ce44SJohn Forte  * Input:
754fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
755fcf3ce44SJohn Forte  *	loop_id:	device loop ID
756fcf3ce44SJohn Forte  *	lun:		device LUN
757fcf3ce44SJohn Forte  *	type:		marker modifier
758fcf3ce44SJohn Forte  *
759fcf3ce44SJohn Forte  * Returns:
760fcf3ce44SJohn Forte  *	ql local function return status code.
761fcf3ce44SJohn Forte  *
762fcf3ce44SJohn Forte  * Context:
763fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
764fcf3ce44SJohn Forte  */
765fcf3ce44SJohn Forte int
766fcf3ce44SJohn Forte ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, uint16_t lun,
767fcf3ce44SJohn Forte     uint8_t type)
768fcf3ce44SJohn Forte {
769fcf3ce44SJohn Forte 	mrk_entry_t	*pkt;
770fcf3ce44SJohn Forte 	int		rval;
771fcf3ce44SJohn Forte 
772fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
773fcf3ce44SJohn Forte 
774fcf3ce44SJohn Forte 	rval = ql_req_pkt(ha, (request_t **)&pkt);
775fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
776fcf3ce44SJohn Forte 		pkt->entry_type = MARKER_TYPE;
777fcf3ce44SJohn Forte 
778*eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
779fcf3ce44SJohn Forte 			marker_24xx_entry_t	*pkt24 =
780fcf3ce44SJohn Forte 			    (marker_24xx_entry_t *)pkt;
781fcf3ce44SJohn Forte 
782fcf3ce44SJohn Forte 			pkt24->modifier = type;
783fcf3ce44SJohn Forte 
784fcf3ce44SJohn Forte 			/* Set LUN number */
785fcf3ce44SJohn Forte 			pkt24->fcp_lun[2] = LSB(lun);
786fcf3ce44SJohn Forte 			pkt24->fcp_lun[3] = MSB(lun);
787fcf3ce44SJohn Forte 
788fcf3ce44SJohn Forte 			pkt24->vp_index = ha->vp_index;
789fcf3ce44SJohn Forte 
790fcf3ce44SJohn Forte 			/* Set N_port handle */
791fcf3ce44SJohn Forte 			ddi_put16(ha->pha->hba_buf.acc_handle,
792fcf3ce44SJohn Forte 			    &pkt24->n_port_hdl, loop_id);
793fcf3ce44SJohn Forte 
794fcf3ce44SJohn Forte 		} else {
795fcf3ce44SJohn Forte 			pkt->modifier = type;
796fcf3ce44SJohn Forte 
797fcf3ce44SJohn Forte 			pkt->lun_l = LSB(lun);
798fcf3ce44SJohn Forte 			pkt->lun_h = MSB(lun);
799fcf3ce44SJohn Forte 
800fcf3ce44SJohn Forte 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
801fcf3ce44SJohn Forte 				pkt->target_l = LSB(loop_id);
802fcf3ce44SJohn Forte 				pkt->target_h = MSB(loop_id);
803fcf3ce44SJohn Forte 			} else {
804fcf3ce44SJohn Forte 				pkt->target_h = LSB(loop_id);
805fcf3ce44SJohn Forte 			}
806fcf3ce44SJohn Forte 		}
807fcf3ce44SJohn Forte 
808fcf3ce44SJohn Forte 		/* Issue command to ISP */
809fcf3ce44SJohn Forte 		ql_isp_cmd(ha);
810fcf3ce44SJohn Forte 	}
811fcf3ce44SJohn Forte 
812fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
813fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
814fcf3ce44SJohn Forte 	} else {
815fcf3ce44SJohn Forte 		/*EMPTY*/
816fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
817fcf3ce44SJohn Forte 	}
818fcf3ce44SJohn Forte 	return (rval);
819fcf3ce44SJohn Forte }
820fcf3ce44SJohn Forte 
821fcf3ce44SJohn Forte /*
822fcf3ce44SJohn Forte  * ql_ms_iocb
823fcf3ce44SJohn Forte  *	Setup of name/management server IOCB.
824fcf3ce44SJohn Forte  *
825fcf3ce44SJohn Forte  * Input:
826fcf3ce44SJohn Forte  *	ha = adapter state pointer.
827fcf3ce44SJohn Forte  *	sp = srb structure pointer.
828fcf3ce44SJohn Forte  *	arg = request queue packet.
829fcf3ce44SJohn Forte  *
830fcf3ce44SJohn Forte  * Context:
831fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
832fcf3ce44SJohn Forte  */
833fcf3ce44SJohn Forte void
834fcf3ce44SJohn Forte ql_ms_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
835fcf3ce44SJohn Forte {
836fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
837fcf3ce44SJohn Forte 	uint32_t		*ptr32;
838fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
839fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
840fcf3ce44SJohn Forte 	ms_entry_t		*pkt = arg;
841fcf3ce44SJohn Forte 
842fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
843fcf3ce44SJohn Forte 	QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
844fcf3ce44SJohn Forte 	/*
845fcf3ce44SJohn Forte 	 * Build command packet.
846fcf3ce44SJohn Forte 	 */
847fcf3ce44SJohn Forte 	pkt->entry_type = MS_TYPE;
848fcf3ce44SJohn Forte 
849fcf3ce44SJohn Forte 	/* Set loop ID */
850fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
851fcf3ce44SJohn Forte 		pkt->loop_id_l = LSB(tq->loop_id);
852fcf3ce44SJohn Forte 		pkt->loop_id_h = MSB(tq->loop_id);
853fcf3ce44SJohn Forte 	} else {
854fcf3ce44SJohn Forte 		pkt->loop_id_h = LSB(tq->loop_id);
855fcf3ce44SJohn Forte 	}
856fcf3ce44SJohn Forte 
857fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
858fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout);
859fcf3ce44SJohn Forte 
860fcf3ce44SJohn Forte 	/* Set cmd data segment count. */
861fcf3ce44SJohn Forte 	pkt->cmd_dseg_count_l = 1;
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 	/* Set total data segment count */
864fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1);
865fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->total_dseg_count, seg_cnt);
866fcf3ce44SJohn Forte 
867fcf3ce44SJohn Forte 	/* Load ct cmd byte count. */
868fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->cmd_byte_count,
869fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
870fcf3ce44SJohn Forte 
871fcf3ce44SJohn Forte 	/* Load ct rsp byte count. */
872fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->resp_byte_count,
873fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_rsplen);
874fcf3ce44SJohn Forte 
875fcf3ce44SJohn Forte 	/* Load MS command data segments. */
876fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
877fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
878fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
879fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
880fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
881fcf3ce44SJohn Forte 	seg_cnt--;
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 	/* Load MS response entry data segments. */
884fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_resp_cookie;
885fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
886fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
887fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size);
888fcf3ce44SJohn Forte 	seg_cnt--;
889fcf3ce44SJohn Forte 	cp++;
890fcf3ce44SJohn Forte 
891fcf3ce44SJohn Forte 	/*
892fcf3ce44SJohn Forte 	 * Build continuation packets.
893fcf3ce44SJohn Forte 	 */
894fcf3ce44SJohn Forte 	if (seg_cnt) {
895fcf3ce44SJohn Forte 		ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE);
896fcf3ce44SJohn Forte 	}
897fcf3ce44SJohn Forte 
898fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
899fcf3ce44SJohn Forte }
900fcf3ce44SJohn Forte 
901fcf3ce44SJohn Forte /*
902fcf3ce44SJohn Forte  * ql_ms_24xx_iocb
903fcf3ce44SJohn Forte  *	Setup of name/management server IOCB.
904fcf3ce44SJohn Forte  *
905fcf3ce44SJohn Forte  * Input:
906fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
907fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
908fcf3ce44SJohn Forte  *	arg:	request queue packet.
909fcf3ce44SJohn Forte  *
910fcf3ce44SJohn Forte  * Context:
911fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
912fcf3ce44SJohn Forte  */
913fcf3ce44SJohn Forte void
914fcf3ce44SJohn Forte ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
915fcf3ce44SJohn Forte {
916fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
917fcf3ce44SJohn Forte 	uint32_t		*ptr32;
918fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
919fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
920fcf3ce44SJohn Forte 	ct_passthru_entry_t	*pkt = arg;
921fcf3ce44SJohn Forte 	ql_adapter_state_t	*pha = ha->pha;
922fcf3ce44SJohn Forte 
923fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
924fcf3ce44SJohn Forte 	QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
925fcf3ce44SJohn Forte 	/*
926fcf3ce44SJohn Forte 	 * Build command packet.
927fcf3ce44SJohn Forte 	 */
928fcf3ce44SJohn Forte 	pkt->entry_type = CT_PASSTHRU_TYPE;
929fcf3ce44SJohn Forte 
930fcf3ce44SJohn Forte 	/* Set loop ID */
931fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id);
932fcf3ce44SJohn Forte 
933fcf3ce44SJohn Forte 	pkt->vp_index = ha->vp_index;
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
936fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
937fcf3ce44SJohn Forte 		ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout,
938fcf3ce44SJohn Forte 		    sp->isp_timeout);
939fcf3ce44SJohn Forte 	}
940fcf3ce44SJohn Forte 
941fcf3ce44SJohn Forte 	/* Set cmd/response data segment counts. */
942fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->cmd_dseg_count, 1);
943fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt;
944fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->resp_dseg_count, seg_cnt);
945fcf3ce44SJohn Forte 
946fcf3ce44SJohn Forte 	/* Load ct cmd byte count. */
947fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, &pkt->cmd_byte_count,
948fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
949fcf3ce44SJohn Forte 
950fcf3ce44SJohn Forte 	/* Load ct rsp byte count. */
951fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, &pkt->resp_byte_count,
952fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_rsplen);
953fcf3ce44SJohn Forte 
954fcf3ce44SJohn Forte 	/* Load MS command entry data segments. */
955fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
956fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
957fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
958fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
959fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
960fcf3ce44SJohn Forte 
961fcf3ce44SJohn Forte 	/* Load MS response entry data segments. */
962fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_resp_cookie;
963fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
964fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
965fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size);
966fcf3ce44SJohn Forte 	seg_cnt--;
967fcf3ce44SJohn Forte 	cp++;
968fcf3ce44SJohn Forte 
969fcf3ce44SJohn Forte 	/*
970fcf3ce44SJohn Forte 	 * Build continuation packets.
971fcf3ce44SJohn Forte 	 */
972fcf3ce44SJohn Forte 	if (seg_cnt) {
973fcf3ce44SJohn Forte 		ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE);
974fcf3ce44SJohn Forte 	}
975fcf3ce44SJohn Forte 
976fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
977fcf3ce44SJohn Forte }
978fcf3ce44SJohn Forte 
979fcf3ce44SJohn Forte /*
980fcf3ce44SJohn Forte  * ql_ip_iocb
981fcf3ce44SJohn Forte  *	Setup of IP IOCB.
982fcf3ce44SJohn Forte  *
983fcf3ce44SJohn Forte  * Input:
984fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
985fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
986fcf3ce44SJohn Forte  *	arg:	request queue packet.
987fcf3ce44SJohn Forte  *
988fcf3ce44SJohn Forte  * Context:
989fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
990fcf3ce44SJohn Forte  */
991fcf3ce44SJohn Forte void
992fcf3ce44SJohn Forte ql_ip_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
993fcf3ce44SJohn Forte {
994fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
995fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
996fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
997fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
998fcf3ce44SJohn Forte 	ip_entry_t		*pkt = arg;
999fcf3ce44SJohn Forte 
1000fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1001fcf3ce44SJohn Forte 
1002fcf3ce44SJohn Forte 	/* Set loop ID */
1003fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1004fcf3ce44SJohn Forte 		pkt->loop_id_l = LSB(tq->loop_id);
1005fcf3ce44SJohn Forte 		pkt->loop_id_h = MSB(tq->loop_id);
1006fcf3ce44SJohn Forte 	} else {
1007fcf3ce44SJohn Forte 		pkt->loop_id_h = LSB(tq->loop_id);
1008fcf3ce44SJohn Forte 	}
1009fcf3ce44SJohn Forte 
1010fcf3ce44SJohn Forte 	/* Set control flags */
1011fcf3ce44SJohn Forte 	pkt->control_flags_l = BIT_6;
1012fcf3ce44SJohn Forte 	if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) {
1013fcf3ce44SJohn Forte 		pkt->control_flags_h = BIT_7;
1014fcf3ce44SJohn Forte 	}
1015fcf3ce44SJohn Forte 
1016fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1017fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout);
1018fcf3ce44SJohn Forte 
1019fcf3ce44SJohn Forte 	/* Set data segment count. */
1020fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1021fcf3ce44SJohn Forte 	/* Load total byte count. */
1022fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count,
1023fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1024fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
1025fcf3ce44SJohn Forte 
1026fcf3ce44SJohn Forte 	/*
1027fcf3ce44SJohn Forte 	 * Build command packet.
1028fcf3ce44SJohn Forte 	 */
1029fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1030fcf3ce44SJohn Forte 		pkt->entry_type = IP_A64_TYPE;
1031fcf3ce44SJohn Forte 		cnt = IP_A64_DATA_SEGMENTS;
1032fcf3ce44SJohn Forte 	} else {
1033fcf3ce44SJohn Forte 		pkt->entry_type = IP_TYPE;
1034fcf3ce44SJohn Forte 		cnt = IP_DATA_SEGMENTS;
1035fcf3ce44SJohn Forte 	}
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 	/* Load command entry data segments. */
1038fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
1039fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
1040fcf3ce44SJohn Forte 	while (cnt && seg_cnt) {
1041fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
1042fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1043fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle, ptr32++,
1044fcf3ce44SJohn Forte 			    cp->dmac_notused);
1045fcf3ce44SJohn Forte 		}
1046fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++,
1047fcf3ce44SJohn Forte 		    (uint32_t)cp->dmac_size);
1048fcf3ce44SJohn Forte 		seg_cnt--;
1049fcf3ce44SJohn Forte 		cnt--;
1050fcf3ce44SJohn Forte 		cp++;
1051fcf3ce44SJohn Forte 	}
1052fcf3ce44SJohn Forte 
1053fcf3ce44SJohn Forte 	/*
1054fcf3ce44SJohn Forte 	 * Build continuation packets.
1055fcf3ce44SJohn Forte 	 */
1056fcf3ce44SJohn Forte 	if (seg_cnt) {
1057fcf3ce44SJohn Forte 		ql_continuation_iocb(ha, cp, seg_cnt,
1058fcf3ce44SJohn Forte 		    (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
1059fcf3ce44SJohn Forte 	}
1060fcf3ce44SJohn Forte 
1061fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1062fcf3ce44SJohn Forte }
1063fcf3ce44SJohn Forte 
1064fcf3ce44SJohn Forte /*
1065fcf3ce44SJohn Forte  * ql_ip_24xx_iocb
1066fcf3ce44SJohn Forte  *	Setup of IP IOCB for ISP24xx.
1067fcf3ce44SJohn Forte  *
1068fcf3ce44SJohn Forte  * Input:
1069fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1070fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
1071fcf3ce44SJohn Forte  *	arg:	request queue packet.
1072fcf3ce44SJohn Forte  *
1073fcf3ce44SJohn Forte  * Context:
1074fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1075fcf3ce44SJohn Forte  */
1076fcf3ce44SJohn Forte void
1077fcf3ce44SJohn Forte ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
1078fcf3ce44SJohn Forte {
1079fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
1080fcf3ce44SJohn Forte 	uint32_t		*ptr32;
1081fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
1082fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
1083fcf3ce44SJohn Forte 	ip_cmd_entry_t		*pkt = arg;
1084fcf3ce44SJohn Forte 
1085fcf3ce44SJohn Forte 	pkt->entry_type = IP_CMD_TYPE;
1086fcf3ce44SJohn Forte 
1087fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1088fcf3ce44SJohn Forte 
1089fcf3ce44SJohn Forte 	/* Set N_port handle */
1090fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->hdl_status, tq->loop_id);
1091fcf3ce44SJohn Forte 
1092fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1093fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
1094fcf3ce44SJohn Forte 		ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout_hdl,
1095fcf3ce44SJohn Forte 		    sp->isp_timeout);
1096fcf3ce44SJohn Forte 	}
1097fcf3ce44SJohn Forte 
1098fcf3ce44SJohn Forte 	/* Set data segment count. */
1099fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1100fcf3ce44SJohn Forte 	/* Load total byte count. */
1101fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count,
1102fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1103fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
1104fcf3ce44SJohn Forte 
1105fcf3ce44SJohn Forte 	/* Set control flags */
1106fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->control_flags,
1107fcf3ce44SJohn Forte 	    (uint16_t)(BIT_0));
1108fcf3ce44SJohn Forte 
1109fcf3ce44SJohn Forte 	/* Set frame header control flags */
1110fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->frame_hdr_cntrl_flgs,
1111fcf3ce44SJohn Forte 	    (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ));
1112fcf3ce44SJohn Forte 
1113fcf3ce44SJohn Forte 	/* Load command data segment. */
1114fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
1115fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
1116fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
1117fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
1118fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1119fcf3ce44SJohn Forte 	seg_cnt--;
1120fcf3ce44SJohn Forte 	cp++;
1121fcf3ce44SJohn Forte 
1122fcf3ce44SJohn Forte 	/*
1123fcf3ce44SJohn Forte 	 * Build continuation packets.
1124fcf3ce44SJohn Forte 	 */
1125fcf3ce44SJohn Forte 	if (seg_cnt) {
1126fcf3ce44SJohn Forte 		ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE);
1127fcf3ce44SJohn Forte 	}
1128fcf3ce44SJohn Forte 
1129fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1130fcf3ce44SJohn Forte }
1131fcf3ce44SJohn Forte 
1132fcf3ce44SJohn Forte /*
1133fcf3ce44SJohn Forte  * ql_isp_rcvbuf
1134fcf3ce44SJohn Forte  *	Locates free buffers and places it on the receive buffer queue.
1135fcf3ce44SJohn Forte  *
1136fcf3ce44SJohn Forte  * Input:
1137fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1138fcf3ce44SJohn Forte  *
1139fcf3ce44SJohn Forte  * Context:
1140fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1141fcf3ce44SJohn Forte  */
1142fcf3ce44SJohn Forte void
1143fcf3ce44SJohn Forte ql_isp_rcvbuf(ql_adapter_state_t *ha)
1144fcf3ce44SJohn Forte {
1145fcf3ce44SJohn Forte 	rcvbuf_t	*container;
114616dd44c2SDaniel Beauregard 	uint16_t	rcv_q_cnt;
1147fcf3ce44SJohn Forte 	uint16_t	index = 0;
1148fcf3ce44SJohn Forte 	uint16_t	index1 = 1;
1149fcf3ce44SJohn Forte 	int		debounce_count = QL_MAX_DEBOUNCE;
1150fcf3ce44SJohn Forte 	ql_srb_t	*sp;
1151fcf3ce44SJohn Forte 	fc_unsol_buf_t	*ubp;
1152fcf3ce44SJohn Forte 	int		ring_updated = FALSE;
1153fcf3ce44SJohn Forte 
1154*eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
1155fcf3ce44SJohn Forte 		ql_isp24xx_rcvbuf(ha);
1156fcf3ce44SJohn Forte 		return;
1157fcf3ce44SJohn Forte 	}
1158fcf3ce44SJohn Forte 
1159fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1160fcf3ce44SJohn Forte 
1161fcf3ce44SJohn Forte 	/* Acquire adapter state lock. */
1162fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1163fcf3ce44SJohn Forte 
1164fcf3ce44SJohn Forte 	/* Calculate number of free receive buffer entries. */
1165*eb82ff87SDaniel Beauregard 	index = RD16_IO_REG(ha, mailbox_out[8]);
1166fcf3ce44SJohn Forte 	do {
1167*eb82ff87SDaniel Beauregard 		index1 = RD16_IO_REG(ha, mailbox_out[8]);
1168fcf3ce44SJohn Forte 		if (index1 == index) {
1169fcf3ce44SJohn Forte 			break;
1170fcf3ce44SJohn Forte 		} else {
1171fcf3ce44SJohn Forte 			index = index1;
1172fcf3ce44SJohn Forte 		}
1173fcf3ce44SJohn Forte 	} while (debounce_count --);
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte 	if (debounce_count < 0) {
1176fcf3ce44SJohn Forte 		/* This should never happen */
1177fcf3ce44SJohn Forte 		EL(ha, "max mb8 debounce retries exceeded\n");
1178fcf3ce44SJohn Forte 	}
1179fcf3ce44SJohn Forte 
1180fcf3ce44SJohn Forte 	rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ?
1181fcf3ce44SJohn Forte 	    index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT -
1182fcf3ce44SJohn Forte 	    (ha->rcvbuf_ring_index - index));
1183fcf3ce44SJohn Forte 
1184fcf3ce44SJohn Forte 	if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) {
1185fcf3ce44SJohn Forte 		rcv_q_cnt--;
1186fcf3ce44SJohn Forte 	}
1187fcf3ce44SJohn Forte 
1188fcf3ce44SJohn Forte 	/* Load all free buffers in ISP receive buffer ring. */
1189fcf3ce44SJohn Forte 	index = 0;
119016dd44c2SDaniel Beauregard 	while (rcv_q_cnt > (uint16_t)0 && index < QL_UB_LIMIT) {
1191fcf3ce44SJohn Forte 		/* Locate a buffer to give. */
1192fcf3ce44SJohn Forte 		QL_UB_LOCK(ha);
1193fcf3ce44SJohn Forte 		while (index < QL_UB_LIMIT) {
1194fcf3ce44SJohn Forte 			ubp = ha->ub_array[index];
1195fcf3ce44SJohn Forte 			if (ubp != NULL) {
1196fcf3ce44SJohn Forte 				sp = ubp->ub_fca_private;
1197fcf3ce44SJohn Forte 				if ((sp->ub_type == FC_TYPE_IS8802_SNAP) &&
1198fcf3ce44SJohn Forte 				    (ha->flags & IP_INITIALIZED) &&
1199fcf3ce44SJohn Forte 				    (sp->flags & SRB_UB_IN_FCA) &&
1200fcf3ce44SJohn Forte 				    (!(sp->flags & (SRB_UB_IN_ISP |
1201fcf3ce44SJohn Forte 				    SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1202fcf3ce44SJohn Forte 				    SRB_UB_ACQUIRED)))) {
1203fcf3ce44SJohn Forte 					sp->flags |= SRB_UB_IN_ISP;
1204fcf3ce44SJohn Forte 					break;
1205fcf3ce44SJohn Forte 				}
1206fcf3ce44SJohn Forte 			}
1207fcf3ce44SJohn Forte 			index++;
1208fcf3ce44SJohn Forte 		}
1209fcf3ce44SJohn Forte 
1210fcf3ce44SJohn Forte 		if (index < QL_UB_LIMIT) {
1211fcf3ce44SJohn Forte 			rcv_q_cnt--;
1212fcf3ce44SJohn Forte 			index++;
1213fcf3ce44SJohn Forte 			container = ha->rcvbuf_ring_ptr;
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 			/*
1216fcf3ce44SJohn Forte 			 * Build container.
1217fcf3ce44SJohn Forte 			 */
1218fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle,
1219fcf3ce44SJohn Forte 			    (uint32_t *)(void *)&container->bufp[0],
1220fcf3ce44SJohn Forte 			    sp->ub_buffer.cookie.dmac_address);
1221fcf3ce44SJohn Forte 
1222fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle,
1223fcf3ce44SJohn Forte 			    (uint32_t *)(void *)&container->bufp[1],
1224fcf3ce44SJohn Forte 			    sp->ub_buffer.cookie.dmac_notused);
1225fcf3ce44SJohn Forte 
1226fcf3ce44SJohn Forte 			ddi_put16(ha->hba_buf.acc_handle, &container->handle,
1227fcf3ce44SJohn Forte 			    LSW(sp->handle));
1228fcf3ce44SJohn Forte 
1229fcf3ce44SJohn Forte 			ha->ub_outcnt++;
1230fcf3ce44SJohn Forte 
1231fcf3ce44SJohn Forte 			/* Adjust ring index. */
1232fcf3ce44SJohn Forte 			ha->rcvbuf_ring_index++;
1233fcf3ce44SJohn Forte 			if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) {
1234fcf3ce44SJohn Forte 				ha->rcvbuf_ring_index = 0;
1235fcf3ce44SJohn Forte 				ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
1236fcf3ce44SJohn Forte 			} else {
1237fcf3ce44SJohn Forte 				ha->rcvbuf_ring_ptr++;
1238fcf3ce44SJohn Forte 			}
1239fcf3ce44SJohn Forte 
1240fcf3ce44SJohn Forte 			ring_updated = TRUE;
1241fcf3ce44SJohn Forte 		}
1242fcf3ce44SJohn Forte 		QL_UB_UNLOCK(ha);
1243fcf3ce44SJohn Forte 	}
1244fcf3ce44SJohn Forte 
1245fcf3ce44SJohn Forte 	if (ring_updated) {
1246fcf3ce44SJohn Forte 		/* Sync queue. */
1247fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
1248fcf3ce44SJohn Forte 		    (off_t)RCVBUF_Q_BUFFER_OFFSET, (size_t)RCVBUF_QUEUE_SIZE,
1249fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
1250fcf3ce44SJohn Forte 
1251fcf3ce44SJohn Forte 		/* Set chip new ring index. */
1252*eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[8], ha->rcvbuf_ring_index);
1253fcf3ce44SJohn Forte 	}
1254fcf3ce44SJohn Forte 
1255fcf3ce44SJohn Forte 	/* Release adapter state lock. */
1256fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1257fcf3ce44SJohn Forte 
1258fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1259fcf3ce44SJohn Forte }
1260fcf3ce44SJohn Forte 
1261fcf3ce44SJohn Forte /*
1262fcf3ce44SJohn Forte  * ql_isp24xx_rcvbuf
1263fcf3ce44SJohn Forte  *	Locates free buffers and send it to adapter.
1264fcf3ce44SJohn Forte  *
1265fcf3ce44SJohn Forte  * Input:
1266fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1267fcf3ce44SJohn Forte  *
1268fcf3ce44SJohn Forte  * Context:
1269fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1270fcf3ce44SJohn Forte  */
1271fcf3ce44SJohn Forte static void
1272fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ql_adapter_state_t *ha)
1273fcf3ce44SJohn Forte {
1274fcf3ce44SJohn Forte 	rcvbuf_t		*container;
1275fcf3ce44SJohn Forte 	uint16_t		index;
1276fcf3ce44SJohn Forte 	ql_srb_t		*sp;
1277fcf3ce44SJohn Forte 	fc_unsol_buf_t		*ubp;
1278fcf3ce44SJohn Forte 	int			rval;
1279fcf3ce44SJohn Forte 	ip_buf_pool_entry_t	*pkt = NULL;
1280fcf3ce44SJohn Forte 
1281fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1282fcf3ce44SJohn Forte 
1283fcf3ce44SJohn Forte 	for (;;) {
1284fcf3ce44SJohn Forte 		/* Locate a buffer to give. */
1285fcf3ce44SJohn Forte 		QL_UB_LOCK(ha);
1286fcf3ce44SJohn Forte 		for (index = 0; index < QL_UB_LIMIT; index++) {
1287fcf3ce44SJohn Forte 			ubp = ha->ub_array[index];
1288fcf3ce44SJohn Forte 			if (ubp != NULL) {
1289fcf3ce44SJohn Forte 				sp = ubp->ub_fca_private;
1290fcf3ce44SJohn Forte 				if ((sp->ub_type == FC_TYPE_IS8802_SNAP) &&
1291fcf3ce44SJohn Forte 				    (ha->flags & IP_INITIALIZED) &&
1292fcf3ce44SJohn Forte 				    (sp->flags & SRB_UB_IN_FCA) &&
1293fcf3ce44SJohn Forte 				    (!(sp->flags & (SRB_UB_IN_ISP |
1294fcf3ce44SJohn Forte 				    SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1295fcf3ce44SJohn Forte 				    SRB_UB_ACQUIRED)))) {
1296fcf3ce44SJohn Forte 					ha->ub_outcnt++;
1297fcf3ce44SJohn Forte 					sp->flags |= SRB_UB_IN_ISP;
1298fcf3ce44SJohn Forte 					break;
1299fcf3ce44SJohn Forte 				}
1300fcf3ce44SJohn Forte 			}
1301fcf3ce44SJohn Forte 		}
1302fcf3ce44SJohn Forte 		QL_UB_UNLOCK(ha);
1303fcf3ce44SJohn Forte 		if (index == QL_UB_LIMIT) {
1304fcf3ce44SJohn Forte 			break;
1305fcf3ce44SJohn Forte 		}
1306fcf3ce44SJohn Forte 
1307fcf3ce44SJohn Forte 		/* Get IOCB packet for buffers. */
1308fcf3ce44SJohn Forte 		if (pkt == NULL) {
1309fcf3ce44SJohn Forte 			rval = ql_req_pkt(ha, (request_t **)&pkt);
1310fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
1311fcf3ce44SJohn Forte 				EL(ha, "failed, ql_req_pkt=%x\n", rval);
1312fcf3ce44SJohn Forte 				QL_UB_LOCK(ha);
1313fcf3ce44SJohn Forte 				ha->ub_outcnt--;
1314fcf3ce44SJohn Forte 				sp->flags &= ~SRB_UB_IN_ISP;
1315fcf3ce44SJohn Forte 				QL_UB_UNLOCK(ha);
1316fcf3ce44SJohn Forte 				break;
1317fcf3ce44SJohn Forte 			}
1318fcf3ce44SJohn Forte 			pkt->entry_type = IP_BUF_POOL_TYPE;
1319fcf3ce44SJohn Forte 			container = &pkt->buffers[0];
1320fcf3ce44SJohn Forte 		}
1321fcf3ce44SJohn Forte 
1322fcf3ce44SJohn Forte 		/*
1323fcf3ce44SJohn Forte 		 * Build container.
1324fcf3ce44SJohn Forte 		 */
1325fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, &container->bufp[0],
1326fcf3ce44SJohn Forte 		    sp->ub_buffer.cookie.dmac_address);
1327fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, &container->bufp[1],
1328fcf3ce44SJohn Forte 		    sp->ub_buffer.cookie.dmac_notused);
1329fcf3ce44SJohn Forte 		ddi_put16(ha->hba_buf.acc_handle, &container->handle,
1330fcf3ce44SJohn Forte 		    LSW(sp->handle));
1331fcf3ce44SJohn Forte 
1332fcf3ce44SJohn Forte 		pkt->buffer_count++;
1333fcf3ce44SJohn Forte 		container++;
1334fcf3ce44SJohn Forte 
1335fcf3ce44SJohn Forte 		if (pkt->buffer_count == IP_POOL_BUFFERS) {
1336fcf3ce44SJohn Forte 			ql_isp_cmd(ha);
1337fcf3ce44SJohn Forte 			pkt = NULL;
1338fcf3ce44SJohn Forte 		}
1339fcf3ce44SJohn Forte 	}
1340fcf3ce44SJohn Forte 
1341fcf3ce44SJohn Forte 	if (pkt != NULL) {
1342fcf3ce44SJohn Forte 		ql_isp_cmd(ha);
1343fcf3ce44SJohn Forte 	}
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1346fcf3ce44SJohn Forte }
1347