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*4c3888b8SHans Rosenfeld /* Copyright 2015 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25f885d00fSDaniel Beauregard  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28fcf3ce44SJohn Forte /*
29fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
30fcf3ce44SJohn Forte  *
31fcf3ce44SJohn Forte  * ***********************************************************************
32fcf3ce44SJohn Forte  * *									**
33fcf3ce44SJohn Forte  * *				NOTICE					**
34*4c3888b8SHans Rosenfeld  * *		COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION		**
35fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
36fcf3ce44SJohn Forte  * *									**
37fcf3ce44SJohn Forte  * ***********************************************************************
38fcf3ce44SJohn Forte  *
39fcf3ce44SJohn Forte  */
40fcf3ce44SJohn Forte 
41fcf3ce44SJohn Forte #include <ql_apps.h>
42fcf3ce44SJohn Forte #include <ql_api.h>
43fcf3ce44SJohn Forte #include <ql_debug.h>
44fcf3ce44SJohn Forte #include <ql_iocb.h>
45fcf3ce44SJohn Forte #include <ql_isr.h>
46*4c3888b8SHans Rosenfeld #include <ql_nx.h>
47fcf3ce44SJohn Forte #include <ql_xioctl.h>
48*4c3888b8SHans Rosenfeld #include <ql_fm.h>
49*4c3888b8SHans Rosenfeld 
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte /*
52fcf3ce44SJohn Forte  * Local Function Prototypes.
53fcf3ce44SJohn Forte  */
54*4c3888b8SHans Rosenfeld static int ql_req_pkt(ql_adapter_state_t *, ql_request_q_t *, request_t **);
55*4c3888b8SHans Rosenfeld static void ql_isp_cmd(ql_adapter_state_t *, ql_request_q_t *);
56*4c3888b8SHans Rosenfeld static void ql_continuation_iocb(ql_adapter_state_t *, ql_request_q_t *,
57*4c3888b8SHans Rosenfeld     ddi_dma_cookie_t *, uint16_t, boolean_t);
58fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *);
59*4c3888b8SHans Rosenfeld static void ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *, ql_request_q_t *,
60*4c3888b8SHans Rosenfeld     ql_srb_t *, void *);
61fcf3ce44SJohn Forte 
62fcf3ce44SJohn Forte /*
63fcf3ce44SJohn Forte  * ql_start_iocb
64fcf3ce44SJohn Forte  *	The start IOCB is responsible for building request packets
65fcf3ce44SJohn Forte  *	on request ring and modifying ISP input pointer.
66fcf3ce44SJohn Forte  *
67fcf3ce44SJohn Forte  * Input:
68fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
69fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
70fcf3ce44SJohn Forte  *
71fcf3ce44SJohn Forte  * Context:
72fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
73fcf3ce44SJohn Forte  */
74fcf3ce44SJohn Forte void
ql_start_iocb(ql_adapter_state_t * vha,ql_srb_t * sp)75fcf3ce44SJohn Forte ql_start_iocb(ql_adapter_state_t *vha, ql_srb_t *sp)
76fcf3ce44SJohn Forte {
77fcf3ce44SJohn Forte 	ql_link_t		*link;
78*4c3888b8SHans Rosenfeld 	ql_request_q_t		*req_q;
79fcf3ce44SJohn Forte 	request_t		*pkt;
80fcf3ce44SJohn Forte 	uint64_t		*ptr64;
81fcf3ce44SJohn Forte 	uint32_t		cnt;
82fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
83fcf3ce44SJohn Forte 
84*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	/* Acquire ring lock. */
87fcf3ce44SJohn Forte 	REQUEST_RING_LOCK(ha);
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte 	if (sp != NULL) {
90fcf3ce44SJohn Forte 		/*
9116dd44c2SDaniel Beauregard 		 * If the pending queue is not empty maintain order
9216dd44c2SDaniel Beauregard 		 * by puting this srb at the tail and geting the head.
93fcf3ce44SJohn Forte 		 */
94fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) != NULL) {
95fcf3ce44SJohn Forte 			ql_add_link_b(&ha->pending_cmds, &sp->cmd);
96fcf3ce44SJohn Forte 			/* Remove command from pending command queue */
97fcf3ce44SJohn Forte 			sp = link->base_address;
98fcf3ce44SJohn Forte 			ql_remove_link(&ha->pending_cmds, &sp->cmd);
99fcf3ce44SJohn Forte 		}
100fcf3ce44SJohn Forte 	} else {
101fcf3ce44SJohn Forte 		/* Get command from pending command queue if not empty. */
102fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) == NULL) {
103fcf3ce44SJohn Forte 			/* Release ring specific lock */
104fcf3ce44SJohn Forte 			REQUEST_RING_UNLOCK(ha);
105*4c3888b8SHans Rosenfeld 			QL_PRINT_3(ha, "empty done\n");
106fcf3ce44SJohn Forte 			return;
107fcf3ce44SJohn Forte 		}
108fcf3ce44SJohn Forte 		/* Remove command from pending command queue */
109fcf3ce44SJohn Forte 		sp = link->base_address;
110fcf3ce44SJohn Forte 		ql_remove_link(&ha->pending_cmds, &sp->cmd);
111fcf3ce44SJohn Forte 	}
112fcf3ce44SJohn Forte 
11316dd44c2SDaniel Beauregard 	/* start this request and as many others as possible */
114fcf3ce44SJohn Forte 	for (;;) {
115*4c3888b8SHans Rosenfeld 		if (ha->req_q[1] != NULL && sp->rsp_q_number != 0) {
116*4c3888b8SHans Rosenfeld 			req_q = ha->req_q[1];
117*4c3888b8SHans Rosenfeld 		} else {
118*4c3888b8SHans Rosenfeld 			req_q = ha->req_q[0];
119*4c3888b8SHans Rosenfeld 		}
120*4c3888b8SHans Rosenfeld 
121*4c3888b8SHans Rosenfeld 		if (req_q->req_q_cnt < sp->req_cnt) {
122fcf3ce44SJohn Forte 			/* Calculate number of free request entries. */
123*4c3888b8SHans Rosenfeld 			if (ha->flags & QUEUE_SHADOW_PTRS) {
124*4c3888b8SHans Rosenfeld 				(void) ddi_dma_sync(req_q->req_ring.dma_handle,
125*4c3888b8SHans Rosenfeld 				    (off_t)req_q->req_out_shadow_ofst,
126*4c3888b8SHans Rosenfeld 				    SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
127*4c3888b8SHans Rosenfeld 				cnt = ddi_get32(req_q->req_ring.acc_handle,
128*4c3888b8SHans Rosenfeld 				    req_q->req_out_shadow_ptr);
129*4c3888b8SHans Rosenfeld 			} else if (ha->flags & MULTI_QUEUE) {
130*4c3888b8SHans Rosenfeld 				cnt = RD16_MBAR_REG(ha, req_q->mbar_req_out);
131fcf3ce44SJohn Forte 			} else {
132*4c3888b8SHans Rosenfeld 				cnt = RD16_IO_REG(ha, req_out);
133fcf3ce44SJohn Forte 			}
134*4c3888b8SHans Rosenfeld 			if (req_q->req_ring_index < cnt) {
135*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt = (uint16_t)
136*4c3888b8SHans Rosenfeld 				    (cnt - req_q->req_ring_index);
137*4c3888b8SHans Rosenfeld 			} else {
138*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt =
139*4c3888b8SHans Rosenfeld 				    (uint16_t)(req_q->req_entry_cnt -
140*4c3888b8SHans Rosenfeld 				    (req_q->req_ring_index - cnt));
141*4c3888b8SHans Rosenfeld 			}
142*4c3888b8SHans Rosenfeld 			if (req_q->req_q_cnt != 0) {
143*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt--;
144fcf3ce44SJohn Forte 			}
145fcf3ce44SJohn Forte 
14616dd44c2SDaniel Beauregard 			/*
14716dd44c2SDaniel Beauregard 			 * If no room in request ring put this srb at
14816dd44c2SDaniel Beauregard 			 * the head of the pending queue and exit.
14916dd44c2SDaniel Beauregard 			 */
150*4c3888b8SHans Rosenfeld 			if (req_q->req_q_cnt < sp->req_cnt) {
151*4c3888b8SHans Rosenfeld 				QL_PRINT_8(ha, "request ring full,"
152fcf3ce44SJohn Forte 				    " req_q_cnt=%d, req_ring_index=%d\n",
153*4c3888b8SHans Rosenfeld 				    req_q->req_q_cnt, req_q->req_ring_index);
154fcf3ce44SJohn Forte 				ql_add_link_t(&ha->pending_cmds, &sp->cmd);
155fcf3ce44SJohn Forte 				break;
156fcf3ce44SJohn Forte 			}
157fcf3ce44SJohn Forte 		}
158fcf3ce44SJohn Forte 
159fcf3ce44SJohn Forte 		/* Check for room in outstanding command list. */
160*4c3888b8SHans Rosenfeld 		for (cnt = 1; cnt < ha->osc_max_cnt; cnt++) {
161fcf3ce44SJohn Forte 			ha->osc_index++;
162*4c3888b8SHans Rosenfeld 			if (ha->osc_index == ha->osc_max_cnt) {
163fcf3ce44SJohn Forte 				ha->osc_index = 1;
164fcf3ce44SJohn Forte 			}
165fcf3ce44SJohn Forte 			if (ha->outstanding_cmds[ha->osc_index] == NULL) {
166fcf3ce44SJohn Forte 				break;
167fcf3ce44SJohn Forte 			}
168fcf3ce44SJohn Forte 		}
16916dd44c2SDaniel Beauregard 		/*
17016dd44c2SDaniel Beauregard 		 * If no room in outstanding array put this srb at
17116dd44c2SDaniel Beauregard 		 * the head of the pending queue and exit.
17216dd44c2SDaniel Beauregard 		 */
173*4c3888b8SHans Rosenfeld 		if (cnt == ha->osc_max_cnt) {
174*4c3888b8SHans Rosenfeld 			QL_PRINT_8(ha, "no room in outstanding array\n");
175fcf3ce44SJohn Forte 			ql_add_link_t(&ha->pending_cmds, &sp->cmd);
176fcf3ce44SJohn Forte 			break;
177fcf3ce44SJohn Forte 		}
178fcf3ce44SJohn Forte 
17916dd44c2SDaniel Beauregard 		/* nothing to stop us now. */
180fcf3ce44SJohn Forte 		ha->outstanding_cmds[ha->osc_index] = sp;
18116dd44c2SDaniel Beauregard 		/* create and save a unique response identifier in the srb */
182fcf3ce44SJohn Forte 		sp->handle = ha->adapter_stats->ncmds << OSC_INDEX_SHIFT |
183fcf3ce44SJohn Forte 		    ha->osc_index;
184*4c3888b8SHans Rosenfeld 		req_q->req_q_cnt = (uint16_t)(req_q->req_q_cnt - sp->req_cnt);
18516dd44c2SDaniel Beauregard 
18616dd44c2SDaniel Beauregard 		/* build the iocb in the request ring */
187*4c3888b8SHans Rosenfeld 		pkt = req_q->req_ring_ptr;
188f885d00fSDaniel Beauregard 		sp->request_ring_ptr = pkt;
189*4c3888b8SHans Rosenfeld 		sp->req_q_number = req_q->req_q_number;
190fcf3ce44SJohn Forte 		sp->flags |= SRB_IN_TOKEN_ARRAY;
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 		/* Zero out packet. */
193fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
194fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
195fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
196fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
197fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 		/* Setup IOCB common data. */
200fcf3ce44SJohn Forte 		pkt->entry_count = (uint8_t)sp->req_cnt;
201*4c3888b8SHans Rosenfeld 		if (ha->req_q[1] != NULL && sp->rsp_q_number != 0) {
202*4c3888b8SHans Rosenfeld 			pkt->entry_status = sp->rsp_q_number;
203*4c3888b8SHans Rosenfeld 		}
204*4c3888b8SHans Rosenfeld 		pkt->sys_define = (uint8_t)req_q->req_ring_index;
205*4c3888b8SHans Rosenfeld 
20616dd44c2SDaniel Beauregard 		/* mark the iocb with the response identifier */
207*4c3888b8SHans Rosenfeld 		ddi_put32(req_q->req_ring.acc_handle, &pkt->handle,
208fcf3ce44SJohn Forte 		    (uint32_t)sp->handle);
209fcf3ce44SJohn Forte 
21016dd44c2SDaniel Beauregard 		/* Setup IOCB unique data. */
211*4c3888b8SHans Rosenfeld 		(sp->iocb)(vha, req_q, sp, pkt);
212fcf3ce44SJohn Forte 
213fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_STARTED;
214fcf3ce44SJohn Forte 
215*4c3888b8SHans Rosenfeld 		QL_PRINT_5(ha, "req packet, sp=%p\n", (void *)sp);
216fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
219*4c3888b8SHans Rosenfeld 		(void) ddi_dma_sync(req_q->req_ring.dma_handle,
220*4c3888b8SHans Rosenfeld 		    (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
221*4c3888b8SHans Rosenfeld 		    (size_t)REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 		/* Adjust ring index. */
224*4c3888b8SHans Rosenfeld 		req_q->req_ring_index++;
225*4c3888b8SHans Rosenfeld 		if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
226*4c3888b8SHans Rosenfeld 			req_q->req_ring_index = 0;
227*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr = req_q->req_ring.bp;
228fcf3ce44SJohn Forte 		} else {
229*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr++;
230fcf3ce44SJohn Forte 		}
231fcf3ce44SJohn Forte 
232fcf3ce44SJohn Forte 		/* Reset watchdog timer */
233fcf3ce44SJohn Forte 		sp->wdg_q_time = sp->init_wdg_q_time;
234fcf3ce44SJohn Forte 
23516dd44c2SDaniel Beauregard 		/*
23616dd44c2SDaniel Beauregard 		 * Send it by setting the new ring index in the ISP Request
23716dd44c2SDaniel Beauregard 		 * Ring In Pointer register.  This is the mechanism
23816dd44c2SDaniel Beauregard 		 * used to notify the isp that a new iocb has been
23916dd44c2SDaniel Beauregard 		 * placed on the request ring.
24016dd44c2SDaniel Beauregard 		 */
241*4c3888b8SHans Rosenfeld 		if (ha->flags & MULTI_QUEUE) {
242*4c3888b8SHans Rosenfeld 			WR16_MBAR_REG(ha, req_q->mbar_req_in,
243*4c3888b8SHans Rosenfeld 			    req_q->req_ring_index);
244*4c3888b8SHans Rosenfeld 		} else if (CFG_IST(ha, CFG_CTRL_82XX)) {
245*4c3888b8SHans Rosenfeld 			ql_8021_wr_req_in(ha, req_q->req_ring_index);
246eb82ff87SDaniel Beauregard 		} else {
247*4c3888b8SHans Rosenfeld 			WRT16_IO_REG(ha, req_in, req_q->req_ring_index);
248eb82ff87SDaniel Beauregard 		}
249fcf3ce44SJohn Forte 
250fcf3ce44SJohn Forte 		/* Update outstanding command count statistic. */
251fcf3ce44SJohn Forte 		ha->adapter_stats->ncmds++;
252fcf3ce44SJohn Forte 
25316dd44c2SDaniel Beauregard 		/* if there is a pending command, try to start it. */
254fcf3ce44SJohn Forte 		if ((link = ha->pending_cmds.first) == NULL) {
255fcf3ce44SJohn Forte 			break;
256fcf3ce44SJohn Forte 		}
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte 		/* Remove command from pending command queue */
259fcf3ce44SJohn Forte 		sp = link->base_address;
260fcf3ce44SJohn Forte 		ql_remove_link(&ha->pending_cmds, &sp->cmd);
261fcf3ce44SJohn Forte 	}
262fcf3ce44SJohn Forte 
263*4c3888b8SHans Rosenfeld 	if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
264*4c3888b8SHans Rosenfeld 	    != DDI_FM_OK) {
265*4c3888b8SHans Rosenfeld 		qlc_fm_report_err_impact(ha,
266*4c3888b8SHans Rosenfeld 		    QL_FM_EREPORT_ACC_HANDLE_CHECK);
267*4c3888b8SHans Rosenfeld 	}
268*4c3888b8SHans Rosenfeld 
269fcf3ce44SJohn Forte 	/* Release ring specific lock */
270fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
271fcf3ce44SJohn Forte 
272*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
273fcf3ce44SJohn Forte }
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte /*
276fcf3ce44SJohn Forte  * ql_req_pkt
277fcf3ce44SJohn Forte  *	Function is responsible for locking ring and
278fcf3ce44SJohn Forte  *	getting a zeroed out request packet.
279fcf3ce44SJohn Forte  *
280fcf3ce44SJohn Forte  * Input:
281fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
282*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
283fcf3ce44SJohn Forte  *	pkt:	address for packet pointer.
284fcf3ce44SJohn Forte  *
285fcf3ce44SJohn Forte  * Returns:
286fcf3ce44SJohn Forte  *	ql local function return status code.
287fcf3ce44SJohn Forte  *
288fcf3ce44SJohn Forte  * Context:
289fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
290fcf3ce44SJohn Forte  */
2915dfd244aSDaniel Beauregard static int
ql_req_pkt(ql_adapter_state_t * vha,ql_request_q_t * req_q,request_t ** pktp)292*4c3888b8SHans Rosenfeld ql_req_pkt(ql_adapter_state_t *vha, ql_request_q_t *req_q, request_t **pktp)
293fcf3ce44SJohn Forte {
294fcf3ce44SJohn Forte 	uint16_t		cnt;
295*4c3888b8SHans Rosenfeld 	uint64_t		*ptr64;
296fcf3ce44SJohn Forte 	uint32_t		timer;
297fcf3ce44SJohn Forte 	int			rval = QL_FUNCTION_TIMEOUT;
298fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
299fcf3ce44SJohn Forte 
300*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 	/* Wait for 30 seconds for slot. */
303fcf3ce44SJohn Forte 	for (timer = 30000; timer != 0; timer--) {
304fcf3ce44SJohn Forte 		/* Acquire ring lock. */
305fcf3ce44SJohn Forte 		REQUEST_RING_LOCK(ha);
306fcf3ce44SJohn Forte 
307*4c3888b8SHans Rosenfeld 		if (req_q->req_q_cnt == 0) {
308fcf3ce44SJohn Forte 			/* Calculate number of free request entries. */
309*4c3888b8SHans Rosenfeld 			if (ha->flags & QUEUE_SHADOW_PTRS) {
310*4c3888b8SHans Rosenfeld 				(void) ddi_dma_sync(req_q->req_ring.dma_handle,
311*4c3888b8SHans Rosenfeld 				    (off_t)req_q->req_out_shadow_ofst,
312*4c3888b8SHans Rosenfeld 				    SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
313*4c3888b8SHans Rosenfeld 				cnt = ddi_get32(req_q->req_ring.acc_handle,
314*4c3888b8SHans Rosenfeld 				    req_q->req_out_shadow_ptr);
315*4c3888b8SHans Rosenfeld 			} else if (ha->flags & MULTI_QUEUE) {
316*4c3888b8SHans Rosenfeld 				cnt = RD16_MBAR_REG(ha, req_q->mbar_req_out);
317*4c3888b8SHans Rosenfeld 			} else {
318*4c3888b8SHans Rosenfeld 				cnt = RD16_IO_REG(ha, req_out);
319*4c3888b8SHans Rosenfeld 			}
320*4c3888b8SHans Rosenfeld 			if (req_q->req_ring_index < cnt) {
321*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt = (uint16_t)
322*4c3888b8SHans Rosenfeld 				    (cnt - req_q->req_ring_index);
323fcf3ce44SJohn Forte 			} else {
324*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt = (uint16_t)
325fcf3ce44SJohn Forte 				    (REQUEST_ENTRY_CNT -
326*4c3888b8SHans Rosenfeld 				    (req_q->req_ring_index - cnt));
327fcf3ce44SJohn Forte 			}
328*4c3888b8SHans Rosenfeld 			if (req_q->req_q_cnt != 0) {
329*4c3888b8SHans Rosenfeld 				req_q->req_q_cnt--;
330fcf3ce44SJohn Forte 			}
331fcf3ce44SJohn Forte 		}
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte 		/* Found empty request ring slot? */
334*4c3888b8SHans Rosenfeld 		if (req_q->req_q_cnt != 0) {
335*4c3888b8SHans Rosenfeld 			req_q->req_q_cnt--;
336*4c3888b8SHans Rosenfeld 			*pktp = req_q->req_ring_ptr;
337fcf3ce44SJohn Forte 
338fcf3ce44SJohn Forte 			/* Zero out packet. */
339*4c3888b8SHans Rosenfeld 			ptr64 = (uint64_t *)req_q->req_ring_ptr;
340*4c3888b8SHans Rosenfeld 			*ptr64++ = 0; *ptr64++ = 0;
341*4c3888b8SHans Rosenfeld 			*ptr64++ = 0; *ptr64++ = 0;
342*4c3888b8SHans Rosenfeld 			*ptr64++ = 0; *ptr64++ = 0;
343*4c3888b8SHans Rosenfeld 			*ptr64++ = 0; *ptr64 = 0;
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 			/* Setup IOCB common data. */
346*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr->entry_count = 1;
347*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr->sys_define =
348*4c3888b8SHans Rosenfeld 			    (uint8_t)req_q->req_ring_index;
349*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle,
350*4c3888b8SHans Rosenfeld 			    &req_q->req_ring_ptr->handle,
351fcf3ce44SJohn Forte 			    (uint32_t)QL_FCA_BRAND);
352fcf3ce44SJohn Forte 
353fcf3ce44SJohn Forte 			rval = QL_SUCCESS;
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 			break;
356fcf3ce44SJohn Forte 		}
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 		/* Release request queue lock. */
359fcf3ce44SJohn Forte 		REQUEST_RING_UNLOCK(ha);
360fcf3ce44SJohn Forte 
361fcf3ce44SJohn Forte 		drv_usecwait(MILLISEC);
362fcf3ce44SJohn Forte 
363fcf3ce44SJohn Forte 		/* Check for pending interrupts. */
364fcf3ce44SJohn Forte 		/*
365fcf3ce44SJohn Forte 		 * XXX protect interrupt routine from calling itself.
366fcf3ce44SJohn Forte 		 * Need to revisit this routine. So far we never
367fcf3ce44SJohn Forte 		 * hit this case as req slot was available
368fcf3ce44SJohn Forte 		 */
369fcf3ce44SJohn Forte 		if ((!(curthread->t_flag & T_INTR_THREAD)) &&
370eb82ff87SDaniel Beauregard 		    INTERRUPT_PENDING(ha)) {
371fcf3ce44SJohn Forte 			(void) ql_isr((caddr_t)ha);
372fcf3ce44SJohn Forte 			INTR_LOCK(ha);
373fcf3ce44SJohn Forte 			ha->intr_claimed = TRUE;
374fcf3ce44SJohn Forte 			INTR_UNLOCK(ha);
375fcf3ce44SJohn Forte 		}
376fcf3ce44SJohn Forte 	}
377fcf3ce44SJohn Forte 
378fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
379fcf3ce44SJohn Forte 		ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
380fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval);
381fcf3ce44SJohn Forte 	} else {
382fcf3ce44SJohn Forte 		/*EMPTY*/
383*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
384fcf3ce44SJohn Forte 	}
385fcf3ce44SJohn Forte 	return (rval);
386fcf3ce44SJohn Forte }
387fcf3ce44SJohn Forte 
388fcf3ce44SJohn Forte /*
389fcf3ce44SJohn Forte  * ql_isp_cmd
390fcf3ce44SJohn Forte  *	Function is responsible for modifying ISP input pointer.
39116dd44c2SDaniel Beauregard  *	This action notifies the isp that a new request has been
39216dd44c2SDaniel Beauregard  *	added to the request ring.
39316dd44c2SDaniel Beauregard  *
394fcf3ce44SJohn Forte  *	Releases ring lock.
395fcf3ce44SJohn Forte  *
396fcf3ce44SJohn Forte  * Input:
397*4c3888b8SHans Rosenfeld  *	vha:	adapter state pointer.
398*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
399fcf3ce44SJohn Forte  *
400fcf3ce44SJohn Forte  * Context:
401fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
402fcf3ce44SJohn Forte  */
403*4c3888b8SHans Rosenfeld static void
ql_isp_cmd(ql_adapter_state_t * vha,ql_request_q_t * req_q)404*4c3888b8SHans Rosenfeld ql_isp_cmd(ql_adapter_state_t *vha, ql_request_q_t *req_q)
405fcf3ce44SJohn Forte {
406fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
407fcf3ce44SJohn Forte 
408*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
409fcf3ce44SJohn Forte 
410*4c3888b8SHans Rosenfeld 	QL_PRINT_5(ha, "req packet:\n");
411*4c3888b8SHans Rosenfeld 	QL_DUMP_5((uint8_t *)req_q->req_ring_ptr, 8, REQUEST_ENTRY_SIZE);
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 	/* Sync DMA buffer. */
414*4c3888b8SHans Rosenfeld 	(void) ddi_dma_sync(req_q->req_ring.dma_handle,
415*4c3888b8SHans Rosenfeld 	    (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
416*4c3888b8SHans Rosenfeld 	    (size_t)REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);
417fcf3ce44SJohn Forte 
418fcf3ce44SJohn Forte 	/* Adjust ring index. */
419*4c3888b8SHans Rosenfeld 	req_q->req_ring_index++;
420*4c3888b8SHans Rosenfeld 	if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
421*4c3888b8SHans Rosenfeld 		req_q->req_ring_index = 0;
422*4c3888b8SHans Rosenfeld 		req_q->req_ring_ptr = req_q->req_ring.bp;
423fcf3ce44SJohn Forte 	} else {
424*4c3888b8SHans Rosenfeld 		req_q->req_ring_ptr++;
425fcf3ce44SJohn Forte 	}
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte 	/* Set chip new ring index. */
428*4c3888b8SHans Rosenfeld 	if (ha->flags & MULTI_QUEUE) {
429*4c3888b8SHans Rosenfeld 		WR16_MBAR_REG(ha, req_q->mbar_req_in,
430*4c3888b8SHans Rosenfeld 		    req_q->req_ring_index);
431*4c3888b8SHans Rosenfeld 	} else if (CFG_IST(ha, CFG_CTRL_82XX)) {
432*4c3888b8SHans Rosenfeld 		ql_8021_wr_req_in(ha, req_q->req_ring_index);
433eb82ff87SDaniel Beauregard 	} else {
434*4c3888b8SHans Rosenfeld 		WRT16_IO_REG(ha, req_in, req_q->req_ring_index);
435eb82ff87SDaniel Beauregard 	}
436fcf3ce44SJohn Forte 
437fcf3ce44SJohn Forte 	/* Release ring lock. */
438fcf3ce44SJohn Forte 	REQUEST_RING_UNLOCK(ha);
439fcf3ce44SJohn Forte 
440*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
441fcf3ce44SJohn Forte }
442fcf3ce44SJohn Forte 
443fcf3ce44SJohn Forte /*
444fcf3ce44SJohn Forte  * ql_command_iocb
445fcf3ce44SJohn Forte  *	Setup of command IOCB.
446fcf3ce44SJohn Forte  *
447fcf3ce44SJohn Forte  * Input:
448fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
449*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
450fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
451fcf3ce44SJohn Forte  *	arg:	request queue packet.
452fcf3ce44SJohn Forte  *
453fcf3ce44SJohn Forte  * Context:
454fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
455fcf3ce44SJohn Forte  */
456fcf3ce44SJohn Forte void
ql_command_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)457*4c3888b8SHans Rosenfeld ql_command_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
458*4c3888b8SHans Rosenfeld     void *arg)
459fcf3ce44SJohn Forte {
460fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
461fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
462fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
463fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
464fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
465fcf3ce44SJohn Forte 	cmd_entry_t		*pkt = arg;
466*4c3888b8SHans Rosenfeld 	cmd_3_entry_t		*pkt3 = arg;
467fcf3ce44SJohn Forte 
468*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 	/* Set LUN number */
471fcf3ce44SJohn Forte 	pkt->lun_l = LSB(sp->lun_queue->lun_no);
472fcf3ce44SJohn Forte 	pkt->lun_h = MSB(sp->lun_queue->lun_no);
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte 	/* Set target ID */
475fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
476fcf3ce44SJohn Forte 		pkt->target_l = LSB(tq->loop_id);
477fcf3ce44SJohn Forte 		pkt->target_h = MSB(tq->loop_id);
478fcf3ce44SJohn Forte 	} else {
479fcf3ce44SJohn Forte 		pkt->target_h = LSB(tq->loop_id);
480fcf3ce44SJohn Forte 	}
481fcf3ce44SJohn Forte 
482fcf3ce44SJohn Forte 	/* Set tag queue control flags */
483fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
484fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
485fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_HTAG);
486fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
487fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
488fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_OTAG);
489fcf3ce44SJohn Forte 	/* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */
490fcf3ce44SJohn Forte 	} else {
491fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
492fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_STAG);
493fcf3ce44SJohn Forte 	}
494fcf3ce44SJohn Forte 
495fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
496*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
497fcf3ce44SJohn Forte 
498fcf3ce44SJohn Forte 	/* Load SCSI CDB */
499*4c3888b8SHans Rosenfeld 	ddi_rep_put8(req_q->req_ring.acc_handle, fcp->fcp_cdb,
500fcf3ce44SJohn Forte 	    pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR);
501fcf3ce44SJohn Forte 
502fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
503*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
504*4c3888b8SHans Rosenfeld 		pkt->entry_type = IOCB_CMD_TYPE_2;
505fcf3ce44SJohn Forte 		ha->xioctl->IOControlRequests++;
506fcf3ce44SJohn Forte 		return;
507fcf3ce44SJohn Forte 	}
508fcf3ce44SJohn Forte 
509fcf3ce44SJohn Forte 	/*
510fcf3ce44SJohn Forte 	 * Set transfer direction. Load Data segments.
511fcf3ce44SJohn Forte 	 */
512fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
513fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
514fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_OUT);
515fcf3ce44SJohn Forte 		ha->xioctl->IOOutputRequests++;
516fcf3ce44SJohn Forte 		ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
517fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
518fcf3ce44SJohn Forte 		pkt->control_flags_l = (uint8_t)
519fcf3ce44SJohn Forte 		    (pkt->control_flags_l | CF_DATA_IN);
520fcf3ce44SJohn Forte 		ha->xioctl->IOInputRequests++;
521fcf3ce44SJohn Forte 		ha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
522fcf3ce44SJohn Forte 	}
523fcf3ce44SJohn Forte 
524fcf3ce44SJohn Forte 	/* Set data segment count. */
525fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
526*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
527fcf3ce44SJohn Forte 
528fcf3ce44SJohn Forte 	/* Load total byte count. */
529*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
530*4c3888b8SHans Rosenfeld 	    fcp->fcp_data_len);
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte 	/* Load command data segment. */
533fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
534*4c3888b8SHans Rosenfeld 
535*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
536*4c3888b8SHans Rosenfeld 		pkt3->entry_type = IOCB_CMD_TYPE_3;
537*4c3888b8SHans Rosenfeld 		cnt = CMD_TYPE_3_DATA_SEGMENTS;
538*4c3888b8SHans Rosenfeld 
539*4c3888b8SHans Rosenfeld 		ptr32 = (uint32_t *)&pkt3->dseg;
540*4c3888b8SHans Rosenfeld 		while (cnt && seg_cnt) {
541*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
542*4c3888b8SHans Rosenfeld 			    cp->dmac_address);
543*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
544fcf3ce44SJohn Forte 			    cp->dmac_notused);
545*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
546*4c3888b8SHans Rosenfeld 			    (uint32_t)cp->dmac_size);
547*4c3888b8SHans Rosenfeld 			seg_cnt--;
548*4c3888b8SHans Rosenfeld 			cnt--;
549*4c3888b8SHans Rosenfeld 			cp++;
550*4c3888b8SHans Rosenfeld 		}
551*4c3888b8SHans Rosenfeld 	} else {
552*4c3888b8SHans Rosenfeld 		pkt->entry_type = IOCB_CMD_TYPE_2;
553*4c3888b8SHans Rosenfeld 		cnt = CMD_TYPE_2_DATA_SEGMENTS;
554*4c3888b8SHans Rosenfeld 
555*4c3888b8SHans Rosenfeld 		ptr32 = (uint32_t *)&pkt->dseg;
556*4c3888b8SHans Rosenfeld 		while (cnt && seg_cnt) {
557*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
558*4c3888b8SHans Rosenfeld 			    cp->dmac_address);
559*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
560*4c3888b8SHans Rosenfeld 			    (uint32_t)cp->dmac_size);
561*4c3888b8SHans Rosenfeld 			seg_cnt--;
562*4c3888b8SHans Rosenfeld 			cnt--;
563*4c3888b8SHans Rosenfeld 			cp++;
564fcf3ce44SJohn Forte 		}
565fcf3ce44SJohn Forte 	}
566fcf3ce44SJohn Forte 
567fcf3ce44SJohn Forte 	/*
568fcf3ce44SJohn Forte 	 * Build continuation packets.
569fcf3ce44SJohn Forte 	 */
570fcf3ce44SJohn Forte 	if (seg_cnt) {
571*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(ha, req_q, cp, seg_cnt,
572fcf3ce44SJohn Forte 		    (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
573fcf3ce44SJohn Forte 	}
574fcf3ce44SJohn Forte 
575*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
576fcf3ce44SJohn Forte }
577fcf3ce44SJohn Forte 
578fcf3ce44SJohn Forte /*
579fcf3ce44SJohn Forte  * ql_continuation_iocb
580fcf3ce44SJohn Forte  *	Setup of continuation IOCB.
581fcf3ce44SJohn Forte  *
582fcf3ce44SJohn Forte  * Input:
583fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
584*4c3888b8SHans Rosenfeld  *	req_q:		request queue structure pointer.
585fcf3ce44SJohn Forte  *	cp:		cookie list pointer.
586fcf3ce44SJohn Forte  *	seg_cnt:	number of segments.
587fcf3ce44SJohn Forte  *	addr64:		64 bit addresses.
588fcf3ce44SJohn Forte  *
589fcf3ce44SJohn Forte  * Context:
590fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
591fcf3ce44SJohn Forte  */
592*4c3888b8SHans Rosenfeld /* ARGSUSED */
593fcf3ce44SJohn Forte static void
ql_continuation_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ddi_dma_cookie_t * cp,uint16_t seg_cnt,boolean_t addr64)594*4c3888b8SHans Rosenfeld ql_continuation_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
595*4c3888b8SHans Rosenfeld     ddi_dma_cookie_t *cp, uint16_t seg_cnt, boolean_t addr64)
596fcf3ce44SJohn Forte {
597*4c3888b8SHans Rosenfeld 	cont_entry_t		*pkt;
598*4c3888b8SHans Rosenfeld 	cont_type_1_entry_t	*pkt1;
599*4c3888b8SHans Rosenfeld 	uint64_t		*ptr64;
600*4c3888b8SHans Rosenfeld 	uint32_t		*ptr32, cnt;
601fcf3ce44SJohn Forte 
602*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
603fcf3ce44SJohn Forte 
604fcf3ce44SJohn Forte 	/*
605fcf3ce44SJohn Forte 	 * Build continuation packets.
606fcf3ce44SJohn Forte 	 */
607fcf3ce44SJohn Forte 	while (seg_cnt) {
608fcf3ce44SJohn Forte 		/* Sync DMA buffer. */
609*4c3888b8SHans Rosenfeld 		(void) ddi_dma_sync(req_q->req_ring.dma_handle,
610*4c3888b8SHans Rosenfeld 		    (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
611*4c3888b8SHans Rosenfeld 		    REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);
612fcf3ce44SJohn Forte 
613fcf3ce44SJohn Forte 		/* Adjust ring pointer, and deal with wrap. */
614*4c3888b8SHans Rosenfeld 		req_q->req_ring_index++;
615*4c3888b8SHans Rosenfeld 		if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
616*4c3888b8SHans Rosenfeld 			req_q->req_ring_index = 0;
617*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr = req_q->req_ring.bp;
618fcf3ce44SJohn Forte 		} else {
619*4c3888b8SHans Rosenfeld 			req_q->req_ring_ptr++;
620fcf3ce44SJohn Forte 		}
621*4c3888b8SHans Rosenfeld 		pkt = (cont_entry_t *)req_q->req_ring_ptr;
622*4c3888b8SHans Rosenfeld 		pkt1 = (cont_type_1_entry_t *)req_q->req_ring_ptr;
623fcf3ce44SJohn Forte 
624fcf3ce44SJohn Forte 		/* Zero out packet. */
625fcf3ce44SJohn Forte 		ptr64 = (uint64_t *)pkt;
626fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
627fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
628fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64++ = 0;
629fcf3ce44SJohn Forte 		*ptr64++ = 0; *ptr64 = 0;
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte 		/*
632fcf3ce44SJohn Forte 		 * Build continuation packet.
633fcf3ce44SJohn Forte 		 */
634fcf3ce44SJohn Forte 		pkt->entry_count = 1;
635*4c3888b8SHans Rosenfeld 		pkt->sys_define = (uint8_t)req_q->req_ring_index;
636fcf3ce44SJohn Forte 		if (addr64) {
637*4c3888b8SHans Rosenfeld 			pkt1->entry_type = CONTINUATION_TYPE_1;
638fcf3ce44SJohn Forte 			cnt = CONT_TYPE_1_DATA_SEGMENTS;
639*4c3888b8SHans Rosenfeld 			ptr32 = (uint32_t *)&pkt1->dseg;
640fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
641*4c3888b8SHans Rosenfeld 				ddi_put32(req_q->req_ring.acc_handle, ptr32++,
642fcf3ce44SJohn Forte 				    cp->dmac_address);
643*4c3888b8SHans Rosenfeld 				ddi_put32(req_q->req_ring.acc_handle, ptr32++,
644fcf3ce44SJohn Forte 				    cp->dmac_notused);
645*4c3888b8SHans Rosenfeld 				ddi_put32(req_q->req_ring.acc_handle, ptr32++,
646fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
647fcf3ce44SJohn Forte 				seg_cnt--;
648fcf3ce44SJohn Forte 				cnt--;
649fcf3ce44SJohn Forte 				cp++;
650fcf3ce44SJohn Forte 			}
651fcf3ce44SJohn Forte 		} else {
652fcf3ce44SJohn Forte 			pkt->entry_type = CONTINUATION_TYPE_0;
653fcf3ce44SJohn Forte 			cnt = CONT_TYPE_0_DATA_SEGMENTS;
654*4c3888b8SHans Rosenfeld 			ptr32 = (uint32_t *)&pkt->dseg;
655fcf3ce44SJohn Forte 			while (cnt && seg_cnt) {
656*4c3888b8SHans Rosenfeld 				ddi_put32(req_q->req_ring.acc_handle, ptr32++,
657fcf3ce44SJohn Forte 				    cp->dmac_address);
658*4c3888b8SHans Rosenfeld 				ddi_put32(req_q->req_ring.acc_handle, ptr32++,
659fcf3ce44SJohn Forte 				    (uint32_t)cp->dmac_size);
660fcf3ce44SJohn Forte 				seg_cnt--;
661fcf3ce44SJohn Forte 				cnt--;
662fcf3ce44SJohn Forte 				cp++;
663fcf3ce44SJohn Forte 			}
664fcf3ce44SJohn Forte 		}
665fcf3ce44SJohn Forte 
666*4c3888b8SHans Rosenfeld 		QL_PRINT_5(ha, "packet:\n");
667fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
668fcf3ce44SJohn Forte 	}
669fcf3ce44SJohn Forte 
670*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
671fcf3ce44SJohn Forte }
672fcf3ce44SJohn Forte 
673fcf3ce44SJohn Forte /*
674fcf3ce44SJohn Forte  * ql_command_24xx_iocb
675fcf3ce44SJohn Forte  *	Setup of ISP24xx command IOCB.
676fcf3ce44SJohn Forte  *
677fcf3ce44SJohn Forte  * Input:
678fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
679*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
680fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
681fcf3ce44SJohn Forte  *	arg:	request queue packet.
682fcf3ce44SJohn Forte  *
683fcf3ce44SJohn Forte  * Context:
684fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
685fcf3ce44SJohn Forte  */
686fcf3ce44SJohn Forte void
ql_command_24xx_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)687*4c3888b8SHans Rosenfeld ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
688*4c3888b8SHans Rosenfeld     ql_srb_t *sp, void *arg)
689fcf3ce44SJohn Forte {
690fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
691fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
692fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
693fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp = sp->fcp;
694fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
695f885d00fSDaniel Beauregard 	cmd7_24xx_entry_t	*pkt = arg;
696fcf3ce44SJohn Forte 	ql_adapter_state_t	*pha = ha->pha;
697*4c3888b8SHans Rosenfeld 	fcp_ent_addr_t		*fcp_ent_addr;
698fcf3ce44SJohn Forte 
699*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
700fcf3ce44SJohn Forte 
701f885d00fSDaniel Beauregard 	if (fcp->fcp_data_len != 0 && sp->sg_dma.dma_handle != NULL &&
702f885d00fSDaniel Beauregard 	    sp->pkt->pkt_data_cookie_cnt > 1) {
703*4c3888b8SHans Rosenfeld 		ql_cmd_24xx_type_6_iocb(ha, req_q, sp, arg);
704*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "cmd6 exit\n");
705f885d00fSDaniel Beauregard 		return;
706f885d00fSDaniel Beauregard 	}
707f885d00fSDaniel Beauregard 
708fcf3ce44SJohn Forte 	pkt->entry_type = IOCB_CMD_TYPE_7;
709fcf3ce44SJohn Forte 
710fcf3ce44SJohn Forte 	/* Set LUN number */
711*4c3888b8SHans Rosenfeld 	fcp_ent_addr = (fcp_ent_addr_t *)&sp->lun_queue->lun_addr;
712*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[2] = lobyte(fcp_ent_addr->ent_addr_0);
713*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[3] = hibyte(fcp_ent_addr->ent_addr_0);
714*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[0] = lobyte(fcp_ent_addr->ent_addr_1);
715*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[1] = hibyte(fcp_ent_addr->ent_addr_1);
716*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[6] = lobyte(fcp_ent_addr->ent_addr_2);
717*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[7] = hibyte(fcp_ent_addr->ent_addr_2);
718*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[4] = lobyte(fcp_ent_addr->ent_addr_3);
719*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[5] = hibyte(fcp_ent_addr->ent_addr_3);
720fcf3ce44SJohn Forte 
721fcf3ce44SJohn Forte 	/* Set N_port handle */
722*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	/* Set target ID */
725fcf3ce44SJohn Forte 	pkt->target_id[0] = tq->d_id.b.al_pa;
726fcf3ce44SJohn Forte 	pkt->target_id[1] = tq->d_id.b.area;
727fcf3ce44SJohn Forte 	pkt->target_id[2] = tq->d_id.b.domain;
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 	pkt->vp_index = ha->vp_index;
730fcf3ce44SJohn Forte 
731fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
732fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
733*4c3888b8SHans Rosenfeld 		ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
734fcf3ce44SJohn Forte 		    sp->isp_timeout);
735fcf3ce44SJohn Forte 	}
736fcf3ce44SJohn Forte 
737fcf3ce44SJohn Forte 	/* Load SCSI CDB */
738*4c3888b8SHans Rosenfeld 	ddi_rep_put8(req_q->req_ring.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb,
739fcf3ce44SJohn Forte 	    MAX_CMDSZ, DDI_DEV_AUTOINCR);
740fcf3ce44SJohn Forte 	for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
741fcf3ce44SJohn Forte 		ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4);
742fcf3ce44SJohn Forte 	}
743fcf3ce44SJohn Forte 
744fcf3ce44SJohn Forte 	/*
745fcf3ce44SJohn Forte 	 * Set tag queue control flags
746fcf3ce44SJohn Forte 	 * Note:
747fcf3ce44SJohn Forte 	 *	Cannot copy fcp->fcp_cntl.cntl_qtype directly,
748fcf3ce44SJohn Forte 	 *	problem with x86 in 32bit kernel mode
749fcf3ce44SJohn Forte 	 */
750fcf3ce44SJohn Forte 	switch (fcp->fcp_cntl.cntl_qtype) {
751fcf3ce44SJohn Forte 	case FCP_QTYPE_SIMPLE:
752fcf3ce44SJohn Forte 		pkt->task = TA_STAG;
753fcf3ce44SJohn Forte 		break;
754fcf3ce44SJohn Forte 	case FCP_QTYPE_HEAD_OF_Q:
755fcf3ce44SJohn Forte 		pkt->task = TA_HTAG;
756fcf3ce44SJohn Forte 		break;
757fcf3ce44SJohn Forte 	case FCP_QTYPE_ORDERED:
758fcf3ce44SJohn Forte 		pkt->task = TA_OTAG;
759fcf3ce44SJohn Forte 		break;
760fcf3ce44SJohn Forte 	case FCP_QTYPE_ACA_Q_TAG:
761fcf3ce44SJohn Forte 		pkt->task = TA_ACA;
762fcf3ce44SJohn Forte 		break;
763fcf3ce44SJohn Forte 	case FCP_QTYPE_UNTAGGED:
764fcf3ce44SJohn Forte 		pkt->task = TA_UNTAGGED;
765fcf3ce44SJohn Forte 		break;
766fcf3ce44SJohn Forte 	default:
767fcf3ce44SJohn Forte 		break;
768fcf3ce44SJohn Forte 	}
769fcf3ce44SJohn Forte 
770fcf3ce44SJohn Forte 	if (fcp->fcp_data_len == 0) {
771*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
772fcf3ce44SJohn Forte 		pha->xioctl->IOControlRequests++;
773fcf3ce44SJohn Forte 		return;
774fcf3ce44SJohn Forte 	}
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 	/* Set transfer direction. */
777fcf3ce44SJohn Forte 	if (fcp->fcp_cntl.cntl_write_data) {
778fcf3ce44SJohn Forte 		pkt->control_flags = CF_WR;
779fcf3ce44SJohn Forte 		pha->xioctl->IOOutputRequests++;
780fcf3ce44SJohn Forte 		pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
781fcf3ce44SJohn Forte 	} else if (fcp->fcp_cntl.cntl_read_data) {
782fcf3ce44SJohn Forte 		pkt->control_flags = CF_RD;
783fcf3ce44SJohn Forte 		pha->xioctl->IOInputRequests++;
784fcf3ce44SJohn Forte 		pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
785fcf3ce44SJohn Forte 	}
786fcf3ce44SJohn Forte 
787fcf3ce44SJohn Forte 	/* Set data segment count. */
788fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
789*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
790fcf3ce44SJohn Forte 
791fcf3ce44SJohn Forte 	/* Load total byte count. */
792*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->total_byte_count,
793fcf3ce44SJohn Forte 	    fcp->fcp_data_len);
794fcf3ce44SJohn Forte 
795fcf3ce44SJohn Forte 	/* Load command data segment. */
796*4c3888b8SHans Rosenfeld 	ptr32 = (uint32_t *)&pkt->dseg;
797fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_data_cookie;
798*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
799*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
800*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
801fcf3ce44SJohn Forte 	seg_cnt--;
802fcf3ce44SJohn Forte 	cp++;
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 	/*
805fcf3ce44SJohn Forte 	 * Build continuation packets.
806fcf3ce44SJohn Forte 	 */
807fcf3ce44SJohn Forte 	if (seg_cnt) {
808*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(pha, req_q, cp, seg_cnt, B_TRUE);
809fcf3ce44SJohn Forte 	}
810fcf3ce44SJohn Forte 
811*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
812fcf3ce44SJohn Forte }
813fcf3ce44SJohn Forte 
814f885d00fSDaniel Beauregard /*
815f885d00fSDaniel Beauregard  * ql_cmd_24xx_type_6_iocb
816f885d00fSDaniel Beauregard  *	Setup of ISP24xx command type 6 IOCB.
817f885d00fSDaniel Beauregard  *
818f885d00fSDaniel Beauregard  * Input:
819f885d00fSDaniel Beauregard  *	ha:	adapter state pointer.
820*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
821f885d00fSDaniel Beauregard  *	sp:	srb structure pointer.
822f885d00fSDaniel Beauregard  *	arg:	request queue packet.
823f885d00fSDaniel Beauregard  *
824f885d00fSDaniel Beauregard  * Context:
825f885d00fSDaniel Beauregard  *	Interrupt or Kernel context, no mailbox commands allowed.
826f885d00fSDaniel Beauregard  */
827f885d00fSDaniel Beauregard static void
ql_cmd_24xx_type_6_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)828*4c3888b8SHans Rosenfeld ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
829*4c3888b8SHans Rosenfeld     ql_srb_t *sp, void *arg)
830f885d00fSDaniel Beauregard {
831f885d00fSDaniel Beauregard 	uint64_t		addr;
832f885d00fSDaniel Beauregard 	ddi_dma_cookie_t	*cp;
833f885d00fSDaniel Beauregard 	uint32_t		*ptr32;
834f885d00fSDaniel Beauregard 	uint16_t		seg_cnt;
835f885d00fSDaniel Beauregard 	fcp_cmd_t		*fcp = sp->fcp;
836f885d00fSDaniel Beauregard 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
837f885d00fSDaniel Beauregard 	cmd6_24xx_entry_t	*pkt = arg;
838f885d00fSDaniel Beauregard 	ql_adapter_state_t	*pha = ha->pha;
839f885d00fSDaniel Beauregard 	dma_mem_t		*cmem = &sp->sg_dma;
840f885d00fSDaniel Beauregard 	cmd6_2400_dma_t		*cdma = cmem->bp;
841*4c3888b8SHans Rosenfeld 	fcp_ent_addr_t		*fcp_ent_addr;
842f885d00fSDaniel Beauregard 
843*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
844f885d00fSDaniel Beauregard 
845f885d00fSDaniel Beauregard 	pkt->entry_type = IOCB_CMD_TYPE_6;
846f885d00fSDaniel Beauregard 
847f885d00fSDaniel Beauregard 	bzero(cdma, sizeof (cmd6_2400_dma_t));
848f885d00fSDaniel Beauregard 
849f885d00fSDaniel Beauregard 	/* Set LUN number */
850*4c3888b8SHans Rosenfeld 	fcp_ent_addr = (fcp_ent_addr_t *)&sp->lun_queue->lun_addr;
851*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[2] = cdma->cmd.fcp_lun[2] =
852*4c3888b8SHans Rosenfeld 	    lobyte(fcp_ent_addr->ent_addr_0);
853*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[3] = cdma->cmd.fcp_lun[3] =
854*4c3888b8SHans Rosenfeld 	    hibyte(fcp_ent_addr->ent_addr_0);
855*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[0] = cdma->cmd.fcp_lun[0] =
856*4c3888b8SHans Rosenfeld 	    lobyte(fcp_ent_addr->ent_addr_1);
857*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[1] = cdma->cmd.fcp_lun[1] =
858*4c3888b8SHans Rosenfeld 	    hibyte(fcp_ent_addr->ent_addr_1);
859*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[6] = cdma->cmd.fcp_lun[6] =
860*4c3888b8SHans Rosenfeld 	    lobyte(fcp_ent_addr->ent_addr_2);
861*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[7] = cdma->cmd.fcp_lun[7] =
862*4c3888b8SHans Rosenfeld 	    hibyte(fcp_ent_addr->ent_addr_2);
863*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[4] = cdma->cmd.fcp_lun[4] =
864*4c3888b8SHans Rosenfeld 	    lobyte(fcp_ent_addr->ent_addr_3);
865*4c3888b8SHans Rosenfeld 	pkt->fcp_lun[5] = cdma->cmd.fcp_lun[5] =
866*4c3888b8SHans Rosenfeld 	    hibyte(fcp_ent_addr->ent_addr_3);
867f885d00fSDaniel Beauregard 
868f885d00fSDaniel Beauregard 	/* Set N_port handle */
869*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
870f885d00fSDaniel Beauregard 
871f885d00fSDaniel Beauregard 	/* Set target ID */
872f885d00fSDaniel Beauregard 	pkt->target_id[0] = tq->d_id.b.al_pa;
873f885d00fSDaniel Beauregard 	pkt->target_id[1] = tq->d_id.b.area;
874f885d00fSDaniel Beauregard 	pkt->target_id[2] = tq->d_id.b.domain;
875f885d00fSDaniel Beauregard 
876f885d00fSDaniel Beauregard 	pkt->vp_index = ha->vp_index;
877f885d00fSDaniel Beauregard 
878f885d00fSDaniel Beauregard 	/* Set ISP command timeout. */
879f885d00fSDaniel Beauregard 	if (sp->isp_timeout < 0x1999) {
880*4c3888b8SHans Rosenfeld 		ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
881f885d00fSDaniel Beauregard 		    sp->isp_timeout);
882f885d00fSDaniel Beauregard 	}
883f885d00fSDaniel Beauregard 
884f885d00fSDaniel Beauregard 	/* Load SCSI CDB */
885f885d00fSDaniel Beauregard 	ddi_rep_put8(cmem->acc_handle, fcp->fcp_cdb, cdma->cmd.scsi_cdb,
886f885d00fSDaniel Beauregard 	    MAX_CMDSZ, DDI_DEV_AUTOINCR);
887f885d00fSDaniel Beauregard 
888f885d00fSDaniel Beauregard 	/*
889f885d00fSDaniel Beauregard 	 * Set tag queue control flags
890f885d00fSDaniel Beauregard 	 * Note:
891f885d00fSDaniel Beauregard 	 *	Cannot copy fcp->fcp_cntl.cntl_qtype directly,
892f885d00fSDaniel Beauregard 	 *	problem with x86 in 32bit kernel mode
893f885d00fSDaniel Beauregard 	 */
894f885d00fSDaniel Beauregard 	switch (fcp->fcp_cntl.cntl_qtype) {
895f885d00fSDaniel Beauregard 	case FCP_QTYPE_SIMPLE:
896f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_STAG;
897f885d00fSDaniel Beauregard 		break;
898f885d00fSDaniel Beauregard 	case FCP_QTYPE_HEAD_OF_Q:
899f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_HTAG;
900f885d00fSDaniel Beauregard 		break;
901f885d00fSDaniel Beauregard 	case FCP_QTYPE_ORDERED:
902f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_OTAG;
903f885d00fSDaniel Beauregard 		break;
904f885d00fSDaniel Beauregard 	case FCP_QTYPE_ACA_Q_TAG:
905f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_ACA;
906f885d00fSDaniel Beauregard 		break;
907f885d00fSDaniel Beauregard 	case FCP_QTYPE_UNTAGGED:
908f885d00fSDaniel Beauregard 		cdma->cmd.task = TA_UNTAGGED;
909f885d00fSDaniel Beauregard 		break;
910f885d00fSDaniel Beauregard 	default:
911f885d00fSDaniel Beauregard 		break;
912f885d00fSDaniel Beauregard 	}
913f885d00fSDaniel Beauregard 
914f885d00fSDaniel Beauregard 	/*
915f885d00fSDaniel Beauregard 	 * FCP_CMND Payload Data Segment
916f885d00fSDaniel Beauregard 	 */
917f885d00fSDaniel Beauregard 	cp = cmem->cookies;
918*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->cmnd_length,
919f885d00fSDaniel Beauregard 	    sizeof (fcp_cmnd_t));
920*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->cmnd_address[0],
921f885d00fSDaniel Beauregard 	    cp->dmac_address);
922*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->cmnd_address[1],
923f885d00fSDaniel Beauregard 	    cp->dmac_notused);
924f885d00fSDaniel Beauregard 
925f885d00fSDaniel Beauregard 	/* Set transfer direction. */
926f885d00fSDaniel Beauregard 	if (fcp->fcp_cntl.cntl_write_data) {
927f885d00fSDaniel Beauregard 		pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_WR);
928f885d00fSDaniel Beauregard 		cdma->cmd.control_flags = CF_WR;
929f885d00fSDaniel Beauregard 		pha->xioctl->IOOutputRequests++;
930f885d00fSDaniel Beauregard 		pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
931f885d00fSDaniel Beauregard 	} else if (fcp->fcp_cntl.cntl_read_data) {
932f885d00fSDaniel Beauregard 		pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_RD);
933f885d00fSDaniel Beauregard 		cdma->cmd.control_flags = CF_RD;
934f885d00fSDaniel Beauregard 		pha->xioctl->IOInputRequests++;
935f885d00fSDaniel Beauregard 		pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
936f885d00fSDaniel Beauregard 	}
937f885d00fSDaniel Beauregard 
938f885d00fSDaniel Beauregard 	/*
939f885d00fSDaniel Beauregard 	 * FCP_DATA Data Segment Descriptor.
940f885d00fSDaniel Beauregard 	 */
941f885d00fSDaniel Beauregard 	addr = cp->dmac_laddress + sizeof (fcp_cmnd_t);
942*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.address[0], LSD(addr));
943*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.address[1], MSD(addr));
944f885d00fSDaniel Beauregard 
945f885d00fSDaniel Beauregard 	/* Set data segment count. */
946f885d00fSDaniel Beauregard 	seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
947*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
948*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.length,
949f885d00fSDaniel Beauregard 	    seg_cnt * 12 + 12);
950f885d00fSDaniel Beauregard 
951f885d00fSDaniel Beauregard 	/* Load total byte count. */
952*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->total_byte_count,
953f885d00fSDaniel Beauregard 	    fcp->fcp_data_len);
954f885d00fSDaniel Beauregard 	ddi_put32(cmem->acc_handle, &cdma->cmd.dl, (uint32_t)fcp->fcp_data_len);
955f885d00fSDaniel Beauregard 	ql_chg_endian((uint8_t *)&cdma->cmd.dl, 4);
956f885d00fSDaniel Beauregard 
957f885d00fSDaniel Beauregard 	/* Load command data segments. */
958f885d00fSDaniel Beauregard 	ptr32 = (uint32_t *)cdma->cookie_list;
959f885d00fSDaniel Beauregard 	cp = sp->pkt->pkt_data_cookie;
960f885d00fSDaniel Beauregard 	while (seg_cnt--) {
961f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_address);
962f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_notused);
963f885d00fSDaniel Beauregard 		ddi_put32(cmem->acc_handle, ptr32++, (uint32_t)cp->dmac_size);
964f885d00fSDaniel Beauregard 		cp++;
965f885d00fSDaniel Beauregard 	}
966f885d00fSDaniel Beauregard 
967f885d00fSDaniel Beauregard 	/* Sync DMA buffer. */
968f885d00fSDaniel Beauregard 	(void) ddi_dma_sync(cmem->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
969f885d00fSDaniel Beauregard 
970*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
971f885d00fSDaniel Beauregard }
972f885d00fSDaniel Beauregard 
973fcf3ce44SJohn Forte /*
974fcf3ce44SJohn Forte  * ql_marker
975fcf3ce44SJohn Forte  *	Function issues marker IOCB.
976fcf3ce44SJohn Forte  *
977fcf3ce44SJohn Forte  * Input:
978fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
979fcf3ce44SJohn Forte  *	loop_id:	device loop ID
980*4c3888b8SHans Rosenfeld  *	lq:		LUN queue pointer.
981fcf3ce44SJohn Forte  *	type:		marker modifier
982fcf3ce44SJohn Forte  *
983fcf3ce44SJohn Forte  * Returns:
984fcf3ce44SJohn Forte  *	ql local function return status code.
985fcf3ce44SJohn Forte  *
986fcf3ce44SJohn Forte  * Context:
987fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
988fcf3ce44SJohn Forte  */
989fcf3ce44SJohn Forte int
ql_marker(ql_adapter_state_t * ha,uint16_t loop_id,ql_lun_t * lq,uint8_t type)990*4c3888b8SHans Rosenfeld ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, ql_lun_t *lq,
991fcf3ce44SJohn Forte     uint8_t type)
992fcf3ce44SJohn Forte {
993fcf3ce44SJohn Forte 	mrk_entry_t	*pkt;
994fcf3ce44SJohn Forte 	int		rval;
995*4c3888b8SHans Rosenfeld 	ql_request_q_t	*req_q = ha->req_q[0];
996*4c3888b8SHans Rosenfeld 	fcp_ent_addr_t	*fcp_ent_addr;
997fcf3ce44SJohn Forte 
998*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
999fcf3ce44SJohn Forte 
1000*4c3888b8SHans Rosenfeld 	rval = ql_req_pkt(ha, req_q, (request_t **)&pkt);
1001fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
1002fcf3ce44SJohn Forte 		pkt->entry_type = MARKER_TYPE;
1003fcf3ce44SJohn Forte 
1004*4c3888b8SHans Rosenfeld 		if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
1005fcf3ce44SJohn Forte 			marker_24xx_entry_t	*pkt24 =
1006fcf3ce44SJohn Forte 			    (marker_24xx_entry_t *)pkt;
1007fcf3ce44SJohn Forte 
1008fcf3ce44SJohn Forte 			pkt24->modifier = type;
1009fcf3ce44SJohn Forte 
1010fcf3ce44SJohn Forte 			/* Set LUN number */
1011*4c3888b8SHans Rosenfeld 			if (lq) {
1012*4c3888b8SHans Rosenfeld 				fcp_ent_addr = (fcp_ent_addr_t *)&lq->lun_addr;
1013*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[2] =
1014*4c3888b8SHans Rosenfeld 				    lobyte(fcp_ent_addr->ent_addr_0);
1015*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[3] =
1016*4c3888b8SHans Rosenfeld 				    hibyte(fcp_ent_addr->ent_addr_0);
1017*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[0] =
1018*4c3888b8SHans Rosenfeld 				    lobyte(fcp_ent_addr->ent_addr_1);
1019*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[1] =
1020*4c3888b8SHans Rosenfeld 				    hibyte(fcp_ent_addr->ent_addr_1);
1021*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[6] =
1022*4c3888b8SHans Rosenfeld 				    lobyte(fcp_ent_addr->ent_addr_2);
1023*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[7] =
1024*4c3888b8SHans Rosenfeld 				    hibyte(fcp_ent_addr->ent_addr_2);
1025*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[4] =
1026*4c3888b8SHans Rosenfeld 				    lobyte(fcp_ent_addr->ent_addr_3);
1027*4c3888b8SHans Rosenfeld 				pkt24->fcp_lun[5] =
1028*4c3888b8SHans Rosenfeld 				    hibyte(fcp_ent_addr->ent_addr_3);
1029*4c3888b8SHans Rosenfeld 			}
1030fcf3ce44SJohn Forte 
1031fcf3ce44SJohn Forte 			pkt24->vp_index = ha->vp_index;
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 			/* Set N_port handle */
1034*4c3888b8SHans Rosenfeld 			ddi_put16(req_q->req_ring.acc_handle,
1035fcf3ce44SJohn Forte 			    &pkt24->n_port_hdl, loop_id);
1036fcf3ce44SJohn Forte 
1037fcf3ce44SJohn Forte 		} else {
1038fcf3ce44SJohn Forte 			pkt->modifier = type;
1039fcf3ce44SJohn Forte 
1040*4c3888b8SHans Rosenfeld 			if (lq) {
1041*4c3888b8SHans Rosenfeld 				pkt->lun_l = LSB(lq->lun_no);
1042*4c3888b8SHans Rosenfeld 				pkt->lun_h = MSB(lq->lun_no);
1043*4c3888b8SHans Rosenfeld 			}
1044fcf3ce44SJohn Forte 
1045fcf3ce44SJohn Forte 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1046fcf3ce44SJohn Forte 				pkt->target_l = LSB(loop_id);
1047fcf3ce44SJohn Forte 				pkt->target_h = MSB(loop_id);
1048fcf3ce44SJohn Forte 			} else {
1049fcf3ce44SJohn Forte 				pkt->target_h = LSB(loop_id);
1050fcf3ce44SJohn Forte 			}
1051fcf3ce44SJohn Forte 		}
1052fcf3ce44SJohn Forte 
1053fcf3ce44SJohn Forte 		/* Issue command to ISP */
1054*4c3888b8SHans Rosenfeld 		ql_isp_cmd(ha, req_q);
1055fcf3ce44SJohn Forte 	}
1056fcf3ce44SJohn Forte 
1057fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
1058fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
1059fcf3ce44SJohn Forte 	} else {
1060fcf3ce44SJohn Forte 		/*EMPTY*/
1061*4c3888b8SHans Rosenfeld 		QL_PRINT_3(ha, "done\n");
1062fcf3ce44SJohn Forte 	}
1063fcf3ce44SJohn Forte 	return (rval);
1064fcf3ce44SJohn Forte }
1065fcf3ce44SJohn Forte 
1066fcf3ce44SJohn Forte /*
1067fcf3ce44SJohn Forte  * ql_ms_iocb
1068fcf3ce44SJohn Forte  *	Setup of name/management server IOCB.
1069fcf3ce44SJohn Forte  *
1070fcf3ce44SJohn Forte  * Input:
1071*4c3888b8SHans Rosenfeld  *	ha:	adapter state pointer.
1072*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
1073*4c3888b8SHans Rosenfeld  *	sp:	srb structure pointer.
1074*4c3888b8SHans Rosenfeld  *	arg:	request queue packet.
1075fcf3ce44SJohn Forte  *
1076fcf3ce44SJohn Forte  * Context:
1077fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1078fcf3ce44SJohn Forte  */
1079fcf3ce44SJohn Forte void
ql_ms_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)1080*4c3888b8SHans Rosenfeld ql_ms_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1081*4c3888b8SHans Rosenfeld     void *arg)
1082fcf3ce44SJohn Forte {
1083fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
1084fcf3ce44SJohn Forte 	uint32_t		*ptr32;
1085fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
1086fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
1087fcf3ce44SJohn Forte 	ms_entry_t		*pkt = arg;
1088fcf3ce44SJohn Forte 
1089*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1090fcf3ce44SJohn Forte 	QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
1091fcf3ce44SJohn Forte 	/*
1092fcf3ce44SJohn Forte 	 * Build command packet.
1093fcf3ce44SJohn Forte 	 */
1094fcf3ce44SJohn Forte 	pkt->entry_type = MS_TYPE;
1095fcf3ce44SJohn Forte 
1096fcf3ce44SJohn Forte 	/* Set loop ID */
1097fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1098fcf3ce44SJohn Forte 		pkt->loop_id_l = LSB(tq->loop_id);
1099fcf3ce44SJohn Forte 		pkt->loop_id_h = MSB(tq->loop_id);
1100fcf3ce44SJohn Forte 	} else {
1101fcf3ce44SJohn Forte 		pkt->loop_id_h = LSB(tq->loop_id);
1102fcf3ce44SJohn Forte 	}
1103fcf3ce44SJohn Forte 
1104fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1105*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
1106fcf3ce44SJohn Forte 
1107fcf3ce44SJohn Forte 	/* Set cmd data segment count. */
1108fcf3ce44SJohn Forte 	pkt->cmd_dseg_count_l = 1;
1109fcf3ce44SJohn Forte 
1110fcf3ce44SJohn Forte 	/* Set total data segment count */
1111fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1);
1112*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->total_dseg_count, seg_cnt);
1113fcf3ce44SJohn Forte 
1114fcf3ce44SJohn Forte 	/* Load ct cmd byte count. */
1115*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->cmd_byte_count,
1116fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1117fcf3ce44SJohn Forte 
1118fcf3ce44SJohn Forte 	/* Load ct rsp byte count. */
1119*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->resp_byte_count,
1120fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_rsplen);
1121fcf3ce44SJohn Forte 
1122fcf3ce44SJohn Forte 	/* Load MS command data segments. */
1123*4c3888b8SHans Rosenfeld 	ptr32 = (uint32_t *)&pkt->dseg;
1124fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
1125*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1126*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1127*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
1128fcf3ce44SJohn Forte 	seg_cnt--;
1129fcf3ce44SJohn Forte 
1130fcf3ce44SJohn Forte 	/* Load MS response entry data segments. */
1131fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_resp_cookie;
1132*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1133*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1134*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1135fcf3ce44SJohn Forte 	seg_cnt--;
1136fcf3ce44SJohn Forte 	cp++;
1137fcf3ce44SJohn Forte 
1138fcf3ce44SJohn Forte 	/*
1139fcf3ce44SJohn Forte 	 * Build continuation packets.
1140fcf3ce44SJohn Forte 	 */
1141fcf3ce44SJohn Forte 	if (seg_cnt) {
1142*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(ha, req_q, cp, seg_cnt, B_TRUE);
1143fcf3ce44SJohn Forte 	}
1144fcf3ce44SJohn Forte 
1145*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1146fcf3ce44SJohn Forte }
1147fcf3ce44SJohn Forte 
1148fcf3ce44SJohn Forte /*
1149fcf3ce44SJohn Forte  * ql_ms_24xx_iocb
1150fcf3ce44SJohn Forte  *	Setup of name/management server IOCB.
1151fcf3ce44SJohn Forte  *
1152fcf3ce44SJohn Forte  * Input:
1153fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1154*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
1155fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
1156fcf3ce44SJohn Forte  *	arg:	request queue packet.
1157fcf3ce44SJohn Forte  *
1158fcf3ce44SJohn Forte  * Context:
1159fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1160fcf3ce44SJohn Forte  */
1161fcf3ce44SJohn Forte void
ql_ms_24xx_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)1162*4c3888b8SHans Rosenfeld ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1163*4c3888b8SHans Rosenfeld     void *arg)
1164fcf3ce44SJohn Forte {
1165fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
1166fcf3ce44SJohn Forte 	uint32_t		*ptr32;
1167fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
1168fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
1169fcf3ce44SJohn Forte 	ct_passthru_entry_t	*pkt = arg;
1170fcf3ce44SJohn Forte 	ql_adapter_state_t	*pha = ha->pha;
1171fcf3ce44SJohn Forte 
1172*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1173fcf3ce44SJohn Forte 	QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
1174fcf3ce44SJohn Forte 	/*
1175fcf3ce44SJohn Forte 	 * Build command packet.
1176fcf3ce44SJohn Forte 	 */
1177fcf3ce44SJohn Forte 	pkt->entry_type = CT_PASSTHRU_TYPE;
1178fcf3ce44SJohn Forte 
1179fcf3ce44SJohn Forte 	/* Set loop ID */
1180*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
1181fcf3ce44SJohn Forte 
1182fcf3ce44SJohn Forte 	pkt->vp_index = ha->vp_index;
1183fcf3ce44SJohn Forte 
1184fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1185fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
1186*4c3888b8SHans Rosenfeld 		ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
1187fcf3ce44SJohn Forte 		    sp->isp_timeout);
1188fcf3ce44SJohn Forte 	}
1189fcf3ce44SJohn Forte 
1190fcf3ce44SJohn Forte 	/* Set cmd/response data segment counts. */
1191*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->cmd_dseg_count, 1);
1192fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt;
1193*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->resp_dseg_count, seg_cnt);
1194fcf3ce44SJohn Forte 
1195fcf3ce44SJohn Forte 	/* Load ct cmd byte count. */
1196*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->cmd_byte_count,
1197fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1198fcf3ce44SJohn Forte 
1199fcf3ce44SJohn Forte 	/* Load ct rsp byte count. */
1200*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->resp_byte_count,
1201fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_rsplen);
1202fcf3ce44SJohn Forte 
1203fcf3ce44SJohn Forte 	/* Load MS command entry data segments. */
1204*4c3888b8SHans Rosenfeld 	ptr32 = (uint32_t *)&pkt->dseg;
1205fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
1206*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1207*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1208*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
1209fcf3ce44SJohn Forte 
1210fcf3ce44SJohn Forte 	/* Load MS response entry data segments. */
1211fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_resp_cookie;
1212*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1213*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1214*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1215fcf3ce44SJohn Forte 	seg_cnt--;
1216fcf3ce44SJohn Forte 	cp++;
1217fcf3ce44SJohn Forte 
1218fcf3ce44SJohn Forte 	/*
1219fcf3ce44SJohn Forte 	 * Build continuation packets.
1220fcf3ce44SJohn Forte 	 */
1221fcf3ce44SJohn Forte 	if (seg_cnt) {
1222*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(pha, req_q, cp, seg_cnt, B_TRUE);
1223fcf3ce44SJohn Forte 	}
1224fcf3ce44SJohn Forte 
1225*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1226fcf3ce44SJohn Forte }
1227fcf3ce44SJohn Forte 
1228fcf3ce44SJohn Forte /*
1229fcf3ce44SJohn Forte  * ql_ip_iocb
1230fcf3ce44SJohn Forte  *	Setup of IP IOCB.
1231fcf3ce44SJohn Forte  *
1232fcf3ce44SJohn Forte  * Input:
1233fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1234*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
1235fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
1236fcf3ce44SJohn Forte  *	arg:	request queue packet.
1237fcf3ce44SJohn Forte  *
1238fcf3ce44SJohn Forte  * Context:
1239fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1240fcf3ce44SJohn Forte  */
1241fcf3ce44SJohn Forte void
ql_ip_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)1242*4c3888b8SHans Rosenfeld ql_ip_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1243*4c3888b8SHans Rosenfeld     void *arg)
1244fcf3ce44SJohn Forte {
1245fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
1246fcf3ce44SJohn Forte 	uint32_t		*ptr32, cnt;
1247fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
1248fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
1249fcf3ce44SJohn Forte 	ip_entry_t		*pkt = arg;
1250*4c3888b8SHans Rosenfeld 	ip_a64_entry_t		*pkt64 = arg;
1251fcf3ce44SJohn Forte 
1252*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1253fcf3ce44SJohn Forte 
1254fcf3ce44SJohn Forte 	/* Set loop ID */
1255fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1256fcf3ce44SJohn Forte 		pkt->loop_id_l = LSB(tq->loop_id);
1257fcf3ce44SJohn Forte 		pkt->loop_id_h = MSB(tq->loop_id);
1258fcf3ce44SJohn Forte 	} else {
1259fcf3ce44SJohn Forte 		pkt->loop_id_h = LSB(tq->loop_id);
1260fcf3ce44SJohn Forte 	}
1261fcf3ce44SJohn Forte 
1262fcf3ce44SJohn Forte 	/* Set control flags */
1263fcf3ce44SJohn Forte 	pkt->control_flags_l = BIT_6;
1264fcf3ce44SJohn Forte 	if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) {
1265fcf3ce44SJohn Forte 		pkt->control_flags_h = BIT_7;
1266fcf3ce44SJohn Forte 	}
1267fcf3ce44SJohn Forte 
1268fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1269*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
1270fcf3ce44SJohn Forte 
1271fcf3ce44SJohn Forte 	/* Set data segment count. */
1272fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1273fcf3ce44SJohn Forte 	/* Load total byte count. */
1274*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
1275fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1276*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
1277fcf3ce44SJohn Forte 
1278fcf3ce44SJohn Forte 	/*
1279fcf3ce44SJohn Forte 	 * Build command packet.
1280fcf3ce44SJohn Forte 	 */
1281*4c3888b8SHans Rosenfeld 
1282*4c3888b8SHans Rosenfeld 	/* Load command entry data segments. */
1283*4c3888b8SHans Rosenfeld 	cp = sp->pkt->pkt_cmd_cookie;
1284*4c3888b8SHans Rosenfeld 
1285fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1286*4c3888b8SHans Rosenfeld 		pkt64->entry_type = IP_A64_TYPE;
1287fcf3ce44SJohn Forte 		cnt = IP_A64_DATA_SEGMENTS;
1288*4c3888b8SHans Rosenfeld 		ptr32 = (uint32_t *)&pkt64->dseg;
1289*4c3888b8SHans Rosenfeld 		while (cnt && seg_cnt) {
1290*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1291*4c3888b8SHans Rosenfeld 			    cp->dmac_address);
1292*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1293*4c3888b8SHans Rosenfeld 			    cp->dmac_notused);
1294*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1295*4c3888b8SHans Rosenfeld 			    (uint32_t)cp->dmac_size);
1296*4c3888b8SHans Rosenfeld 			seg_cnt--;
1297*4c3888b8SHans Rosenfeld 			cnt--;
1298*4c3888b8SHans Rosenfeld 			cp++;
1299*4c3888b8SHans Rosenfeld 		}
1300fcf3ce44SJohn Forte 	} else {
1301fcf3ce44SJohn Forte 		pkt->entry_type = IP_TYPE;
1302fcf3ce44SJohn Forte 		cnt = IP_DATA_SEGMENTS;
1303*4c3888b8SHans Rosenfeld 		ptr32 = (uint32_t *)&pkt->dseg;
1304*4c3888b8SHans Rosenfeld 		while (cnt && seg_cnt) {
1305*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1306*4c3888b8SHans Rosenfeld 			    cp->dmac_address);
1307*4c3888b8SHans Rosenfeld 			ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1308*4c3888b8SHans Rosenfeld 			    (uint32_t)cp->dmac_size);
1309*4c3888b8SHans Rosenfeld 			seg_cnt--;
1310*4c3888b8SHans Rosenfeld 			cnt--;
1311*4c3888b8SHans Rosenfeld 			cp++;
1312fcf3ce44SJohn Forte 		}
1313fcf3ce44SJohn Forte 	}
1314fcf3ce44SJohn Forte 
1315fcf3ce44SJohn Forte 	/*
1316fcf3ce44SJohn Forte 	 * Build continuation packets.
1317fcf3ce44SJohn Forte 	 */
1318fcf3ce44SJohn Forte 	if (seg_cnt) {
1319*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(ha, req_q, cp, seg_cnt,
1320fcf3ce44SJohn Forte 		    (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
1321fcf3ce44SJohn Forte 	}
1322fcf3ce44SJohn Forte 
1323*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1324fcf3ce44SJohn Forte }
1325fcf3ce44SJohn Forte 
1326fcf3ce44SJohn Forte /*
1327fcf3ce44SJohn Forte  * ql_ip_24xx_iocb
1328fcf3ce44SJohn Forte  *	Setup of IP IOCB for ISP24xx.
1329fcf3ce44SJohn Forte  *
1330fcf3ce44SJohn Forte  * Input:
1331fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
1332*4c3888b8SHans Rosenfeld  *	req_q:	request queue structure pointer.
1333fcf3ce44SJohn Forte  *	sp:	srb structure pointer.
1334fcf3ce44SJohn Forte  *	arg:	request queue packet.
1335fcf3ce44SJohn Forte  *
1336fcf3ce44SJohn Forte  * Context:
1337fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1338fcf3ce44SJohn Forte  */
1339fcf3ce44SJohn Forte void
ql_ip_24xx_iocb(ql_adapter_state_t * ha,ql_request_q_t * req_q,ql_srb_t * sp,void * arg)1340*4c3888b8SHans Rosenfeld ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1341*4c3888b8SHans Rosenfeld     void *arg)
1342fcf3ce44SJohn Forte {
1343fcf3ce44SJohn Forte 	ddi_dma_cookie_t	*cp;
1344fcf3ce44SJohn Forte 	uint32_t		*ptr32;
1345fcf3ce44SJohn Forte 	uint16_t		seg_cnt;
1346fcf3ce44SJohn Forte 	ql_tgt_t		*tq = sp->lun_queue->target_queue;
1347fcf3ce44SJohn Forte 	ip_cmd_entry_t		*pkt = arg;
1348fcf3ce44SJohn Forte 
1349fcf3ce44SJohn Forte 	pkt->entry_type = IP_CMD_TYPE;
1350fcf3ce44SJohn Forte 
1351*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1352fcf3ce44SJohn Forte 
1353fcf3ce44SJohn Forte 	/* Set N_port handle */
1354*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->hdl_status, tq->loop_id);
1355fcf3ce44SJohn Forte 
1356fcf3ce44SJohn Forte 	/* Set ISP command timeout. */
1357fcf3ce44SJohn Forte 	if (sp->isp_timeout < 0x1999) {
1358*4c3888b8SHans Rosenfeld 		ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout_hdl,
1359fcf3ce44SJohn Forte 		    sp->isp_timeout);
1360fcf3ce44SJohn Forte 	}
1361fcf3ce44SJohn Forte 
1362fcf3ce44SJohn Forte 	/* Set data segment count. */
1363fcf3ce44SJohn Forte 	seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1364fcf3ce44SJohn Forte 	/* Load total byte count. */
1365*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
1366fcf3ce44SJohn Forte 	    (uint32_t)sp->pkt->pkt_cmdlen);
1367*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
1368fcf3ce44SJohn Forte 
1369fcf3ce44SJohn Forte 	/* Set control flags */
1370*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->control_flags,
1371fcf3ce44SJohn Forte 	    (uint16_t)(BIT_0));
1372fcf3ce44SJohn Forte 
1373fcf3ce44SJohn Forte 	/* Set frame header control flags */
1374*4c3888b8SHans Rosenfeld 	ddi_put16(req_q->req_ring.acc_handle, &pkt->frame_hdr_cntrl_flgs,
1375fcf3ce44SJohn Forte 	    (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ));
1376fcf3ce44SJohn Forte 
1377fcf3ce44SJohn Forte 	/* Load command data segment. */
1378*4c3888b8SHans Rosenfeld 	ptr32 = (uint32_t *)&pkt->dseg;
1379fcf3ce44SJohn Forte 	cp = sp->pkt->pkt_cmd_cookie;
1380*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1381*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1382*4c3888b8SHans Rosenfeld 	ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1383fcf3ce44SJohn Forte 	seg_cnt--;
1384fcf3ce44SJohn Forte 	cp++;
1385fcf3ce44SJohn Forte 
1386fcf3ce44SJohn Forte 	/*
1387fcf3ce44SJohn Forte 	 * Build continuation packets.
1388fcf3ce44SJohn Forte 	 */
1389fcf3ce44SJohn Forte 	if (seg_cnt) {
1390*4c3888b8SHans Rosenfeld 		ql_continuation_iocb(ha, req_q, cp, seg_cnt, B_TRUE);
1391fcf3ce44SJohn Forte 	}
1392fcf3ce44SJohn Forte 
1393*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1394fcf3ce44SJohn Forte }
1395fcf3ce44SJohn Forte 
1396fcf3ce44SJohn Forte /*
1397fcf3ce44SJohn Forte  * ql_isp_rcvbuf
1398fcf3ce44SJohn Forte  *	Locates free buffers and places it on the receive buffer queue.
1399fcf3ce44SJohn Forte  *
1400fcf3ce44SJohn Forte  * Input:
1401fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1402fcf3ce44SJohn Forte  *
1403fcf3ce44SJohn Forte  * Context:
1404fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1405fcf3ce44SJohn Forte  */
1406fcf3ce44SJohn Forte void
ql_isp_rcvbuf(ql_adapter_state_t * ha)1407fcf3ce44SJohn Forte ql_isp_rcvbuf(ql_adapter_state_t *ha)
1408fcf3ce44SJohn Forte {
1409fcf3ce44SJohn Forte 	rcvbuf_t	*container;
141016dd44c2SDaniel Beauregard 	uint16_t	rcv_q_cnt;
1411fcf3ce44SJohn Forte 	uint16_t	index = 0;
1412fcf3ce44SJohn Forte 	uint16_t	index1 = 1;
1413fcf3ce44SJohn Forte 	int		debounce_count = QL_MAX_DEBOUNCE;
1414fcf3ce44SJohn Forte 	ql_srb_t	*sp;
1415fcf3ce44SJohn Forte 	fc_unsol_buf_t	*ubp;
1416fcf3ce44SJohn Forte 	int		ring_updated = FALSE;
1417fcf3ce44SJohn Forte 
1418*4c3888b8SHans Rosenfeld 	if (CFG_IST(ha, CFG_CTRL_24XX)) {
1419fcf3ce44SJohn Forte 		ql_isp24xx_rcvbuf(ha);
1420fcf3ce44SJohn Forte 		return;
1421fcf3ce44SJohn Forte 	}
1422fcf3ce44SJohn Forte 
1423*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1424fcf3ce44SJohn Forte 
1425fcf3ce44SJohn Forte 	/* Acquire adapter state lock. */
1426fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
1427fcf3ce44SJohn Forte 
1428fcf3ce44SJohn Forte 	/* Calculate number of free receive buffer entries. */
1429eb82ff87SDaniel Beauregard 	index = RD16_IO_REG(ha, mailbox_out[8]);
1430fcf3ce44SJohn Forte 	do {
1431eb82ff87SDaniel Beauregard 		index1 = RD16_IO_REG(ha, mailbox_out[8]);
1432fcf3ce44SJohn Forte 		if (index1 == index) {
1433fcf3ce44SJohn Forte 			break;
1434fcf3ce44SJohn Forte 		} else {
1435fcf3ce44SJohn Forte 			index = index1;
1436fcf3ce44SJohn Forte 		}
1437*4c3888b8SHans Rosenfeld 	} while (debounce_count--);
1438fcf3ce44SJohn Forte 
1439fcf3ce44SJohn Forte 	if (debounce_count < 0) {
1440fcf3ce44SJohn Forte 		/* This should never happen */
1441fcf3ce44SJohn Forte 		EL(ha, "max mb8 debounce retries exceeded\n");
1442fcf3ce44SJohn Forte 	}
1443fcf3ce44SJohn Forte 
1444fcf3ce44SJohn Forte 	rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ?
1445fcf3ce44SJohn Forte 	    index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT -
1446fcf3ce44SJohn Forte 	    (ha->rcvbuf_ring_index - index));
1447fcf3ce44SJohn Forte 
1448fcf3ce44SJohn Forte 	if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) {
1449fcf3ce44SJohn Forte 		rcv_q_cnt--;
1450fcf3ce44SJohn Forte 	}
1451fcf3ce44SJohn Forte 
1452fcf3ce44SJohn Forte 	/* Load all free buffers in ISP receive buffer ring. */
1453fcf3ce44SJohn Forte 	index = 0;
145416dd44c2SDaniel Beauregard 	while (rcv_q_cnt > (uint16_t)0 && index < QL_UB_LIMIT) {
1455fcf3ce44SJohn Forte 		/* Locate a buffer to give. */
1456fcf3ce44SJohn Forte 		QL_UB_LOCK(ha);
1457fcf3ce44SJohn Forte 		while (index < QL_UB_LIMIT) {
1458fcf3ce44SJohn Forte 			ubp = ha->ub_array[index];
1459fcf3ce44SJohn Forte 			if (ubp != NULL) {
1460fcf3ce44SJohn Forte 				sp = ubp->ub_fca_private;
1461fcf3ce44SJohn Forte 				if ((sp->ub_type == FC_TYPE_IS8802_SNAP) &&
1462fcf3ce44SJohn Forte 				    (ha->flags & IP_INITIALIZED) &&
1463fcf3ce44SJohn Forte 				    (sp->flags & SRB_UB_IN_FCA) &&
1464fcf3ce44SJohn Forte 				    (!(sp->flags & (SRB_UB_IN_ISP |
1465fcf3ce44SJohn Forte 				    SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1466fcf3ce44SJohn Forte 				    SRB_UB_ACQUIRED)))) {
1467fcf3ce44SJohn Forte 					sp->flags |= SRB_UB_IN_ISP;
1468fcf3ce44SJohn Forte 					break;
1469fcf3ce44SJohn Forte 				}
1470fcf3ce44SJohn Forte 			}
1471fcf3ce44SJohn Forte 			index++;
1472fcf3ce44SJohn Forte 		}
1473fcf3ce44SJohn Forte 
1474fcf3ce44SJohn Forte 		if (index < QL_UB_LIMIT) {
1475fcf3ce44SJohn Forte 			rcv_q_cnt--;
1476fcf3ce44SJohn Forte 			index++;
1477fcf3ce44SJohn Forte 			container = ha->rcvbuf_ring_ptr;
1478fcf3ce44SJohn Forte 
1479fcf3ce44SJohn Forte 			/*
1480fcf3ce44SJohn Forte 			 * Build container.
1481fcf3ce44SJohn Forte 			 */
1482*4c3888b8SHans Rosenfeld 			ddi_put32(ha->rcv_ring.acc_handle,
1483fcf3ce44SJohn Forte 			    (uint32_t *)(void *)&container->bufp[0],
1484fcf3ce44SJohn Forte 			    sp->ub_buffer.cookie.dmac_address);
1485fcf3ce44SJohn Forte 
1486*4c3888b8SHans Rosenfeld 			ddi_put32(ha->rcv_ring.acc_handle,
1487fcf3ce44SJohn Forte 			    (uint32_t *)(void *)&container->bufp[1],
1488fcf3ce44SJohn Forte 			    sp->ub_buffer.cookie.dmac_notused);
1489fcf3ce44SJohn Forte 
1490*4c3888b8SHans Rosenfeld 			ddi_put16(ha->rcv_ring.acc_handle, &container->handle,
1491fcf3ce44SJohn Forte 			    LSW(sp->handle));
1492fcf3ce44SJohn Forte 
1493fcf3ce44SJohn Forte 			ha->ub_outcnt++;
1494fcf3ce44SJohn Forte 
1495fcf3ce44SJohn Forte 			/* Adjust ring index. */
1496fcf3ce44SJohn Forte 			ha->rcvbuf_ring_index++;
1497fcf3ce44SJohn Forte 			if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) {
1498fcf3ce44SJohn Forte 				ha->rcvbuf_ring_index = 0;
1499*4c3888b8SHans Rosenfeld 				ha->rcvbuf_ring_ptr = ha->rcv_ring.bp;
1500fcf3ce44SJohn Forte 			} else {
1501fcf3ce44SJohn Forte 				ha->rcvbuf_ring_ptr++;
1502fcf3ce44SJohn Forte 			}
1503fcf3ce44SJohn Forte 
1504fcf3ce44SJohn Forte 			ring_updated = TRUE;
1505fcf3ce44SJohn Forte 		}
1506fcf3ce44SJohn Forte 		QL_UB_UNLOCK(ha);
1507fcf3ce44SJohn Forte 	}
1508fcf3ce44SJohn Forte 
1509fcf3ce44SJohn Forte 	if (ring_updated) {
1510fcf3ce44SJohn Forte 		/* Sync queue. */
1511*4c3888b8SHans Rosenfeld 		(void) ddi_dma_sync(ha->rcv_ring.dma_handle, 0,
1512*4c3888b8SHans Rosenfeld 		    (size_t)RCVBUF_QUEUE_SIZE, DDI_DMA_SYNC_FORDEV);
1513fcf3ce44SJohn Forte 
1514fcf3ce44SJohn Forte 		/* Set chip new ring index. */
1515eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, mailbox_in[8], ha->rcvbuf_ring_index);
1516fcf3ce44SJohn Forte 	}
1517fcf3ce44SJohn Forte 
1518fcf3ce44SJohn Forte 	/* Release adapter state lock. */
1519fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
1520fcf3ce44SJohn Forte 
1521*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1522fcf3ce44SJohn Forte }
1523fcf3ce44SJohn Forte 
1524fcf3ce44SJohn Forte /*
1525fcf3ce44SJohn Forte  * ql_isp24xx_rcvbuf
1526fcf3ce44SJohn Forte  *	Locates free buffers and send it to adapter.
1527fcf3ce44SJohn Forte  *
1528fcf3ce44SJohn Forte  * Input:
1529fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1530fcf3ce44SJohn Forte  *
1531fcf3ce44SJohn Forte  * Context:
1532fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1533fcf3ce44SJohn Forte  */
1534fcf3ce44SJohn Forte static void
ql_isp24xx_rcvbuf(ql_adapter_state_t * ha)1535fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ql_adapter_state_t *ha)
1536fcf3ce44SJohn Forte {
1537fcf3ce44SJohn Forte 	rcvbuf_t		*container;
1538fcf3ce44SJohn Forte 	uint16_t		index;
1539fcf3ce44SJohn Forte 	ql_srb_t		*sp;
1540fcf3ce44SJohn Forte 	fc_unsol_buf_t		*ubp;
1541fcf3ce44SJohn Forte 	int			rval;
1542fcf3ce44SJohn Forte 	ip_buf_pool_entry_t	*pkt = NULL;
1543*4c3888b8SHans Rosenfeld 	ql_request_q_t		*req_q = ha->req_q[0];
1544fcf3ce44SJohn Forte 
1545*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "started\n");
1546fcf3ce44SJohn Forte 
1547fcf3ce44SJohn Forte 	for (;;) {
1548fcf3ce44SJohn Forte 		/* Locate a buffer to give. */
1549fcf3ce44SJohn Forte 		QL_UB_LOCK(ha);
1550fcf3ce44SJohn Forte 		for (index = 0; index < QL_UB_LIMIT; index++) {
1551fcf3ce44SJohn Forte 			ubp = ha->ub_array[index];
1552fcf3ce44SJohn Forte 			if (ubp != NULL) {
1553fcf3ce44SJohn Forte 				sp = ubp->ub_fca_private;
1554fcf3ce44SJohn Forte 				if ((sp->ub_type == FC_TYPE_IS8802_SNAP) &&
1555fcf3ce44SJohn Forte 				    (ha->flags & IP_INITIALIZED) &&
1556fcf3ce44SJohn Forte 				    (sp->flags & SRB_UB_IN_FCA) &&
1557fcf3ce44SJohn Forte 				    (!(sp->flags & (SRB_UB_IN_ISP |
1558fcf3ce44SJohn Forte 				    SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1559fcf3ce44SJohn Forte 				    SRB_UB_ACQUIRED)))) {
1560fcf3ce44SJohn Forte 					ha->ub_outcnt++;
1561fcf3ce44SJohn Forte 					sp->flags |= SRB_UB_IN_ISP;
1562fcf3ce44SJohn Forte 					break;
1563fcf3ce44SJohn Forte 				}
1564fcf3ce44SJohn Forte 			}
1565fcf3ce44SJohn Forte 		}
1566fcf3ce44SJohn Forte 		QL_UB_UNLOCK(ha);
1567fcf3ce44SJohn Forte 		if (index == QL_UB_LIMIT) {
1568fcf3ce44SJohn Forte 			break;
1569fcf3ce44SJohn Forte 		}
1570fcf3ce44SJohn Forte 
1571fcf3ce44SJohn Forte 		/* Get IOCB packet for buffers. */
1572fcf3ce44SJohn Forte 		if (pkt == NULL) {
1573*4c3888b8SHans Rosenfeld 			rval = ql_req_pkt(ha, req_q, (request_t **)&pkt);
1574fcf3ce44SJohn Forte 			if (rval != QL_SUCCESS) {
1575fcf3ce44SJohn Forte 				EL(ha, "failed, ql_req_pkt=%x\n", rval);
1576fcf3ce44SJohn Forte 				QL_UB_LOCK(ha);
1577fcf3ce44SJohn Forte 				ha->ub_outcnt--;
1578fcf3ce44SJohn Forte 				sp->flags &= ~SRB_UB_IN_ISP;
1579fcf3ce44SJohn Forte 				QL_UB_UNLOCK(ha);
1580fcf3ce44SJohn Forte 				break;
1581fcf3ce44SJohn Forte 			}
1582fcf3ce44SJohn Forte 			pkt->entry_type = IP_BUF_POOL_TYPE;
1583fcf3ce44SJohn Forte 			container = &pkt->buffers[0];
1584fcf3ce44SJohn Forte 		}
1585fcf3ce44SJohn Forte 
1586fcf3ce44SJohn Forte 		/*
1587fcf3ce44SJohn Forte 		 * Build container.
1588fcf3ce44SJohn Forte 		 */
1589*4c3888b8SHans Rosenfeld 		ddi_put32(req_q->req_ring.acc_handle, &container->bufp[0],
1590fcf3ce44SJohn Forte 		    sp->ub_buffer.cookie.dmac_address);
1591*4c3888b8SHans Rosenfeld 		ddi_put32(req_q->req_ring.acc_handle, &container->bufp[1],
1592fcf3ce44SJohn Forte 		    sp->ub_buffer.cookie.dmac_notused);
1593*4c3888b8SHans Rosenfeld 		ddi_put16(req_q->req_ring.acc_handle, &container->handle,
1594fcf3ce44SJohn Forte 		    LSW(sp->handle));
1595fcf3ce44SJohn Forte 
1596fcf3ce44SJohn Forte 		pkt->buffer_count++;
1597fcf3ce44SJohn Forte 		container++;
1598fcf3ce44SJohn Forte 
1599fcf3ce44SJohn Forte 		if (pkt->buffer_count == IP_POOL_BUFFERS) {
1600*4c3888b8SHans Rosenfeld 			ql_isp_cmd(ha, req_q);
1601fcf3ce44SJohn Forte 			pkt = NULL;
1602fcf3ce44SJohn Forte 		}
1603fcf3ce44SJohn Forte 	}
1604fcf3ce44SJohn Forte 
1605fcf3ce44SJohn Forte 	if (pkt != NULL) {
1606*4c3888b8SHans Rosenfeld 		ql_isp_cmd(ha, req_q);
1607fcf3ce44SJohn Forte 	}
1608fcf3ce44SJohn Forte 
1609*4c3888b8SHans Rosenfeld 	QL_PRINT_3(ha, "done\n");
1610fcf3ce44SJohn Forte }
1611