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