1*45039663SJohn Forte /*
2*45039663SJohn Forte  * CDDL HEADER START
3*45039663SJohn Forte  *
4*45039663SJohn Forte  * The contents of this file are subject to the terms of the
5*45039663SJohn Forte  * Common Development and Distribution License (the "License").
6*45039663SJohn Forte  * You may not use this file except in compliance with the License.
7*45039663SJohn Forte  *
8*45039663SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45039663SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*45039663SJohn Forte  * See the License for the specific language governing permissions
11*45039663SJohn Forte  * and limitations under the License.
12*45039663SJohn Forte  *
13*45039663SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*45039663SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45039663SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*45039663SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*45039663SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*45039663SJohn Forte  *
19*45039663SJohn Forte  * CDDL HEADER END
20*45039663SJohn Forte  */
21*45039663SJohn Forte /*
22*45039663SJohn Forte  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*45039663SJohn Forte  * Use is subject to license terms.
24*45039663SJohn Forte  */
25*45039663SJohn Forte 
26*45039663SJohn Forte #include <sys/cpuvar.h>
27*45039663SJohn Forte #include <sys/types.h>
28*45039663SJohn Forte #include <sys/conf.h>
29*45039663SJohn Forte #include <sys/file.h>
30*45039663SJohn Forte #include <sys/ddi.h>
31*45039663SJohn Forte #include <sys/sunddi.h>
32*45039663SJohn Forte #include <sys/modctl.h>
33*45039663SJohn Forte #include <sys/sysmacros.h>
34*45039663SJohn Forte 
35*45039663SJohn Forte #include <sys/socket.h>
36*45039663SJohn Forte #include <sys/strsubr.h>
37*45039663SJohn Forte #include <sys/door.h>
38*45039663SJohn Forte 
39*45039663SJohn Forte #include <sys/stmf.h>
40*45039663SJohn Forte #include <sys/stmf_ioctl.h>
41*45039663SJohn Forte #include <sys/portif.h>
42*45039663SJohn Forte #include <pppt.h>
43*45039663SJohn Forte 
44*45039663SJohn Forte static void pppt_msg_tgt_register(stmf_ic_msg_t *reg_port);
45*45039663SJohn Forte 
46*45039663SJohn Forte static void pppt_msg_tgt_deregister(stmf_ic_msg_t *msg);
47*45039663SJohn Forte 
48*45039663SJohn Forte static void pppt_msg_session_destroy(stmf_ic_msg_t *msg);
49*45039663SJohn Forte 
50*45039663SJohn Forte static void pppt_msg_scsi_cmd(stmf_ic_msg_t *msg);
51*45039663SJohn Forte 
52*45039663SJohn Forte static void pppt_msg_data_xfer_done(stmf_ic_msg_t *msg);
53*45039663SJohn Forte 
54*45039663SJohn Forte static void pppt_msg_handle_status(stmf_ic_msg_t *msg);
55*45039663SJohn Forte 
56*45039663SJohn Forte void
57*45039663SJohn Forte pppt_msg_rx(stmf_ic_msg_t *msg)
58*45039663SJohn Forte {
59*45039663SJohn Forte 	switch (msg->icm_msg_type) {
60*45039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
61*45039663SJohn Forte 		pppt_msg_tgt_register(msg);
62*45039663SJohn Forte 		break;
63*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
64*45039663SJohn Forte 		pppt_msg_tgt_deregister(msg);
65*45039663SJohn Forte 		break;
66*45039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
67*45039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_NOT_SUPPORTED);
68*45039663SJohn Forte 		stmf_ic_msg_free(msg);
69*45039663SJohn Forte 		break;
70*45039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
71*45039663SJohn Forte 		pppt_msg_session_destroy(msg);
72*45039663SJohn Forte 		break;
73*45039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
74*45039663SJohn Forte 		pppt_msg_scsi_cmd(msg);
75*45039663SJohn Forte 		break;
76*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
77*45039663SJohn Forte 		pppt_msg_data_xfer_done(msg);
78*45039663SJohn Forte 		break;
79*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
80*45039663SJohn Forte 		/* Ignore, all proxy data will be immediate for now */
81*45039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_NOT_SUPPORTED);
82*45039663SJohn Forte 		stmf_ic_msg_free(msg);
83*45039663SJohn Forte 		break;
84*45039663SJohn Forte 	case STMF_ICM_STATUS:
85*45039663SJohn Forte 		pppt_msg_handle_status(msg);
86*45039663SJohn Forte 		break;
87*45039663SJohn Forte 	default:
88*45039663SJohn Forte 		/* Other message types are not allowed */
89*45039663SJohn Forte 		ASSERT(0);
90*45039663SJohn Forte 		break;
91*45039663SJohn Forte 	}
92*45039663SJohn Forte }
93*45039663SJohn Forte 
94*45039663SJohn Forte void
95*45039663SJohn Forte pppt_msg_tx_status(stmf_ic_msg_t *orig_msg, stmf_status_t status)
96*45039663SJohn Forte {
97*45039663SJohn Forte 	stmf_ic_msg_t	*msg;
98*45039663SJohn Forte 
99*45039663SJohn Forte 	/*
100*45039663SJohn Forte 	 * If TX of status fails it should be treated the same as a loss of
101*45039663SJohn Forte 	 * connection.  We expect the remote node to handle it.
102*45039663SJohn Forte 	 */
103*45039663SJohn Forte 	msg = stmf_ic_status_msg_alloc(status, orig_msg->icm_msg_type,
104*45039663SJohn Forte 	    orig_msg->icm_msgid);
105*45039663SJohn Forte 
106*45039663SJohn Forte 	if (msg != NULL) {
107*45039663SJohn Forte 		(void) stmf_ic_tx_msg(msg);
108*45039663SJohn Forte 	}
109*45039663SJohn Forte }
110*45039663SJohn Forte 
111*45039663SJohn Forte static void
112*45039663SJohn Forte pppt_msg_tgt_register(stmf_ic_msg_t *msg)
113*45039663SJohn Forte {
114*45039663SJohn Forte 	stmf_ic_reg_port_msg_t	*reg_port;
115*45039663SJohn Forte 	pppt_tgt_t		*result;
116*45039663SJohn Forte 	stmf_status_t		stmf_status;
117*45039663SJohn Forte 
118*45039663SJohn Forte 	reg_port = msg->icm_msg;
119*45039663SJohn Forte 
120*45039663SJohn Forte 
121*45039663SJohn Forte 	PPPT_GLOBAL_LOCK();
122*45039663SJohn Forte 	if (pppt_global.global_svc_state != PSS_ENABLED) {
123*45039663SJohn Forte 		stmf_status = STMF_FAILURE;
124*45039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_svc_disabled);
125*45039663SJohn Forte 		goto pppt_register_tgt_done;
126*45039663SJohn Forte 	}
127*45039663SJohn Forte 
128*45039663SJohn Forte 	/*
129*45039663SJohn Forte 	 * For now we assume that the marshall/unmarshall code is responsible
130*45039663SJohn Forte 	 * for validating the message length and ensuring the resulting
131*45039663SJohn Forte 	 * request structure is self consistent.  Make sure this
132*45039663SJohn Forte 	 * target doesn't already exist.
133*45039663SJohn Forte 	 */
134*45039663SJohn Forte 	if ((result = pppt_tgt_lookup_locked(reg_port->icrp_port_id)) != NULL) {
135*45039663SJohn Forte 		stmf_status = STMF_ALREADY;
136*45039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_duplicate);
137*45039663SJohn Forte 		goto pppt_register_tgt_done;
138*45039663SJohn Forte 	}
139*45039663SJohn Forte 
140*45039663SJohn Forte 	result = pppt_tgt_create(reg_port, &stmf_status);
141*45039663SJohn Forte 
142*45039663SJohn Forte 	if (result == NULL) {
143*45039663SJohn Forte 		stmf_status = STMF_TARGET_FAILURE;
144*45039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_create_fail);
145*45039663SJohn Forte 		goto pppt_register_tgt_done;
146*45039663SJohn Forte 	}
147*45039663SJohn Forte 
148*45039663SJohn Forte 	avl_add(&pppt_global.global_target_list, result);
149*45039663SJohn Forte 
150*45039663SJohn Forte 	stmf_status = STMF_SUCCESS;
151*45039663SJohn Forte 
152*45039663SJohn Forte pppt_register_tgt_done:
153*45039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
154*45039663SJohn Forte 	pppt_msg_tx_status(msg, stmf_status);
155*45039663SJohn Forte 	stmf_ic_msg_free(msg);
156*45039663SJohn Forte }
157*45039663SJohn Forte 
158*45039663SJohn Forte static void
159*45039663SJohn Forte pppt_msg_tgt_deregister(stmf_ic_msg_t *msg)
160*45039663SJohn Forte {
161*45039663SJohn Forte 	stmf_ic_dereg_port_msg_t	*dereg_port;
162*45039663SJohn Forte 	stmf_status_t			stmf_status;
163*45039663SJohn Forte 	pppt_tgt_t			*tgt;
164*45039663SJohn Forte 
165*45039663SJohn Forte 	PPPT_GLOBAL_LOCK();
166*45039663SJohn Forte 	if (pppt_global.global_svc_state != PSS_ENABLED) {
167*45039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
168*45039663SJohn Forte 		stmf_status = STMF_FAILURE;
169*45039663SJohn Forte 		PPPT_INC_STAT(es_tgt_dereg_svc_disabled);
170*45039663SJohn Forte 		goto pppt_deregister_tgt_done;
171*45039663SJohn Forte 	}
172*45039663SJohn Forte 
173*45039663SJohn Forte 	dereg_port = msg->icm_msg;
174*45039663SJohn Forte 
175*45039663SJohn Forte 	/* Lookup target */
176*45039663SJohn Forte 	if ((tgt = pppt_tgt_lookup_locked(dereg_port->icdp_port_id)) == NULL) {
177*45039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
178*45039663SJohn Forte 		stmf_status = STMF_NOT_FOUND;
179*45039663SJohn Forte 		PPPT_INC_STAT(es_tgt_dereg_not_found);
180*45039663SJohn Forte 		goto pppt_deregister_tgt_done;
181*45039663SJohn Forte 	}
182*45039663SJohn Forte 	avl_remove(&pppt_global.global_target_list, tgt);
183*45039663SJohn Forte 	pppt_tgt_async_delete(tgt);
184*45039663SJohn Forte 
185*45039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
186*45039663SJohn Forte 
187*45039663SJohn Forte 	/* Wait for delete to complete */
188*45039663SJohn Forte 	mutex_enter(&tgt->target_mutex);
189*45039663SJohn Forte 	while ((tgt->target_refcount > 0) ||
190*45039663SJohn Forte 	    (tgt->target_state != TS_DELETING)) {
191*45039663SJohn Forte 		cv_wait(&tgt->target_cv, &tgt->target_mutex);
192*45039663SJohn Forte 	}
193*45039663SJohn Forte 	mutex_exit(&tgt->target_mutex);
194*45039663SJohn Forte 
195*45039663SJohn Forte 	pppt_tgt_destroy(tgt);
196*45039663SJohn Forte 	stmf_status = STMF_SUCCESS;
197*45039663SJohn Forte 
198*45039663SJohn Forte pppt_deregister_tgt_done:
199*45039663SJohn Forte 	pppt_msg_tx_status(msg, stmf_status);
200*45039663SJohn Forte 	stmf_ic_msg_free(msg);
201*45039663SJohn Forte }
202*45039663SJohn Forte 
203*45039663SJohn Forte static void
204*45039663SJohn Forte pppt_msg_session_destroy(stmf_ic_msg_t *msg)
205*45039663SJohn Forte {
206*45039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t	*sess_destroy;
207*45039663SJohn Forte 	pppt_tgt_t				*tgt;
208*45039663SJohn Forte 	pppt_sess_t				*ps;
209*45039663SJohn Forte 
210*45039663SJohn Forte 	sess_destroy = msg->icm_msg;
211*45039663SJohn Forte 
212*45039663SJohn Forte 	PPPT_GLOBAL_LOCK();
213*45039663SJohn Forte 
214*45039663SJohn Forte 	/*
215*45039663SJohn Forte 	 * Look for existing session for this ID
216*45039663SJohn Forte 	 */
217*45039663SJohn Forte 	ps = pppt_sess_lookup_locked(sess_destroy->icscd_session_id,
218*45039663SJohn Forte 	    sess_destroy->icscd_tgt_devid, sess_destroy->icscd_ini_devid);
219*45039663SJohn Forte 
220*45039663SJohn Forte 	if (ps == NULL) {
221*45039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
222*45039663SJohn Forte 		stmf_ic_msg_free(msg);
223*45039663SJohn Forte 		PPPT_INC_STAT(es_sess_destroy_no_session);
224*45039663SJohn Forte 		return;
225*45039663SJohn Forte 	}
226*45039663SJohn Forte 
227*45039663SJohn Forte 	tgt = ps->ps_target;
228*45039663SJohn Forte 
229*45039663SJohn Forte 	mutex_enter(&tgt->target_mutex);
230*45039663SJohn Forte 	mutex_enter(&ps->ps_mutex);
231*45039663SJohn Forte 
232*45039663SJohn Forte 	/* Release the reference from the lookup */
233*45039663SJohn Forte 	pppt_sess_rele_locked(ps);
234*45039663SJohn Forte 
235*45039663SJohn Forte 	/* Make sure another thread is not already closing the session */
236*45039663SJohn Forte 	if (!ps->ps_closed) {
237*45039663SJohn Forte 		/* Found matching open session, quiesce... */
238*45039663SJohn Forte 		pppt_sess_close_locked(ps);
239*45039663SJohn Forte 	}
240*45039663SJohn Forte 	mutex_exit(&ps->ps_mutex);
241*45039663SJohn Forte 	mutex_exit(&tgt->target_mutex);
242*45039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
243*45039663SJohn Forte 
244*45039663SJohn Forte 	stmf_ic_msg_free(msg);
245*45039663SJohn Forte }
246*45039663SJohn Forte 
247*45039663SJohn Forte static void
248*45039663SJohn Forte pppt_msg_scsi_cmd(stmf_ic_msg_t *msg)
249*45039663SJohn Forte {
250*45039663SJohn Forte 	pppt_sess_t			*pppt_sess;
251*45039663SJohn Forte 	pppt_buf_t			*pbuf;
252*45039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t		*scmd;
253*45039663SJohn Forte 	pppt_task_t			*ptask;
254*45039663SJohn Forte 	scsi_task_t			*task;
255*45039663SJohn Forte 	pppt_status_t			pppt_status;
256*45039663SJohn Forte 	stmf_local_port_t		*lport;
257*45039663SJohn Forte 	stmf_scsi_session_t		*stmf_sess;
258*45039663SJohn Forte 	stmf_status_t			stmf_status;
259*45039663SJohn Forte 
260*45039663SJohn Forte 	/*
261*45039663SJohn Forte 	 * Get a task context
262*45039663SJohn Forte 	 */
263*45039663SJohn Forte 	ptask = pppt_task_alloc();
264*45039663SJohn Forte 	if (ptask == NULL) {
265*45039663SJohn Forte 		/*
266*45039663SJohn Forte 		 * We must be very low on memory.  Just free the message
267*45039663SJohn Forte 		 * and let the command timeout.
268*45039663SJohn Forte 		 */
269*45039663SJohn Forte 		stmf_ic_msg_free(msg);
270*45039663SJohn Forte 		PPPT_INC_STAT(es_scmd_ptask_alloc_fail);
271*45039663SJohn Forte 		return;
272*45039663SJohn Forte 	}
273*45039663SJohn Forte 
274*45039663SJohn Forte 	scmd = msg->icm_msg;
275*45039663SJohn Forte 
276*45039663SJohn Forte 	/*
277*45039663SJohn Forte 	 * Session are created implicitly on the first use of an
278*45039663SJohn Forte 	 * IT nexus
279*45039663SJohn Forte 	 */
280*45039663SJohn Forte 	pppt_sess = pppt_sess_lookup_create(scmd->icsc_tgt_devid,
281*45039663SJohn Forte 	    scmd->icsc_ini_devid, scmd->icsc_session_id, &stmf_status);
282*45039663SJohn Forte 	if (pppt_sess == NULL) {
283*45039663SJohn Forte 		pppt_task_free(ptask);
284*45039663SJohn Forte 		pppt_msg_tx_status(msg, stmf_status);
285*45039663SJohn Forte 		stmf_ic_msg_free(msg);
286*45039663SJohn Forte 		PPPT_INC_STAT(es_scmd_sess_create_fail);
287*45039663SJohn Forte 		return;
288*45039663SJohn Forte 	}
289*45039663SJohn Forte 
290*45039663SJohn Forte 	ptask->pt_sess = pppt_sess;
291*45039663SJohn Forte 	ptask->pt_task_id = scmd->icsc_task_msgid;
292*45039663SJohn Forte 	stmf_sess = pppt_sess->ps_stmf_sess;
293*45039663SJohn Forte 	lport = stmf_sess->ss_lport;
294*45039663SJohn Forte 
295*45039663SJohn Forte 	/*
296*45039663SJohn Forte 	 * Add task to our internal task set.
297*45039663SJohn Forte 	 */
298*45039663SJohn Forte 	pppt_status = pppt_task_start(ptask);
299*45039663SJohn Forte 
300*45039663SJohn Forte 	if (pppt_status != 0) {
301*45039663SJohn Forte 		/* Release hold from pppt_sess_lookup_create() */
302*45039663SJohn Forte 		PPPT_LOG(CE_WARN, "Duplicate taskid from remote node 0x%llx",
303*45039663SJohn Forte 		    (longlong_t)scmd->icsc_task_msgid);
304*45039663SJohn Forte 		pppt_task_free(ptask);
305*45039663SJohn Forte 		pppt_sess_rele(pppt_sess);
306*45039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_ALREADY);
307*45039663SJohn Forte 		stmf_ic_msg_free(msg);
308*45039663SJohn Forte 		PPPT_INC_STAT(es_scmd_dup_task_count);
309*45039663SJohn Forte 		return;
310*45039663SJohn Forte 	}
311*45039663SJohn Forte 
312*45039663SJohn Forte 	/*
313*45039663SJohn Forte 	 * Allocate STMF task context
314*45039663SJohn Forte 	 */
315*45039663SJohn Forte 	ptask->pt_stmf_task = stmf_task_alloc(lport, stmf_sess,
316*45039663SJohn Forte 	    scmd->icsc_task_lun_no,
317*45039663SJohn Forte 	    scmd->icsc_task_cdb_length, 0);
318*45039663SJohn Forte 	if (ptask->pt_stmf_task == NULL) {
319*45039663SJohn Forte 		(void) pppt_task_done(ptask);
320*45039663SJohn Forte 		pppt_task_free(ptask);
321*45039663SJohn Forte 		pppt_sess_rele(pppt_sess);
322*45039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_ALLOC_FAILURE);
323*45039663SJohn Forte 		stmf_ic_msg_free(msg);
324*45039663SJohn Forte 		PPPT_INC_STAT(es_scmd_stask_alloc_fail);
325*45039663SJohn Forte 		return;
326*45039663SJohn Forte 	}
327*45039663SJohn Forte 
328*45039663SJohn Forte 	task = ptask->pt_stmf_task;
329*45039663SJohn Forte 	task->task_port_private = ptask;
330*45039663SJohn Forte 	task->task_flags = scmd->icsc_task_flags;
331*45039663SJohn Forte 	task->task_additional_flags = 0;
332*45039663SJohn Forte 	task->task_priority = 0;
333*45039663SJohn Forte 
334*45039663SJohn Forte 	/*
335*45039663SJohn Forte 	 * Set task->task_mgmt_function to TM_NONE for a normal SCSI task
336*45039663SJohn Forte 	 * or one of these values for a task management command:
337*45039663SJohn Forte 	 *
338*45039663SJohn Forte 	 * TM_ABORT_TASK ***
339*45039663SJohn Forte 	 * TM_ABORT_TASK_SET
340*45039663SJohn Forte 	 * TM_CLEAR_ACA
341*45039663SJohn Forte 	 * TM_CLEAR_TASK_SET
342*45039663SJohn Forte 	 * TM_LUN_RESET
343*45039663SJohn Forte 	 * TM_TARGET_WARM_RESET
344*45039663SJohn Forte 	 * TM_TARGET_COLD_RESET
345*45039663SJohn Forte 	 *
346*45039663SJohn Forte 	 * *** Note that STMF does not currently support TM_ABORT_TASK so
347*45039663SJohn Forte 	 * port providers must implement this command on their own
348*45039663SJohn Forte 	 * (e.g. lookup the desired task and call stmf_abort).
349*45039663SJohn Forte 	 */
350*45039663SJohn Forte 	task->task_mgmt_function = scmd->icsc_task_mgmt_function;
351*45039663SJohn Forte 
352*45039663SJohn Forte 	task->task_max_nbufs = STMF_BUFS_MAX; /* Or protocol value */
353*45039663SJohn Forte 	task->task_cmd_seq_no = msg->icm_msgid;
354*45039663SJohn Forte 	task->task_expected_xfer_length =
355*45039663SJohn Forte 	    scmd->icsc_task_expected_xfer_length;
356*45039663SJohn Forte 
357*45039663SJohn Forte 	bcopy(scmd->icsc_task_cdb, task->task_cdb,
358*45039663SJohn Forte 	    scmd->icsc_task_cdb_length);
359*45039663SJohn Forte 	bcopy(scmd->icsc_lun_id, ptask->pt_lun_id, 16);
360*45039663SJohn Forte 
361*45039663SJohn Forte 	if (scmd->icsc_immed_data_len) {
362*45039663SJohn Forte 		pbuf = ptask->pt_immed_data;
363*45039663SJohn Forte 		pbuf->pbuf_immed_msg = msg;
364*45039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_data_size = scmd->icsc_immed_data_len;
365*45039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_buf_size = scmd->icsc_immed_data_len;
366*45039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_relative_offset = 0;
367*45039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_sglist[0].seg_length =
368*45039663SJohn Forte 		    scmd->icsc_immed_data_len;
369*45039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_sglist[0].seg_addr =
370*45039663SJohn Forte 		    scmd->icsc_immed_data;
371*45039663SJohn Forte 
372*45039663SJohn Forte 		stmf_post_task(task, pbuf->pbuf_stmf_buf);
373*45039663SJohn Forte 	} else {
374*45039663SJohn Forte 		stmf_post_task(task, NULL);
375*45039663SJohn Forte 		stmf_ic_msg_free(msg);
376*45039663SJohn Forte 	}
377*45039663SJohn Forte }
378*45039663SJohn Forte 
379*45039663SJohn Forte static void
380*45039663SJohn Forte pppt_msg_data_xfer_done(stmf_ic_msg_t *msg)
381*45039663SJohn Forte {
382*45039663SJohn Forte 	pppt_task_t				*pppt_task;
383*45039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t	*data_xfer_done;
384*45039663SJohn Forte 
385*45039663SJohn Forte 	data_xfer_done = msg->icm_msg;
386*45039663SJohn Forte 
387*45039663SJohn Forte 	/*
388*45039663SJohn Forte 	 * Find task
389*45039663SJohn Forte 	 */
390*45039663SJohn Forte 	pppt_task = pppt_task_lookup(data_xfer_done->icsx_task_msgid);
391*45039663SJohn Forte 
392*45039663SJohn Forte 	/* If we found one, complete the transfer */
393*45039663SJohn Forte 	if (pppt_task != NULL) {
394*45039663SJohn Forte 		pppt_xfer_read_complete(pppt_task, data_xfer_done->icsx_status);
395*45039663SJohn Forte 	}
396*45039663SJohn Forte 
397*45039663SJohn Forte 	stmf_ic_msg_free(msg);
398*45039663SJohn Forte }
399*45039663SJohn Forte 
400*45039663SJohn Forte static void
401*45039663SJohn Forte pppt_msg_handle_status(stmf_ic_msg_t *msg)
402*45039663SJohn Forte {
403*45039663SJohn Forte 	/* Don't care for now */
404*45039663SJohn Forte 	stmf_ic_msg_free(msg);
405*45039663SJohn Forte }
406