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 
22eb82ff87SDaniel Beauregard /* Copyright 2010 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25*f885d00fSDaniel Beauregard  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28eb82ff87SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_iocb.c"
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /*
31fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32fcf3ce44SJohn Forte  *
33fcf3ce44SJohn Forte  * ***********************************************************************
34fcf3ce44SJohn Forte  * *									**
35fcf3ce44SJohn Forte  * *				NOTICE					**
36eb82ff87SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
37fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
38fcf3ce44SJohn Forte  * *									**
39fcf3ce44SJohn Forte  * ***********************************************************************
40fcf3ce44SJohn Forte  *
41fcf3ce44SJohn Forte  */
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte #include <ql_apps.h>
44fcf3ce44SJohn Forte #include <ql_api.h>
45fcf3ce44SJohn Forte #include <ql_debug.h>
46fcf3ce44SJohn Forte #include <ql_iocb.h>
47fcf3ce44SJohn Forte #include <ql_isr.h>
48fcf3ce44SJohn Forte #include <ql_xioctl.h>
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte /*
51fcf3ce44SJohn Forte  * Local Function Prototypes.
52fcf3ce44SJohn Forte  */
535dfd244aSDaniel Beauregard static int ql_req_pkt(ql_adapter_state_t *, request_t **);
54fcf3ce44SJohn Forte static void ql_continuation_iocb(ql_adapter_state_t *, ddi_dma_cookie_t *,
55fcf3ce44SJohn Forte     uint16_t, boolean_t);
56fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *);
57*f885d00fSDaniel Beauregard static void ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *, ql_srb_t *, void *);
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
ql_start_iocb(ql_adapter_state_t * vha,ql_srb_t * sp)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;
170*f885d00fSDaniel Beauregard 		sp->request_ring_ptr = pkt;
171fcf3ce44SJohn Forte 		sp->flags |= SRB_IN_TOKEN_ARRAY;
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 		/* Zero out packet. */
174fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
175fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
176fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
177fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
178fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 		/* Setup IOCB common data. */
181fcf3ce44SJohn Forte 		pkt->entry_count = (uint8_t)sp->req_cnt;
182fcf3ce44SJohn Forte 		pkt->sys_define = (uint8_t)ha->req_ring_index;
18316dd44c2SDaniel Beauregard 		/* mark the iocb with the response identifier */
184fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, &pkt->handle,
185fcf3ce44SJohn Forte 		    (uint32_t)sp->handle);
186fcf3ce44SJohn Forte 
18716dd44c2SDaniel Beauregard 		/* Setup IOCB unique data. */
188fcf3ce44SJohn Forte 		(sp->iocb)(vha, sp, pkt);
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_STARTED;
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d,%d): req packet, sp=%p\n",
193fcf3ce44SJohn Forte 		    ha->instance, vha->vp_index, (void *)sp);
194fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
195fcf3ce44SJohn Forte 
196fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
197fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
198fcf3ce44SJohn Forte 		    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
199fcf3ce44SJohn Forte 		    REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE,
200fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 		/* Adjust ring index. */
203fcf3ce44SJohn Forte 		ha->req_ring_index++;
204fcf3ce44SJohn Forte 		if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
205fcf3ce44SJohn Forte 			ha->req_ring_index = 0;
206fcf3ce44SJohn Forte 			ha->request_ring_ptr = ha->request_ring_bp;
207fcf3ce44SJohn Forte 		} else {
208fcf3ce44SJohn Forte 			ha->request_ring_ptr++;
209fcf3ce44SJohn Forte 		}
210fcf3ce44SJohn Forte 
211fcf3ce44SJohn Forte 		/* Reset watchdog timer */
212fcf3ce44SJohn Forte 		sp->wdg_q_time = sp->init_wdg_q_time;
213fcf3ce44SJohn Forte 
21416dd44c2SDaniel Beauregard 		/*
21516dd44c2SDaniel Beauregard 		 * Send it by setting the new ring index in the ISP Request
21616dd44c2SDaniel Beauregard 		 * Ring In Pointer register.  This is the mechanism
21716dd44c2SDaniel Beauregard 		 * used to notify the isp that a new iocb has been
21816dd44c2SDaniel Beauregard 		 * placed on the request ring.
21916dd44c2SDaniel Beauregard 		 */
220eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_8021)) {
221eb82ff87SDaniel Beauregard 			uint32_t	w32;
222eb82ff87SDaniel Beauregard 
223eb82ff87SDaniel Beauregard 			w32 = ha->req_ring_index << 16 |
224eb82ff87SDaniel Beauregard 			    ha->function_number << 5 | 4;
225eb82ff87SDaniel Beauregard 			do {
226eb82ff87SDaniel Beauregard 				ddi_put32(ha->db_dev_handle, ha->nx_req_in,
227eb82ff87SDaniel Beauregard 				    w32);
228eb82ff87SDaniel Beauregard 			} while (RD_REG_DWORD(ha, ha->db_read) != w32);
229eb82ff87SDaniel Beauregard 
230eb82ff87SDaniel Beauregard 		} else {
231eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, req_in, ha->req_ring_index);
232eb82ff87SDaniel Beauregard 		}
233fcf3ce44SJohn Forte 
234fcf3ce44SJohn Forte 		/* Update outstanding command count statistic. */
235fcf3ce44SJohn Forte 		ha->adapter_stats->ncmds++;
236fcf3ce44SJohn Forte 
23716dd44c2SDaniel Beauregard 		/* if there is a pending command, try to start it. */
238fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) == NULL) {
239fcf3ce44SJohn Forte 			break;
240fcf3ce44SJohn Forte 		}
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 		/* Remove command from pending command queue */
243fcf3ce44SJohn Forte 		sp = link->base_address;
244fcf3ce44SJohn Forte 		ql_remove_link(&ha->pending_cmds, &sp->cmd);
245fcf3ce44SJohn Forte 	}
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 	/* Release ring specific lock */
248fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
249fcf3ce44SJohn Forte 
250fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
251fcf3ce44SJohn Forte }
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte /*
254fcf3ce44SJohn Forte  * ql_req_pkt
255fcf3ce44SJohn Forte  *	Function is responsible for locking ring and
256fcf3ce44SJohn Forte  *	getting a zeroed out request packet.
257fcf3ce44SJohn Forte  *
258fcf3ce44SJohn Forte  * Input:
259fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
260fcf3ce44SJohn Forte  *	pkt:	address for packet pointer.
261fcf3ce44SJohn Forte  *
262fcf3ce44SJohn Forte  * Returns:
263fcf3ce44SJohn Forte  *	ql local function return status code.
264fcf3ce44SJohn Forte  *
265fcf3ce44SJohn Forte  * Context:
266fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
267fcf3ce44SJohn Forte  */
2685dfd244aSDaniel Beauregard static int
ql_req_pkt(ql_adapter_state_t * vha,request_t ** pktp)269fcf3ce44SJohn Forte ql_req_pkt(ql_adapter_state_t *vha, request_t **pktp)
270fcf3ce44SJohn Forte {
271fcf3ce44SJohn Forte 	uint16_t		cnt;
272fcf3ce44SJohn Forte 	uint32_t		*long_ptr;
273fcf3ce44SJohn Forte 	uint32_t		timer;
274fcf3ce44SJohn Forte 	int			rval = QL_FUNCTION_TIMEOUT;
275fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 	/* Wait for 30 seconds for slot. */
280fcf3ce44SJohn Forte 	for (timer = 30000; timer != 0; timer--) {
281fcf3ce44SJohn Forte 		/* Acquire ring lock. */
282fcf3ce44SJohn Forte 		REQUEST_RING_LOCK(ha);
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte 		if (ha->req_q_cnt == 0) {
285fcf3ce44SJohn Forte 			/* Calculate number of free request entries. */
286fcf3ce44SJohn Forte 			cnt = RD16_IO_REG(ha, req_out);
287fcf3ce44SJohn Forte 			if (ha->req_ring_index < cnt) {
288fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)
289fcf3ce44SJohn Forte 				    (cnt - ha->req_ring_index);
290fcf3ce44SJohn Forte 			} else {
291fcf3ce44SJohn Forte 				ha->req_q_cnt = (uint16_t)
292fcf3ce44SJohn Forte 				    (REQUEST_ENTRY_CNT -
293fcf3ce44SJohn Forte 				    (ha->req_ring_index - cnt));
294fcf3ce44SJohn Forte 			}
295fcf3ce44SJohn Forte 			if (ha->req_q_cnt != 0) {
296fcf3ce44SJohn Forte 				ha->req_q_cnt--;
297fcf3ce44SJohn Forte 			}
298fcf3ce44SJohn Forte 		}
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte 		/* Found empty request ring slot? */
301fcf3ce44SJohn Forte 		if (ha->req_q_cnt != 0) {
302fcf3ce44SJohn Forte 			ha->req_q_cnt--;
303fcf3ce44SJohn Forte 			*pktp = ha->request_ring_ptr;
304fcf3ce44SJohn Forte 
305fcf3ce44SJohn Forte 			/* Zero out packet. */
306fcf3ce44SJohn Forte 			long_ptr = (uint32_t *)ha->request_ring_ptr;
307fcf3ce44SJohn Forte 			for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) {
308fcf3ce44SJohn Forte 				*long_ptr++ = 0;
309fcf3ce44SJohn Forte 			}
310fcf3ce44SJohn Forte 
311fcf3ce44SJohn Forte 			/* Setup IOCB common data. */
312fcf3ce44SJohn Forte 			ha->request_ring_ptr->entry_count = 1;
313fcf3ce44SJohn Forte 			ha->request_ring_ptr->sys_define =
314fcf3ce44SJohn Forte 			    (uint8_t)ha->req_ring_index;
315fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle,
316fcf3ce44SJohn Forte 			    &ha->request_ring_ptr->handle,
317fcf3ce44SJohn Forte 			    (uint32_t)QL_FCA_BRAND);
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 			rval = QL_SUCCESS;
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 			break;
322fcf3ce44SJohn Forte 		}
323fcf3ce44SJohn Forte 
324fcf3ce44SJohn Forte 		/* Release request queue lock. */
325fcf3ce44SJohn Forte 		REQUEST_RING_UNLOCK(ha);
326fcf3ce44SJohn Forte 
327fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
328fcf3ce44SJohn Forte 
329fcf3ce44SJohn Forte 		/* Check for pending interrupts. */
330fcf3ce44SJohn Forte 		/*
331fcf3ce44SJohn Forte 		 * XXX protect interrupt routine from calling itself.
332fcf3ce44SJohn Forte 		 * Need to revisit this routine. So far we never
333fcf3ce44SJohn Forte 		 * hit this case as req slot was available
334fcf3ce44SJohn Forte 		 */
335fcf3ce44SJohn Forte 		if ((!(curthread->t_flag & T_INTR_THREAD)) &&
336eb82ff87SDaniel Beauregard 		    INTERRUPT_PENDING(ha)) {
337fcf3ce44SJohn Forte 			(void) ql_isr((caddr_t)ha);
338fcf3ce44SJohn Forte 			INTR_LOCK(ha);
339fcf3ce44SJohn Forte 			ha->intr_claimed = TRUE;
340fcf3ce44SJohn Forte 			INTR_UNLOCK(ha);
341fcf3ce44SJohn Forte 		}
342fcf3ce44SJohn Forte 	}
343fcf3ce44SJohn Forte 
344fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
345fcf3ce44SJohn Forte 		ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
346fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval);
347fcf3ce44SJohn Forte 	} else {
348fcf3ce44SJohn Forte 		/*EMPTY*/
349fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
350fcf3ce44SJohn Forte 	}
351fcf3ce44SJohn Forte 	return (rval);
352fcf3ce44SJohn Forte }
353fcf3ce44SJohn Forte 
354fcf3ce44SJohn Forte /*
355fcf3ce44SJohn Forte  * ql_isp_cmd
356fcf3ce44SJohn Forte  *	Function is responsible for modifying ISP input pointer.
35716dd44c2SDaniel Beauregard  *	This action notifies the isp that a new request has been
35816dd44c2SDaniel Beauregard  *	added to the request ring.
35916dd44c2SDaniel Beauregard  *
360fcf3ce44SJohn Forte  *	Releases ring lock.
361fcf3ce44SJohn Forte  *
362fcf3ce44SJohn Forte  * Input:
363fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
364fcf3ce44SJohn Forte  *
365fcf3ce44SJohn Forte  * Context:
366fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
367fcf3ce44SJohn Forte  */
368fcf3ce44SJohn Forte void
ql_isp_cmd(ql_adapter_state_t * vha)369fcf3ce44SJohn Forte ql_isp_cmd(ql_adapter_state_t *vha)
370fcf3ce44SJohn Forte {
371fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte 	QL_PRINT_5(CE_CONT, "(%d): req packet:\n", ha->instance);
376fcf3ce44SJohn Forte 	QL_DUMP_5((uint8_t *)ha->request_ring_ptr, 8, REQUEST_ENTRY_SIZE);
377fcf3ce44SJohn Forte 
378fcf3ce44SJohn Forte 	/* Sync DMA buffer. */
379fcf3ce44SJohn Forte 	(void) ddi_dma_sync(ha->hba_buf.dma_handle,
380fcf3ce44SJohn Forte 	    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
381fcf3ce44SJohn Forte 	    REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE,
382fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
383fcf3ce44SJohn Forte 
384fcf3ce44SJohn Forte 	/* Adjust ring index. */
385fcf3ce44SJohn Forte 	ha->req_ring_index++;
386fcf3ce44SJohn Forte 	if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
387fcf3ce44SJohn Forte 		ha->req_ring_index = 0;
388fcf3ce44SJohn Forte 		ha->request_ring_ptr = ha->request_ring_bp;
389fcf3ce44SJohn Forte 	} else {
390fcf3ce44SJohn Forte 		ha->request_ring_ptr++;
391fcf3ce44SJohn Forte 	}
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte 	/* Set chip new ring index. */
394eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
395eb82ff87SDaniel Beauregard 		uint32_t	w32;
396eb82ff87SDaniel Beauregard 
397eb82ff87SDaniel Beauregard 		w32 = ha->req_ring_index << 16 |
398eb82ff87SDaniel Beauregard 		    ha->function_number << 5 | 4;
399eb82ff87SDaniel Beauregard 		do {
400eb82ff87SDaniel Beauregard 			ddi_put32(ha->db_dev_handle, ha->nx_req_in, w32);
401eb82ff87SDaniel Beauregard 		} while (RD_REG_DWORD(ha, ha->db_read) != w32);
402eb82ff87SDaniel Beauregard 
403eb82ff87SDaniel Beauregard 	} else {
404eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, req_in, ha->req_ring_index);
405eb82ff87SDaniel Beauregard 	}
406fcf3ce44SJohn Forte 
407fcf3ce44SJohn Forte 	/* Release ring lock. */
408fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
409fcf3ce44SJohn Forte 
410fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
411fcf3ce44SJohn Forte }
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte /*
414fcf3ce44SJohn Forte  * ql_command_iocb
415fcf3ce44SJohn Forte  *	Setup of command IOCB.
416fcf3ce44SJohn Forte  *
417fcf3ce44SJohn Forte  * Input:
418fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
419fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
420fcf3ce44SJohn Forte  *
421fcf3ce44SJohn Forte  *	arg:	request queue packet.
422fcf3ce44SJohn Forte  *
423fcf3ce44SJohn Forte  * Context:
424fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
425fcf3ce44SJohn Forte  */
426fcf3ce44SJohn Forte void
ql_command_iocb(ql_adapter_state_t * ha,ql_srb_t * sp,void * arg)427fcf3ce44SJohn Forte ql_command_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
428fcf3ce44SJohn Forte {
429fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
430fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
431fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
432fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
433fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
434fcf3ce44SJohn Forte 	cmd_entry_t		*pkt = arg;
435fcf3ce44SJohn Forte 
436fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
437fcf3ce44SJohn Forte 
438fcf3ce44SJohn Forte 	/* Set LUN number */
439fcf3ce44SJohn Forte 	pkt->lun_l = LSB(sp->lun_queue->lun_no);
440fcf3ce44SJohn Forte 	pkt->lun_h = MSB(sp->lun_queue->lun_no);
441fcf3ce44SJohn Forte 
442fcf3ce44SJohn Forte 	/* Set target ID */
443fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
444fcf3ce44SJohn Forte 		pkt->target_l = LSB(tq->loop_id);
445fcf3ce44SJohn Forte 		pkt->target_h = MSB(tq->loop_id);
446fcf3ce44SJohn Forte 	} else {
447fcf3ce44SJohn Forte 		pkt->target_h = LSB(tq->loop_id);
448fcf3ce44SJohn Forte 	}
449fcf3ce44SJohn Forte 
450fcf3ce44SJohn Forte 	/* Set tag queue control flags */
451fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
452fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
453fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_HTAG);
454fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
455fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
456fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_OTAG);
457fcf3ce44SJohn Forte 	/* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */
458fcf3ce44SJohn Forte 	} else {
459fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
460fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_STAG);
461fcf3ce44SJohn Forte 	}
462fcf3ce44SJohn Forte 
463fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
464fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout);
465fcf3ce44SJohn Forte 
466fcf3ce44SJohn Forte 	/* Load SCSI CDB */
467fcf3ce44SJohn Forte 	ddi_rep_put8(ha->hba_buf.acc_handle, fcp->fcp_cdb,
468fcf3ce44SJohn Forte 	    pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR);
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
471fcf3ce44SJohn Forte 		pkt->entry_type = IOCB_CMD_TYPE_3;
472fcf3ce44SJohn Forte 		cnt = CMD_TYPE_3_DATA_SEGMENTS;
473fcf3ce44SJohn Forte 	} else {
474fcf3ce44SJohn Forte 		pkt->entry_type = IOCB_CMD_TYPE_2;
475fcf3ce44SJohn Forte 		cnt = CMD_TYPE_2_DATA_SEGMENTS;
476fcf3ce44SJohn Forte 	}
477fcf3ce44SJohn Forte 
478fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
479fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
480fcf3ce44SJohn Forte 		ha->xioctl->IOControlRequests++;
481fcf3ce44SJohn Forte 		return;
482fcf3ce44SJohn Forte 	}
483fcf3ce44SJohn Forte 
484fcf3ce44SJohn Forte 	/*
485fcf3ce44SJohn Forte 	 * Set transfer direction. Load Data segments.
486fcf3ce44SJohn Forte 	 */
487fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
488fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
489fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_OUT);
490fcf3ce44SJohn Forte 		ha->xioctl->IOOutputRequests++;
491fcf3ce44SJohn Forte 		ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
492fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
493fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
494fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_IN);
495fcf3ce44SJohn Forte 		ha->xioctl->IOInputRequests++;
496fcf3ce44SJohn Forte 		ha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
497fcf3ce44SJohn Forte 	}
498fcf3ce44SJohn Forte 
499fcf3ce44SJohn Forte 	/* Set data segment count. */
500fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
501fcf3ce44SJohn Forte 	ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
502fcf3ce44SJohn Forte 
503fcf3ce44SJohn Forte 	/* Load total byte count. */
504fcf3ce44SJohn Forte 	ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, fcp->fcp_data_len);
505fcf3ce44SJohn Forte 
506fcf3ce44SJohn Forte 	/* Load command data segment. */
507fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
508fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
509fcf3ce44SJohn Forte 	while (cnt && seg_cnt) {
510fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
511fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
512fcf3ce44SJohn Forte 			ddi_put32(ha->hba_buf.acc_handle, ptr32++,
513fcf3ce44SJohn Forte 			    cp->dmac_notused);
514fcf3ce44SJohn Forte 		}
515fcf3ce44SJohn Forte 		ddi_put32(ha->hba_buf.acc_handle, ptr32++,
516fcf3ce44SJohn Forte 		    (uint32_t)cp->dmac_size);
517fcf3ce44SJohn Forte 		seg_cnt--;
518fcf3ce44SJohn Forte 		cnt--;
519fcf3ce44SJohn Forte 		cp++;
520fcf3ce44SJohn Forte 	}
521fcf3ce44SJohn Forte 
522fcf3ce44SJohn Forte 	/*
523fcf3ce44SJohn Forte 	 * Build continuation packets.
524fcf3ce44SJohn Forte 	 */
525fcf3ce44SJohn Forte 	if (seg_cnt) {
526fcf3ce44SJohn Forte 		ql_continuation_iocb(ha, cp, seg_cnt,
527fcf3ce44SJohn Forte 		    (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
528fcf3ce44SJohn Forte 	}
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
531fcf3ce44SJohn Forte }
532fcf3ce44SJohn Forte 
533fcf3ce44SJohn Forte /*
534fcf3ce44SJohn Forte  * ql_continuation_iocb
535fcf3ce44SJohn Forte  *	Setup of continuation IOCB.
536fcf3ce44SJohn Forte  *
537fcf3ce44SJohn Forte  * Input:
538fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
539fcf3ce44SJohn Forte  *	cp:		cookie list pointer.
540fcf3ce44SJohn Forte  *	seg_cnt:	number of segments.
541fcf3ce44SJohn Forte  *	addr64:		64 bit addresses.
542fcf3ce44SJohn Forte  *
543fcf3ce44SJohn Forte  * Context:
544fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
545fcf3ce44SJohn Forte  */
546fcf3ce44SJohn Forte static void
ql_continuation_iocb(ql_adapter_state_t * ha,ddi_dma_cookie_t * cp,uint16_t seg_cnt,boolean_t addr64)547fcf3ce44SJohn Forte ql_continuation_iocb(ql_adapter_state_t *ha, ddi_dma_cookie_t *cp,
548fcf3ce44SJohn Forte     uint16_t seg_cnt, boolean_t addr64)
549fcf3ce44SJohn Forte {
550fcf3ce44SJohn Forte 	cont_entry_t	*pkt;
551fcf3ce44SJohn Forte 	uint64_t	*ptr64;
552fcf3ce44SJohn Forte 	uint32_t	*ptr32, cnt;
553fcf3ce44SJohn Forte 
554fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
555fcf3ce44SJohn Forte 
556fcf3ce44SJohn Forte 	/*
557fcf3ce44SJohn Forte 	 * Build continuation packets.
558fcf3ce44SJohn Forte 	 */
559fcf3ce44SJohn Forte 	while (seg_cnt) {
560fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
561fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
562fcf3ce44SJohn Forte 		    (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE +
564fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORDEV);
565fcf3ce44SJohn Forte 
566fcf3ce44SJohn Forte 		/* Adjust ring pointer, and deal with wrap. */
567fcf3ce44SJohn Forte 		ha->req_ring_index++;
568fcf3ce44SJohn Forte 		if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
569fcf3ce44SJohn Forte 			ha->req_ring_index = 0;
570fcf3ce44SJohn Forte 			ha->request_ring_ptr = ha->request_ring_bp;
571fcf3ce44SJohn Forte 		} else {
572fcf3ce44SJohn Forte 			ha->request_ring_ptr++;
573fcf3ce44SJohn Forte 		}
574fcf3ce44SJohn Forte 		pkt = (cont_entry_t *)ha->request_ring_ptr;
575fcf3ce44SJohn Forte 
576fcf3ce44SJohn Forte 		/* Zero out packet. */
577fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
578fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
579fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
580fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
581fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 		/*
584fcf3ce44SJohn Forte 		 * Build continuation packet.
585fcf3ce44SJohn Forte 		 */
586fcf3ce44SJohn Forte 		pkt->entry_count = 1;
587fcf3ce44SJohn Forte 		pkt->sys_define = (uint8_t)ha->req_ring_index;
588fcf3ce44SJohn Forte 		if (addr64) {
589fcf3ce44SJohn Forte 			pkt->entry_type = CONTINUATION_TYPE_1;
590fcf3ce44SJohn Forte 			cnt = CONT_TYPE_1_DATA_SEGMENTS;
591fcf3ce44SJohn Forte 			ptr32 = (uint32_t *)
592fcf3ce44SJohn Forte 			    &((cont_type_1_entry_t *)pkt)->dseg_0_address;
593fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
594fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
595fcf3ce44SJohn Forte 				    cp->dmac_address);
596fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
597fcf3ce44SJohn Forte 				    cp->dmac_notused);
598fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
599fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
600fcf3ce44SJohn Forte 				seg_cnt--;
601fcf3ce44SJohn Forte 				cnt--;
602fcf3ce44SJohn Forte 				cp++;
603fcf3ce44SJohn Forte 			}
604fcf3ce44SJohn Forte 		} else {
605fcf3ce44SJohn Forte 			pkt->entry_type = CONTINUATION_TYPE_0;
606fcf3ce44SJohn Forte 			cnt = CONT_TYPE_0_DATA_SEGMENTS;
607fcf3ce44SJohn Forte 			ptr32 = (uint32_t *)&pkt->dseg_0_address;
608fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
609fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
610fcf3ce44SJohn Forte 				    cp->dmac_address);
611fcf3ce44SJohn Forte 				ddi_put32(ha->hba_buf.acc_handle, ptr32++,
612fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
613fcf3ce44SJohn Forte 				seg_cnt--;
614fcf3ce44SJohn Forte 				cnt--;
615fcf3ce44SJohn Forte 				cp++;
616fcf3ce44SJohn Forte 			}
617fcf3ce44SJohn Forte 		}
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d): packet:\n", ha->instance);
620fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
621fcf3ce44SJohn Forte 	}
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
624fcf3ce44SJohn Forte }
625fcf3ce44SJohn Forte 
626fcf3ce44SJohn Forte /*
627fcf3ce44SJohn Forte  * ql_command_24xx_iocb
628fcf3ce44SJohn Forte  *	Setup of ISP24xx command IOCB.
629fcf3ce44SJohn Forte  *
630fcf3ce44SJohn Forte  * Input:
631fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
632fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
633fcf3ce44SJohn Forte  *	arg:	request queue packet.
634fcf3ce44SJohn Forte  *
635fcf3ce44SJohn Forte  * Context:
636fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
637fcf3ce44SJohn Forte  */
638fcf3ce44SJohn Forte void
ql_command_24xx_iocb(ql_adapter_state_t * ha,ql_srb_t * sp,void * arg)639fcf3ce44SJohn Forte ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
640fcf3ce44SJohn Forte {
641fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
642fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
643fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
644fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
645fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
646*f885d00fSDaniel Beauregard 	cmd7_24xx_entry_t	*pkt = arg;
647fcf3ce44SJohn Forte 	ql_adapter_state_t	*pha = ha->pha;
648fcf3ce44SJohn Forte 
649fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
650fcf3ce44SJohn Forte 
651*f885d00fSDaniel Beauregard 	if (fcp->fcp_data_len != 0 && sp->sg_dma.dma_handle != NULL &&
652*f885d00fSDaniel Beauregard 	    sp->pkt->pkt_data_cookie_cnt > 1) {
653*f885d00fSDaniel Beauregard 		ql_cmd_24xx_type_6_iocb(ha, sp, arg);
654*f885d00fSDaniel Beauregard 		QL_PRINT_3(CE_CONT, "(%d): cmd6 exit\n", ha->instance);
655*f885d00fSDaniel Beauregard 		return;
656*f885d00fSDaniel Beauregard 	}
657*f885d00fSDaniel Beauregard 
658fcf3ce44SJohn Forte 	pkt->entry_type = IOCB_CMD_TYPE_7;
659fcf3ce44SJohn Forte 
660fcf3ce44SJohn Forte 	/* Set LUN number */
661fcf3ce44SJohn Forte 	pkt->fcp_lun[2] = LSB(sp->lun_queue->lun_no);
662fcf3ce44SJohn Forte 	pkt->fcp_lun[3] = MSB(sp->lun_queue->lun_no);
663fcf3ce44SJohn Forte 
664fcf3ce44SJohn Forte 	/* Set N_port handle */
665fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id);
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte 	/* Set target ID */
668fcf3ce44SJohn Forte 	pkt->target_id[0] = tq->d_id.b.al_pa;
669fcf3ce44SJohn Forte 	pkt->target_id[1] = tq->d_id.b.area;
670fcf3ce44SJohn Forte 	pkt->target_id[2] = tq->d_id.b.domain;
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	pkt->vp_index = ha->vp_index;
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
675fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
676fcf3ce44SJohn Forte 		ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout,
677fcf3ce44SJohn Forte 		    sp->isp_timeout);
678fcf3ce44SJohn Forte 	}
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 	/* Load SCSI CDB */
681fcf3ce44SJohn Forte 	ddi_rep_put8(pha->hba_buf.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb,
682fcf3ce44SJohn Forte 	    MAX_CMDSZ, DDI_DEV_AUTOINCR);
683fcf3ce44SJohn Forte 	for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
684fcf3ce44SJohn Forte 		ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4);
685fcf3ce44SJohn Forte 	}
686fcf3ce44SJohn Forte 
687fcf3ce44SJohn Forte 	/*
688fcf3ce44SJohn Forte 	 * Set tag queue control flags
689fcf3ce44SJohn Forte 	 * Note:
690fcf3ce44SJohn Forte 	 *	Cannot copy fcp->fcp_cntl.cntl_qtype directly,
691fcf3ce44SJohn Forte 	 *	problem with x86 in 32bit kernel mode
692fcf3ce44SJohn Forte 	 */
693fcf3ce44SJohn Forte 	switch (fcp->fcp_cntl.cntl_qtype) {
694fcf3ce44SJohn Forte 	case FCP_QTYPE_SIMPLE:
695fcf3ce44SJohn Forte 		pkt->task = TA_STAG;
696fcf3ce44SJohn Forte 		break;
697fcf3ce44SJohn Forte 	case FCP_QTYPE_HEAD_OF_Q:
698fcf3ce44SJohn Forte 		pkt->task = TA_HTAG;
699fcf3ce44SJohn Forte 		break;
700fcf3ce44SJohn Forte 	case FCP_QTYPE_ORDERED:
701fcf3ce44SJohn Forte 		pkt->task = TA_OTAG;
702fcf3ce44SJohn Forte 		break;
703fcf3ce44SJohn Forte 	case FCP_QTYPE_ACA_Q_TAG:
704fcf3ce44SJohn Forte 		pkt->task = TA_ACA;
705fcf3ce44SJohn Forte 		break;
706fcf3ce44SJohn Forte 	case FCP_QTYPE_UNTAGGED:
707fcf3ce44SJohn Forte 		pkt->task = TA_UNTAGGED;
708fcf3ce44SJohn Forte 		break;
709fcf3ce44SJohn Forte 	default:
710fcf3ce44SJohn Forte 		break;
711fcf3ce44SJohn Forte 	}
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
714fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
715fcf3ce44SJohn Forte 		pha->xioctl->IOControlRequests++;
716fcf3ce44SJohn Forte 		return;
717fcf3ce44SJohn Forte 	}
718fcf3ce44SJohn Forte 
719fcf3ce44SJohn Forte 	/* Set transfer direction. */
720fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
721fcf3ce44SJohn Forte 		pkt->control_flags = CF_WR;
722fcf3ce44SJohn Forte 		pha->xioctl->IOOutputRequests++;
723fcf3ce44SJohn Forte 		pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
724fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
725fcf3ce44SJohn Forte 		pkt->control_flags = CF_RD;
726fcf3ce44SJohn Forte 		pha->xioctl->IOInputRequests++;
727fcf3ce44SJohn Forte 		pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
728fcf3ce44SJohn Forte 	}
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 	/* Set data segment count. */
731fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
732fcf3ce44SJohn Forte 	ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
733fcf3ce44SJohn Forte 
734fcf3ce44SJohn Forte 	/* Load total byte count. */
735fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count,
736fcf3ce44SJohn Forte 	    fcp->fcp_data_len);
737fcf3ce44SJohn Forte 
738fcf3ce44SJohn Forte 	/* Load command data segment. */
739fcf3ce44SJohn Forte 	ptr32 = (uint32_t *)&pkt->dseg_0_address;
740fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
741fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address);
742fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused);
743fcf3ce44SJohn Forte 	ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size);
744fcf3ce44SJohn Forte 	seg_cnt--;
745fcf3ce44SJohn Forte 	cp++;
746fcf3ce44SJohn Forte 
747fcf3ce44SJohn Forte 	/*
748fcf3ce44SJohn Forte 	 * Build continuation packets.
749fcf3ce44SJohn Forte 	 */
750fcf3ce44SJohn Forte 	if (seg_cnt) {
751fcf3ce44SJohn Forte 		ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE);
752fcf3ce44SJohn Forte 	}
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
755fcf3ce44SJohn Forte }
756fcf3ce44SJohn Forte 
757*f885d00fSDaniel Beauregard /*
758*f885d00fSDaniel Beauregard  * ql_cmd_24xx_type_6_iocb
759*f885d00fSDaniel Beauregard  *	Setup of ISP24xx command type 6 IOCB.
760*f885d00fSDaniel Beauregard  *
761*f885d00fSDaniel Beauregard  * Input:
762*f885d00fSDaniel Beauregard  *	ha:	adapter state pointer.
763*f885d00fSDaniel Beauregard  *	sp:	srb structure pointer.
764*f885d00fSDaniel Beauregard  *	arg:	request queue packet.
765*f885d00fSDaniel Beauregard  *
766*f885d00fSDaniel Beauregard  * Context:
767*f885d00fSDaniel Beauregard  *	Interrupt or Kernel context, no mailbox commands allowed.
768*f885d00fSDaniel Beauregard  */
769*f885d00fSDaniel Beauregard static void
ql_cmd_24xx_type_6_iocb(ql_adapter_state_t * ha,ql_srb_t * sp,void * arg)770*f885d00fSDaniel Beauregard ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg)
771*f885d00fSDaniel Beauregard {
772*f885d00fSDaniel Beauregard 	uint64_t		addr;
773*f885d00fSDaniel Beauregard 	ddi_dma_cookie_t	*cp;
774*f885d00fSDaniel Beauregard 	uint32_t		*ptr32;
775*f885d00fSDaniel Beauregard 	uint16_t		seg_cnt;
776*f885d00fSDaniel Beauregard 	fcp_cmd_t		*fcp = sp->fcp;
777*f885d00fSDaniel Beauregard 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
778*f885d00fSDaniel Beauregard 	cmd6_24xx_entry_t	*pkt = arg;
779*f885d00fSDaniel Beauregard 	ql_adapter_state_t	*pha = ha->pha;
780*f885d00fSDaniel Beauregard 	dma_mem_t		*cmem = &sp->sg_dma;
781*f885d00fSDaniel Beauregard 	cmd6_2400_dma_t		*cdma = cmem->bp;
782*f885d00fSDaniel Beauregard 
783*f885d00fSDaniel Beauregard 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
784*f885d00fSDaniel Beauregard 
785*f885d00fSDaniel Beauregard 	pkt->entry_type = IOCB_CMD_TYPE_6;
786*f885d00fSDaniel Beauregard 
787*f885d00fSDaniel Beauregard 	bzero(cdma, sizeof (cmd6_2400_dma_t));
788*f885d00fSDaniel Beauregard 
789*f885d00fSDaniel Beauregard 	/* Set LUN number */
790*f885d00fSDaniel Beauregard 	pkt->fcp_lun[2] = cdma->cmd.fcp_lun[1] = LSB(sp->lun_queue->lun_no);
791*f885d00fSDaniel Beauregard 	pkt->fcp_lun[3] = cdma->cmd.fcp_lun[0] = MSB(sp->lun_queue->lun_no);
792*f885d00fSDaniel Beauregard 
793*f885d00fSDaniel Beauregard 	/* Set N_port handle */
794*f885d00fSDaniel Beauregard 	ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id);
795*f885d00fSDaniel Beauregard 
796*f885d00fSDaniel Beauregard 	/* Set target ID */
797*f885d00fSDaniel Beauregard 	pkt->target_id[0] = tq->d_id.b.al_pa;
798*f885d00fSDaniel Beauregard 	pkt->target_id[1] = tq->d_id.b.area;
799*f885d00fSDaniel Beauregard 	pkt->target_id[2] = tq->d_id.b.domain;
800*f885d00fSDaniel Beauregard 
801*f885d00fSDaniel Beauregard 	pkt->vp_index = ha->vp_index;
802*f885d00fSDaniel Beauregard 
803*f885d00fSDaniel Beauregard 	/* Set ISP command timeout. */
804*f885d00fSDaniel Beauregard 	if (sp->isp_timeout < 0x1999) {
805*f885d00fSDaniel Beauregard 		ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout,
806*f885d00fSDaniel Beauregard 		    sp->isp_timeout);
807*f885d00fSDaniel Beauregard 	}
808*f885d00fSDaniel Beauregard 
809*f885d00fSDaniel Beauregard 	/* Load SCSI CDB */
810*f885d00fSDaniel Beauregard 	ddi_rep_put8(cmem->acc_handle, fcp->fcp_cdb, cdma->cmd.scsi_cdb,
811*f885d00fSDaniel Beauregard 	    MAX_CMDSZ, DDI_DEV_AUTOINCR);
812*f885d00fSDaniel Beauregard 
813*f885d00fSDaniel Beauregard 	/*
814*f885d00fSDaniel Beauregard 	 * Set tag queue control flags
815*f885d00fSDaniel Beauregard 	 * Note:
816*f885d00fSDaniel Beauregard 	 *	Cannot copy fcp->fcp_cntl.cntl_qtype directly,
817*f885d00fSDaniel Beauregard 	 *	problem with x86 in 32bit kernel mode
818*f885d00fSDaniel Beauregard 	 */
819*f885d00fSDaniel Beauregard 	switch (fcp->fcp_cntl.cntl_qtype) {
820*f885d00fSDaniel Beauregard 	case FCP_QTYPE_SIMPLE:
821*f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_STAG;
822*f885d00fSDaniel Beauregard 		break;
823*f885d00fSDaniel Beauregard 	case FCP_QTYPE_HEAD_OF_Q:
824*f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_HTAG;
825*f885d00fSDaniel Beauregard 		break;
826*f885d00fSDaniel Beauregard 	case FCP_QTYPE_ORDERED:
827*f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_OTAG;
828*f885d00fSDaniel Beauregard 		break;
829*f885d00fSDaniel Beauregard 	case FCP_QTYPE_ACA_Q_TAG:
830*f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_ACA;
831*f885d00fSDaniel Beauregard 		break;
832*f885d00fSDaniel Beauregard 	case FCP_QTYPE_UNTAGGED:
833*f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_UNTAGGED;
834*f885d00fSDaniel Beauregard 		break;
835*f885d00fSDaniel Beauregard 	default:
836*f885d00fSDaniel Beauregard 		break;
837*f885d00fSDaniel Beauregard 	}
838*f885d00fSDaniel Beauregard 
839*f885d00fSDaniel Beauregard 	/*
840*f885d00fSDaniel Beauregard 	 * FCP_CMND Payload Data Segment
841*f885d00fSDaniel Beauregard 	 */
842*f885d00fSDaniel Beauregard 	cp = cmem->cookies;
843*f885d00fSDaniel Beauregard 	ddi_put16(pha->hba_buf.acc_handle, &pkt->cmnd_length,
844*f885d00fSDaniel Beauregard 	    sizeof (fcp_cmnd_t));
845*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->cmnd_address[0],
846*f885d00fSDaniel Beauregard 	    cp->dmac_address);
847*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->cmnd_address[1],
848*f885d00fSDaniel Beauregard 	    cp->dmac_notused);
849*f885d00fSDaniel Beauregard 
850*f885d00fSDaniel Beauregard 	/* Set transfer direction. */
851*f885d00fSDaniel Beauregard 	if (fcp->fcp_cntl.cntl_write_data) {
852*f885d00fSDaniel Beauregard 		pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_WR);
853*f885d00fSDaniel Beauregard 		cdma->cmd.control_flags = CF_WR;
854*f885d00fSDaniel Beauregard 		pha->xioctl->IOOutputRequests++;
855*f885d00fSDaniel Beauregard 		pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
856*f885d00fSDaniel Beauregard 	} else if (fcp->fcp_cntl.cntl_read_data) {
857*f885d00fSDaniel Beauregard 		pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_RD);
858*f885d00fSDaniel Beauregard 		cdma->cmd.control_flags = CF_RD;
859*f885d00fSDaniel Beauregard 		pha->xioctl->IOInputRequests++;
860*f885d00fSDaniel Beauregard 		pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
861*f885d00fSDaniel Beauregard 	}
862*f885d00fSDaniel Beauregard 
863*f885d00fSDaniel Beauregard 	/*
864*f885d00fSDaniel Beauregard 	 * FCP_DATA Data Segment Descriptor.
865*f885d00fSDaniel Beauregard 	 */
866*f885d00fSDaniel Beauregard 	addr = cp->dmac_laddress + sizeof (fcp_cmnd_t);
867*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_address[0], LSD(addr));
868*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_address[1], MSD(addr));
869*f885d00fSDaniel Beauregard 
870*f885d00fSDaniel Beauregard 	/* Set data segment count. */
871*f885d00fSDaniel Beauregard 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
872*f885d00fSDaniel Beauregard 	ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt);
873*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_length,
874*f885d00fSDaniel Beauregard 	    seg_cnt * 12 + 12);
875*f885d00fSDaniel Beauregard 
876*f885d00fSDaniel Beauregard 	/* Load total byte count. */
877*f885d00fSDaniel Beauregard 	ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count,
878*f885d00fSDaniel Beauregard 	    fcp->fcp_data_len);
879*f885d00fSDaniel Beauregard 	ddi_put32(cmem->acc_handle, &cdma->cmd.dl, (uint32_t)fcp->fcp_data_len);
880*f885d00fSDaniel Beauregard 	ql_chg_endian((uint8_t *)&cdma->cmd.dl, 4);
881*f885d00fSDaniel Beauregard 
882*f885d00fSDaniel Beauregard 	/* Load command data segments. */
883*f885d00fSDaniel Beauregard 	ptr32 = (uint32_t *)cdma->cookie_list;
884*f885d00fSDaniel Beauregard 	cp = sp->pkt->pkt_data_cookie;
885*f885d00fSDaniel Beauregard 	while (seg_cnt--) {
886*f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_address);
887*f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_notused);
888*f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, (uint32_t)cp->dmac_size);
889*f885d00fSDaniel Beauregard 		cp++;
890*f885d00fSDaniel Beauregard 	}
891*f885d00fSDaniel Beauregard 
892*f885d00fSDaniel Beauregard 	/* Sync DMA buffer. */
893*f885d00fSDaniel Beauregard 	(void) ddi_dma_sync(cmem->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
894*f885d00fSDaniel Beauregard 
895*f885d00fSDaniel Beauregard 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
896*f885d00fSDaniel Beauregard }
897*f885d00fSDaniel Beauregard 
898fcf3ce44SJohn Forte /*
899fcf3ce44SJohn Forte  * ql_marker
900fcf3ce44SJohn Forte  *	Function issues marker IOCB.
901fcf3ce44SJohn Forte  *
902fcf3ce44SJohn Forte  * Input:
903fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
904fcf3ce44SJohn Forte  *	loop_id:	device loop ID
905fcf3ce44SJohn Forte  *	lun:		device LUN
906fcf3ce44SJohn Forte  *	type:		marker modifier
907fcf3ce44SJohn Forte  *
908fcf3ce44SJohn Forte  * Returns:
909fcf3ce44SJohn Forte  *	ql local function return status code.
910fcf3ce44SJohn Forte  *
911fcf3ce44SJohn Forte  * Context:
912fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
913fcf3ce44SJohn Forte  */
914fcf3ce44SJohn Forte int
ql_marker(ql_adapter_state_t * ha,uint16_t loop_id,uint16_t lun,uint8_t type)915fcf3ce44SJohn Forte ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, uint16_t lun,
916fcf3ce44SJohn Forte     uint8_t type)
917fcf3ce44SJohn Forte {
918fcf3ce44SJohn Forte 	mrk_entry_t	*pkt;
919fcf3ce44SJohn Forte 	int		rval;
920fcf3ce44SJohn Forte 
921fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
922fcf3ce44SJohn Forte 
923fcf3ce44SJohn Forte 	rval = ql_req_pkt(ha, (request_t **)&pkt);
924fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
925fcf3ce44SJohn Forte 		pkt->entry_type = MARKER_TYPE;
926fcf3ce44SJohn Forte 
927eb82ff87SDaniel Beauregard 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
928fcf3ce44SJohn Forte 			marker_24xx_entry_t	*pkt24 =
929fcf3ce44SJohn Forte 			    (marker_24xx_entry_t *)pkt;
930fcf3ce44SJohn Forte 
931fcf3ce44SJohn Forte 			pkt24->modifier = type;
932fcf3ce44SJohn Forte 
933fcf3ce44SJohn Forte 			/* Set LUN number */
934fcf3ce44SJohn Forte 			pkt24->fcp_lun[2] = LSB(lun);
935fcf3ce44SJohn Forte 			pkt24->fcp_lun[3] = MSB(lun);
936fcf3ce44SJohn Forte 
937fcf3ce44SJohn Forte 			pkt24->vp_index = ha->vp_index;
938fcf3ce44SJohn Forte 
939fcf3ce44SJohn Forte 			/* Set N_port handle */