xref: /titanic_50/usr/src/uts/common/io/sbp2/sbp2.c (revision 554ff184129088135ad2643c1c9832174a17be88)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * SBP2 module
31  */
32 #include <sys/param.h>
33 #include <sys/errno.h>
34 #include <sys/cred.h>
35 #include <sys/conf.h>
36 #include <sys/modctl.h>
37 #include <sys/stat.h>
38 #include <sys/stream.h>
39 #include <sys/strsubr.h>
40 #include <sys/strsun.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 
44 #include <sys/sbp2/impl.h>
45 #include <sys/1394/ieee1212.h>
46 
47 /* target routines */
48 static void	sbp2_tgt_init_sobj(sbp2_tgt_t *);
49 static void	sbp2_tgt_fini_sobj(sbp2_tgt_t *);
50 static int	sbp2_tgt_init_params(sbp2_tgt_t *);
51 static int	sbp2_tgt_init_luns(sbp2_tgt_t *, int);
52 static void	sbp2_tgt_fini_luns(sbp2_tgt_t *);
53 static int	sbp2_tgt_init_bus(sbp2_tgt_t *);
54 static void	sbp2_tgt_fini_bus(sbp2_tgt_t *);
55 static int	sbp2_tgt_mgt_request(sbp2_tgt_t *, int *);
56 static int	sbp2_tgt_task_mgt_request(sbp2_tgt_t *, uint16_t, int, uint64_t,
57 		int *);
58 
59 /* lun routines */
60 static void	sbp2_lun_logout_orb(sbp2_lun_t *, sbp2_tgt_t *, int *);
61 static boolean_t sbp2_lun_accepting_tasks(sbp2_lun_t *);
62 
63 /* session routines */
64 static int	sbp2_ses_init(sbp2_ses_t **, sbp2_lun_t *,
65 		void (*)(void *, sbp2_task_t *), void *);
66 static void	sbp2_ses_fini(sbp2_ses_t *);
67 static sbp2_task_t *sbp2_ses_orbp2task(sbp2_ses_t *, uint64_t);
68 static void	sbp2_ses_append_task(sbp2_ses_t *, sbp2_task_t *);
69 static void	sbp2_ses_reset_pending_tasks(sbp2_ses_t *, uint16_t);
70 static int	sbp2_ses_reconnect_orb(sbp2_ses_t *, int *);
71 
72 /* orb alloc routines */
73 static sbp2_bus_buf_t *sbp2_orb_freelist_get(sbp2_lun_t *, sbp2_task_t *, int);
74 static int	sbp2_orb_freelist_put(sbp2_lun_t *, sbp2_bus_buf_t *);
75 static void	sbp2_orb_freelist_destroy(sbp2_lun_t *);
76 
77 /* fetch agent routines */
78 static int	sbp2_agent_init(sbp2_agent_t *, uint64_t, sbp2_tgt_t *tp);
79 static void	sbp2_agent_fini(sbp2_agent_t *);
80 static void	sbp2_agent_acquire_locked(sbp2_agent_t *);
81 static void	sbp2_agent_release_locked(sbp2_agent_t *);
82 static void	sbp2_agent_acquire(sbp2_agent_t *);
83 static void	sbp2_agent_release(sbp2_agent_t *);
84 static int	sbp2_agent_keepalive(sbp2_agent_t *, int *);
85 static int	sbp2_agent_doorbell(sbp2_agent_t *, int *);
86 static int	sbp2_agent_write_orbp(sbp2_agent_t *, uint64_t, int *);
87 static int	sbp2_agent_reset(sbp2_agent_t *, int *);
88 
89 /* callbacks and timeouts */
90 static void	sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t *, void *, mblk_t **);
91 static void	sbp2_task_timeout(void *);
92 static void	sbp2_status_fifo_wb_cb(sbp2_bus_buf_t *, void *, mblk_t **);
93 
94 /* other */
95 static void	sbp2_mgt_agent_acquire(sbp2_tgt_t *);
96 static void	sbp2_mgt_agent_release(sbp2_tgt_t *);
97 static void	sbp2_fetch_agent_acquire(sbp2_ses_t *);
98 static void	sbp2_fetch_agent_release(sbp2_ses_t *);
99 
100 extern struct mod_ops mod_miscops;
101 
102 static struct modlmisc sbp2_modlmisc = {
103 	&mod_miscops,		/* module type */
104 	"Serial Bus Protocol 2 module %I%" /* module name */
105 };
106 
107 static struct modlinkage sbp2_modlinkage = {
108 	MODREV_1, (void *)&sbp2_modlmisc, NULL
109 };
110 
111 /* tunables */
112 int	sbp2_submit_reset_nretries = 3;
113 clock_t	sbp2_submit_reset_delay = 10;	/* microsec */
114 
115 int	sbp2_write_orbp_nretries = 3;
116 clock_t	sbp2_write_orbp_delay = 10;	/* microsec */
117 
118 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab msgb))
119 
120 /*
121  *
122  * --- loadable module entry points
123  *
124  */
125 int
126 _init(void)
127 {
128 	return (mod_install(&sbp2_modlinkage));
129 }
130 
131 
132 int
133 _fini(void)
134 {
135 	return (mod_remove(&sbp2_modlinkage));
136 }
137 
138 
139 int
140 _info(struct modinfo *modinfop)
141 {
142 	return (mod_info(&sbp2_modlinkage, modinfop));
143 }
144 
145 /*
146  *
147  * --- target routines
148  *
149  */
150 int
151 sbp2_tgt_init(void *bus_hdl, sbp2_bus_t *bus, int maxluns, sbp2_tgt_t **tpp)
152 {
153 	sbp2_tgt_t	*tp;
154 	int		ret;
155 
156 	tp = kmem_zalloc(sizeof (sbp2_tgt_t), KM_SLEEP);
157 	tp->t_bus = bus;
158 	tp->t_bus_hdl = bus_hdl;
159 
160 	sbp2_tgt_init_sobj(tp);
161 
162 	if ((ret = sbp2_cfgrom_parse(tp, &tp->t_cfgrom)) != SBP2_SUCCESS) {
163 		sbp2_tgt_fini_sobj(tp);
164 		kmem_free(tp, sizeof (sbp2_tgt_t));
165 		return (SBP2_ECFGROM);
166 	}
167 
168 	if ((ret = sbp2_tgt_init_params(tp)) != SBP2_SUCCESS) {
169 		sbp2_cfgrom_free(tp, &tp->t_cfgrom);
170 		sbp2_tgt_fini_sobj(tp);
171 		kmem_free(tp, sizeof (sbp2_tgt_t));
172 		return (ret);
173 	}
174 
175 	if ((ret = sbp2_tgt_init_luns(tp, maxluns)) != SBP2_SUCCESS) {
176 		sbp2_cfgrom_free(tp, &tp->t_cfgrom);
177 		sbp2_tgt_fini_sobj(tp);
178 		kmem_free(tp, sizeof (sbp2_tgt_t));
179 		return (ret);
180 	}
181 
182 	if ((ret = sbp2_tgt_init_bus(tp)) != SBP2_SUCCESS) {
183 		sbp2_tgt_fini_luns(tp);
184 		sbp2_cfgrom_free(tp, &tp->t_cfgrom);
185 		sbp2_tgt_fini_sobj(tp);
186 		kmem_free(tp, sizeof (sbp2_tgt_t));
187 		return (ret);
188 	}
189 
190 	*tpp = tp;
191 	return (SBP2_SUCCESS);
192 }
193 
194 void
195 sbp2_tgt_fini(sbp2_tgt_t *tp)
196 {
197 	sbp2_tgt_fini_bus(tp);
198 	sbp2_tgt_fini_luns(tp);
199 	sbp2_cfgrom_free(tp, &tp->t_cfgrom);
200 	sbp2_tgt_fini_sobj(tp);
201 	kmem_free(tp, sizeof (sbp2_tgt_t));
202 }
203 
204 static void
205 sbp2_tgt_init_sobj(sbp2_tgt_t *tp)
206 {
207 	mutex_init(&tp->t_mutex, NULL, MUTEX_DRIVER, NULL);
208 	cv_init(&tp->t_mgt_agent_cv, NULL, CV_DRIVER, NULL);
209 	cv_init(&tp->t_mgt_status_cv, NULL, CV_DRIVER, NULL);
210 }
211 
212 static void
213 sbp2_tgt_fini_sobj(sbp2_tgt_t *tp)
214 {
215 	cv_destroy(&tp->t_mgt_status_cv);
216 	cv_destroy(&tp->t_mgt_agent_cv);
217 	mutex_destroy(&tp->t_mutex);
218 }
219 
220 static int
221 sbp2_tgt_init_params(sbp2_tgt_t *tp)
222 {
223 	sbp2_cfgrom_ent_t *root = &tp->t_cfgrom.cr_root;
224 	sbp2_cfgrom_ent_t *ent;
225 	uint32_t	q;
226 
227 	/* MANAGEMENT_AGENT */
228 	if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_MGT_AGENT,
229 	    SBP2_KV_MGT_AGENT, 0)) == NULL) {
230 		return (SBP2_ECFGROM);
231 	}
232 	tp->t_mgt_agent = SBP2_CSR_BASE(tp) + ent->ce_data.offset * 4;
233 
234 	/* Unit_Characteristics */
235 	if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_UNCHAR,
236 	    SBP2_KV_UNCHAR, 0)) == NULL) {
237 		return (SBP2_ECFGROM);
238 	}
239 	q = ent->ce_data.imm;
240 
241 	/* units of 500 ms -> ms */
242 	tp->t_mot = ((q & SBP2_UNCHAR_MOT) >> SBP2_UNCHAR_MOT_SHIFT) * 500;
243 
244 	/* quadlets -> bytes */
245 	tp->t_orb_size = (q & SBP2_UNCHAR_ORB_SIZE) * 4;
246 
247 	/* some devices return incorrect values */
248 	if (tp->t_mot < SBP2_MOT_MIN) {
249 		tp->t_mot = SBP2_MOT_DFLT;
250 	}
251 	if (tp->t_orb_size < SBP2_ORB_SIZE_MIN) {
252 		tp->t_orb_size = SBP2_ORB_SIZE_MIN;
253 	}
254 
255 	return (SBP2_SUCCESS);
256 }
257 
258 
259 /*ARGSUSED*/
260 static int
261 sbp2_tgt_init_luns(sbp2_tgt_t *tp, int maxluns)
262 {
263 	sbp2_cfgrom_ent_t *root = &tp->t_cfgrom.cr_root;
264 	sbp2_cfgrom_ent_t *ent;
265 	sbp2_lun_t	*lp;
266 	uint32_t	q;
267 
268 	ASSERT(tp->t_nluns == 0);
269 
270 	tp->t_lun = kmem_zalloc(maxluns * sizeof (sbp2_lun_t), KM_SLEEP);
271 	tp->t_nluns_alloc = maxluns;
272 
273 	/* search for Logical_Unit_Number's */
274 	for (tp->t_nluns = 0; tp->t_nluns < maxluns; tp->t_nluns++) {
275 		if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_LUN,
276 		    SBP2_KV_LUN, tp->t_nluns)) == NULL) {
277 			break;
278 		}
279 		q = ent->ce_data.imm;
280 		lp = &tp->t_lun[tp->t_nluns];
281 		lp->l_tgt = tp;
282 		lp->l_lun = q & SBP2_LUN_NUM;
283 		lp->l_type = (q & SBP2_LUN_TYPE) >> SBP2_LUN_TYPE_SHIFT;
284 		mutex_init(&lp->l_orb_freelist.bl_mutex, NULL, MUTEX_DRIVER,
285 		    NULL);
286 	}
287 
288 	if (tp->t_nluns > 0) {
289 		return (SBP2_SUCCESS);
290 	} else {
291 		kmem_free(tp->t_lun, tp->t_nluns_alloc * sizeof (sbp2_lun_t));
292 		return (SBP2_ECFGROM);
293 	}
294 
295 }
296 
297 
298 static void
299 sbp2_tgt_fini_luns(sbp2_tgt_t *tp)
300 {
301 	int		i;
302 	sbp2_lun_t	*lp;
303 
304 	/* destroy each lun */
305 	for (i = 0; i < tp->t_nluns; i++) {
306 		lp = &tp->t_lun[i];
307 		sbp2_orb_freelist_destroy(lp);
308 		mutex_destroy(&lp->l_orb_freelist.bl_mutex);
309 	}
310 
311 	kmem_free(tp->t_lun, tp->t_nluns_alloc * sizeof (sbp2_lun_t));
312 }
313 
314 /*
315  * initialize bus buffers and commands
316  */
317 static int
318 sbp2_tgt_init_bus(sbp2_tgt_t *tp)
319 {
320 	int		ret;
321 
322 	/*
323 	 * We serialize management requests and reuse the same buffers.
324 	 *
325 	 * mgt ORB
326 	 */
327 	tp->t_mgt_orb_buf.bb_len =
328 	    SBP2_ORB_SIZE_ROUNDUP(tp, sizeof (sbp2_mgt_orb_t));
329 	tp->t_mgt_orb_buf.bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RD;
330 	if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_orb_buf)) != SBP2_SUCCESS) {
331 		sbp2_tgt_fini_bus(tp);
332 		return (ret);
333 	}
334 
335 	/*
336 	 * mgt status FIFO
337 	 */
338 	tp->t_mgt_status_fifo_buf.bb_len = sizeof (sbp2_status_t);
339 	tp->t_mgt_status_fifo_buf.bb_flags = SBP2_BUS_BUF_WR_POSTED;
340 	tp->t_mgt_status_fifo_buf.bb_wb_cb = sbp2_mgt_status_fifo_wb_cb;
341 	tp->t_mgt_status_fifo_buf.bb_sbp2_priv = tp;
342 	if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_status_fifo_buf)) !=
343 	    SBP2_SUCCESS) {
344 		return (ret);
345 	}
346 
347 	/*
348 	 * login response
349 	 */
350 	tp->t_mgt_login_resp_buf.bb_len =
351 	    SBP2_ORB_SIZE_ROUNDUP(tp, sizeof (sbp2_login_resp_t));
352 	/*
353 	 * read-only should have been sufficient here, but it causes
354 	 * DVMA errors on Grover, while read/write works just fine
355 	 */
356 	tp->t_mgt_login_resp_buf.bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RW;
357 	if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_login_resp_buf)) !=
358 	    SBP2_SUCCESS) {
359 		sbp2_tgt_fini_bus(tp);
360 		return (ret);
361 	}
362 
363 	/*
364 	 * allocate bus commands
365 	 */
366 	if ((ret = SBP2_ALLOC_CMD(tp, &tp->t_mgt_cmd, 0)) != SBP2_SUCCESS) {
367 		sbp2_tgt_fini_bus(tp);
368 		return (ret);
369 	}
370 	if ((tp->t_mgt_cmd_data = allocb(8, BPRI_HI)) == NULL) {
371 		sbp2_tgt_fini_bus(tp);
372 		return (SBP2_ENOMEM);
373 	}
374 
375 	return (SBP2_SUCCESS);
376 }
377 
378 static void
379 sbp2_tgt_fini_bus(sbp2_tgt_t *tp)
380 {
381 	if (tp->t_mgt_status_fifo_buf.bb_hdl != NULL) {
382 		SBP2_FREE_BUF(tp, &tp->t_mgt_status_fifo_buf);
383 	}
384 	if (tp->t_mgt_orb_buf.bb_hdl != NULL) {
385 		SBP2_FREE_BUF(tp, &tp->t_mgt_orb_buf);
386 	}
387 	if (tp->t_mgt_login_resp_buf.bb_hdl != NULL) {
388 		SBP2_FREE_BUF(tp, &tp->t_mgt_login_resp_buf);
389 	}
390 	if (tp->t_mgt_cmd) {
391 		SBP2_FREE_CMD(tp, tp->t_mgt_cmd);
392 	}
393 	if (tp->t_mgt_cmd_data) {
394 		freeb(tp->t_mgt_cmd_data);
395 	}
396 }
397 
398 void
399 sbp2_tgt_disconnect(sbp2_tgt_t *tp)
400 {
401 	sbp2_tgt_fini_bus(tp);
402 }
403 
404 int
405 sbp2_tgt_reconnect(sbp2_tgt_t *tp)
406 {
407 	return (sbp2_tgt_init_bus(tp));
408 }
409 
410 /*
411  * send mgt ORB and wait for status
412  *
413  * mgt agent should be acquired
414  */
415 static int
416 sbp2_tgt_mgt_request(sbp2_tgt_t *tp, int *berr)
417 {
418 	clock_t		until;
419 	int		ret;
420 
421 	tp->t_mgt_status_rcvd = B_FALSE;
422 
423 	/* write ORB address into MANAGEMENT_AGENT */
424 	SBP2_ADDR_SET(tp->t_mgt_cmd_data->b_rptr, tp->t_mgt_orb_buf.bb_baddr,
425 	    0);
426 	tp->t_mgt_cmd_data->b_wptr = tp->t_mgt_cmd_data->b_rptr + 8;
427 
428 	if ((ret = SBP2_WB(tp, tp->t_mgt_cmd, tp->t_mgt_agent,
429 	    tp->t_mgt_cmd_data, 8, berr)) != SBP2_SUCCESS) {
430 		return (ret);
431 	}
432 
433 	/* wait for login response */
434 	mutex_enter(&tp->t_mutex);
435 	until = ddi_get_lbolt() + drv_usectohz(tp->t_mot * 1000);
436 	ret = 1;
437 
438 	while (!tp->t_mgt_status_rcvd && (ret > 0)) {
439 		ret = cv_timedwait(&tp->t_mgt_status_cv, &tp->t_mutex, until);
440 	}
441 
442 	if (!tp->t_mgt_status_rcvd) {
443 		ret = SBP2_ETIMEOUT;
444 	} else if ((tp->t_mgt_status.st_param & SBP2_ST_RESP) ==
445 	    SBP2_ST_RESP_COMPLETE) {
446 		ret = SBP2_SUCCESS;
447 	} else {
448 		ret = SBP2_FAILURE;
449 	}
450 	mutex_exit(&tp->t_mutex);
451 
452 	return (ret);
453 }
454 
455 /*
456  * Send task management request, one of:
457  *
458  *	ABORT TASK, ABORT TASK SET, LOGICAL UNIT RESET, TARGET RESET
459  */
460 static int
461 sbp2_tgt_task_mgt_request(sbp2_tgt_t *tp, uint16_t id, int func, uint64_t orbp,
462     int *berr)
463 {
464 	sbp2_task_mgt_orb_t *torb;
465 	int		ret;
466 
467 	sbp2_mgt_agent_acquire(tp);
468 
469 	torb = (sbp2_task_mgt_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
470 	bzero(torb, sizeof (sbp2_task_mgt_orb_t));
471 	SBP2_ORBP_SET(torb->to_orb, orbp);
472 	torb->to_params = SBP2_SWAP16(func | SBP2_ORB_NOTIFY |
473 	    SBP2_ORB_RQ_FMT_SBP2);
474 	torb->to_login_id = SBP2_SWAP16(id);
475 	SBP2_ADDR_SET(torb->to_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
476 	    0);
477 
478 	ret = sbp2_tgt_mgt_request(tp, berr);
479 
480 	sbp2_mgt_agent_release(tp);
481 
482 	return (ret);
483 }
484 
485 int
486 sbp2_tgt_reset(sbp2_tgt_t *tp, int *berr)
487 {
488 	sbp2_lun_t	*lp = &tp->t_lun[0];
489 	int		ret;
490 
491 	/* issue TARGET RESET */
492 	if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
493 	    SBP2_ORB_MGT_FUNC_TARGET_RESET, 0, berr)) != SBP2_SUCCESS) {
494 		return (ret);
495 	}
496 
497 	return (SBP2_SUCCESS);
498 }
499 
500 int
501 sbp2_tgt_get_cfgrom(sbp2_tgt_t *tp, sbp2_cfgrom_t **crpp)
502 {
503 	*crpp = &tp->t_cfgrom;
504 	return (SBP2_SUCCESS);
505 }
506 
507 int
508 sbp2_tgt_get_lun_cnt(sbp2_tgt_t *tp)
509 {
510 	return (tp->t_nluns);
511 }
512 
513 sbp2_lun_t *
514 sbp2_tgt_get_lun(sbp2_tgt_t *tp, int num)
515 {
516 	if (num < tp->t_nluns) {
517 		return (&tp->t_lun[num]);
518 	} else {
519 		return (NULL);
520 	}
521 }
522 
523 /*
524  *
525  * --- lun routines
526  *
527  */
528 int
529 sbp2_lun_reset(sbp2_lun_t *lp, int *berr)
530 {
531 	sbp2_tgt_t	*tp = lp->l_tgt;
532 	sbp2_ses_t	*sp = lp->l_ses;
533 	sbp2_task_t	*task = NULL;
534 	int		ret;
535 
536 	/* issue LOGICAL UNIT RESET */
537 	if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
538 	    SBP2_ORB_MGT_FUNC_LUN_RESET, 0, berr)) != SBP2_SUCCESS) {
539 		return (ret);
540 	}
541 
542 	/* mark all pending tasks reset and notify the driver */
543 	mutex_enter(&sp->s_task_mutex);
544 	for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
545 		if (task->ts_state < SBP2_TASK_COMP) {
546 			task->ts_error = SBP2_TASK_ERR_LUN_RESET;
547 			task->ts_state = SBP2_TASK_COMP;
548 		}
549 	}
550 	mutex_exit(&sp->s_task_mutex);
551 
552 	sp->s_status_cb(sp->s_status_cb_arg, NULL);
553 
554 	return (SBP2_SUCCESS);
555 }
556 
557 int
558 sbp2_lun_login(sbp2_lun_t *lp, sbp2_ses_t **spp,
559     void (*cb)(void *, sbp2_task_t *), void *cb_arg, int *berr)
560 {
561 	sbp2_tgt_t	*tp = lp->l_tgt;
562 	sbp2_ses_t	*sp;
563 	sbp2_login_orb_t *lorb;
564 	int		ret;
565 
566 	if (cb == NULL) {
567 		return (SBP2_EINVAL);
568 	}
569 
570 	/* multiple sessions not supported yet */
571 	if (lp->l_ses != NULL) {
572 		return (SBP2_EALREADY);
573 	}
574 
575 	if ((ret = sbp2_ses_init(&sp, lp, cb, cb_arg)) != SBP2_SUCCESS) {
576 		return (ret);
577 	}
578 	lp->l_ses = sp;
579 
580 	sbp2_mgt_agent_acquire(tp);
581 
582 	/* prepare login ORB */
583 	mutex_enter(&tp->t_mutex);
584 	lorb = (sbp2_login_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
585 	bzero(lorb, sizeof (sbp2_login_orb_t));
586 	SBP2_ADDR_SET(lorb->lo_resp, tp->t_mgt_login_resp_buf.bb_baddr, 0);
587 	lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGIN |
588 	    SBP2_ORB_LOGIN_EXCL | SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
589 	lorb->lo_lun = SBP2_SWAP16(lp->l_lun);
590 	lorb->lo_resp_len = SBP2_SWAP16(tp->t_mgt_login_resp_buf.bb_len);
591 	SBP2_ADDR_SET(lorb->lo_status_fifo, sp->s_status_fifo_buf.bb_baddr, 0);
592 
593 	bzero(tp->t_mgt_login_resp_buf.bb_kaddr, sizeof (sbp2_login_resp_t));
594 
595 	lp->l_logged_in = B_FALSE;
596 	mutex_exit(&tp->t_mutex);
597 
598 	/* send request */
599 	if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) {
600 		sbp2_mgt_agent_release(tp);
601 		sbp2_ses_fini(lp->l_ses);
602 		lp->l_ses = NULL;
603 		return (ret);
604 	}
605 
606 	/* retrieve response data (XXX sanity checks?) */
607 	mutex_enter(&tp->t_mutex);
608 	(void) SBP2_SYNC_BUF(tp, &tp->t_mgt_login_resp_buf, 0, 0,
609 	    DDI_DMA_SYNC_FORKERNEL);
610 	bcopy(tp->t_mgt_login_resp_buf.bb_kaddr, &lp->l_login_resp,
611 	    sizeof (sbp2_login_resp_t));
612 
613 	/* convert from BE to native endianness */
614 	SBP2_SWAP16_1(lp->l_login_resp.lr_len);
615 	SBP2_SWAP16_1(lp->l_login_resp.lr_login_id);
616 	SBP2_SWAP32_2(lp->l_login_resp.lr_cmd_agent);
617 	SBP2_SWAP16_1(lp->l_login_resp.lr_reconnect_hold);
618 	lp->l_login_resp.lr_reconnect_hold++;
619 
620 	sp->s_agent_offset = SBP2_ADDR2UINT64(lp->l_login_resp.lr_cmd_agent);
621 
622 	lp->l_logged_in = B_TRUE;
623 	mutex_exit(&tp->t_mutex);
624 
625 	sbp2_mgt_agent_release(tp);
626 
627 	if ((ret = sbp2_agent_init(&sp->s_agent, sp->s_agent_offset, tp)) !=
628 	    SBP2_SUCCESS) {
629 		sbp2_ses_fini(sp);
630 		lp->l_ses = NULL;
631 		return (ret);
632 	}
633 
634 	*spp = lp->l_ses;
635 	return (SBP2_SUCCESS);
636 }
637 
638 /*ARGSUSED*/
639 int
640 sbp2_lun_logout(sbp2_lun_t *lp, sbp2_ses_t **sp, int *berr, boolean_t phys)
641 {
642 	sbp2_tgt_t	*tp = lp->l_tgt;
643 
644 	ASSERT(*sp == lp->l_ses);
645 
646 	mutex_enter(&tp->t_mutex);
647 	if (lp->l_logged_in) {
648 		lp->l_logged_in = B_FALSE;
649 		/* do physical LOGOUT if requested */
650 		if (phys) {
651 			mutex_exit(&tp->t_mutex);
652 			sbp2_lun_logout_orb(lp, tp, berr);
653 			mutex_enter(&tp->t_mutex);
654 		}
655 	}
656 
657 	sbp2_agent_fini(&lp->l_ses->s_agent);
658 	sbp2_ses_fini(lp->l_ses);
659 	lp->l_ses = NULL;
660 	*sp = NULL;
661 	mutex_exit(&tp->t_mutex);
662 
663 	return (SBP2_SUCCESS);
664 }
665 
666 /*
667  * Issue LOGOUT mgt orb and wait for response. We are not interested in
668  * the success at the time, since the device may be disconnected or hung,
669  * just trying to make the best effort.
670  */
671 static void
672 sbp2_lun_logout_orb(sbp2_lun_t *lp, sbp2_tgt_t *tp, int *berr)
673 {
674 	sbp2_logout_orb_t *lorb;
675 
676 	sbp2_mgt_agent_acquire(tp);
677 
678 	/* prepare logout ORB */
679 	lorb = (sbp2_logout_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
680 	bzero(lorb, sizeof (sbp2_logout_orb_t));
681 	lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGOUT |
682 	    SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
683 	lorb->lo_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id);
684 	SBP2_ADDR_SET(lorb->lo_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
685 	    0);
686 
687 	/* send request */
688 	(void) sbp2_tgt_mgt_request(tp, berr);
689 
690 	sbp2_mgt_agent_release(tp);
691 }
692 
693 static boolean_t
694 sbp2_lun_accepting_tasks(sbp2_lun_t *lp)
695 {
696 	sbp2_tgt_t	*tp = lp->l_tgt;
697 	boolean_t	ret;
698 
699 	mutex_enter(&tp->t_mutex);
700 	ret = ((lp->l_ses != NULL) && lp->l_logged_in && !lp->l_reconnecting);
701 	mutex_exit(&tp->t_mutex);
702 	return (ret);
703 }
704 
705 /*
706  *
707  * --- session routines
708  *
709  */
710 static int
711 sbp2_ses_init(sbp2_ses_t **spp, sbp2_lun_t *lp,
712     void (*cb)(void *, sbp2_task_t *), void *cb_arg)
713 {
714 	sbp2_tgt_t	*tp = lp->l_tgt;
715 	sbp2_ses_t	*sp;
716 	int		ret;
717 
718 	sp = kmem_zalloc(sizeof (sbp2_ses_t), KM_SLEEP);
719 
720 	sp->s_tgt = tp;
721 	sp->s_lun = lp;
722 	sp->s_status_cb = cb;
723 	sp->s_status_cb_arg = cb_arg;
724 
725 	mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER,
726 	    SBP2_GET_IBLOCK_COOKIE(tp));
727 	mutex_init(&sp->s_task_mutex, NULL, MUTEX_DRIVER,
728 	    SBP2_GET_IBLOCK_COOKIE(tp));
729 
730 	/*
731 	 * status FIFO for block requests
732 	 */
733 	sp->s_status_fifo_buf.bb_len = sizeof (sbp2_status_t);
734 	sp->s_status_fifo_buf.bb_flags = SBP2_BUS_BUF_WR_POSTED;
735 	sp->s_status_fifo_buf.bb_wb_cb = sbp2_status_fifo_wb_cb;
736 	sp->s_status_fifo_buf.bb_sbp2_priv = sp;
737 	if ((ret = SBP2_ALLOC_BUF(tp, &sp->s_status_fifo_buf)) !=
738 	    SBP2_SUCCESS) {
739 		sbp2_ses_fini(sp);
740 		return (ret);
741 	}
742 
743 	*spp = sp;
744 	return (SBP2_SUCCESS);
745 }
746 
747 
748 static void
749 sbp2_ses_fini(sbp2_ses_t *sp)
750 {
751 	sbp2_tgt_t	*tp = sp->s_lun->l_tgt;
752 
753 	if (sp->s_status_fifo_buf.bb_hdl != NULL) {
754 		SBP2_FREE_BUF(tp, &sp->s_status_fifo_buf);
755 	}
756 
757 	mutex_destroy(&sp->s_task_mutex);
758 	mutex_destroy(&sp->s_mutex);
759 
760 	kmem_free(sp, sizeof (sbp2_ses_t));
761 }
762 
763 int
764 sbp2_ses_reconnect(sbp2_ses_t *sp, int *berr, uint16_t nodeID)
765 {
766 	sbp2_tgt_t	*tp = sp->s_tgt;
767 	sbp2_lun_t	*lp = sp->s_lun;
768 	int		ret;
769 
770 	/* prevent new tasks from being submitted */
771 	mutex_enter(&tp->t_mutex);
772 	lp->l_reconnecting = B_TRUE;
773 	mutex_exit(&tp->t_mutex);
774 
775 	/*
776 	 * From 10.5 Task management event matrix:
777 	 *	Immediately upon detection of a bus reset, all command
778 	 *	block fetch agents transition to the reset state and
779 	 *	their associated task sets are cleared without
780 	 *	the return of completion status.
781 	 *
782 	 * Reset pending tasks so we can retry them later.
783 	 */
784 	sbp2_ses_reset_pending_tasks(sp, nodeID);
785 
786 	ret = sbp2_ses_reconnect_orb(sp, berr);
787 
788 	mutex_enter(&tp->t_mutex);
789 	lp->l_reconnecting = B_FALSE;
790 	mutex_exit(&tp->t_mutex);
791 
792 	return (ret);
793 }
794 
795 /*
796  * Send reconnect ORB. If operation fails, set lp->l_logged_in = B_FALSE.
797  */
798 static int
799 sbp2_ses_reconnect_orb(sbp2_ses_t *sp, int *berr)
800 {
801 	sbp2_tgt_t	*tp = sp->s_tgt;
802 	sbp2_lun_t	*lp = sp->s_lun;
803 	sbp2_agent_t	*ap = &sp->s_agent;
804 	sbp2_reconnect_orb_t *rorb;
805 	int		ret;
806 
807 	sbp2_mgt_agent_acquire(tp);
808 
809 	/* prepare login ORB */
810 	rorb = (sbp2_reconnect_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
811 	bzero(rorb, sizeof (sbp2_reconnect_orb_t));
812 	rorb->ro_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_RECONNECT |
813 	    SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
814 	rorb->ro_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id);
815 	SBP2_ADDR_SET(rorb->ro_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
816 	    0);
817 
818 	/* send request */
819 	if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) {
820 		mutex_enter(&tp->t_mutex);
821 		lp->l_logged_in = B_FALSE;
822 		mutex_exit(&tp->t_mutex);
823 	} else {
824 		/* after successful reset fetch agent is in RESET state */
825 		mutex_enter(&ap->a_mutex);
826 		ap->a_state = SBP2_AGENT_STATE_RESET;
827 		mutex_exit(&ap->a_mutex);
828 	}
829 
830 	sbp2_mgt_agent_release(tp);
831 
832 	return (ret);
833 }
834 
835 
836 static sbp2_task_t *
837 sbp2_ses_orbp2task(sbp2_ses_t *sp, uint64_t orbp)
838 {
839 	sbp2_task_t	*task;
840 
841 	mutex_enter(&sp->s_task_mutex);
842 	for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
843 		if (task->ts_buf->bb_baddr == orbp) {
844 			break;
845 		}
846 	}
847 	mutex_exit(&sp->s_task_mutex);
848 	return (task);
849 }
850 
851 /*
852  * This is where tasks (command ORB's) are signalled to the target.
853  * 'task' argument is allowed to be NULL, in which case the task will be
854  * taken from the current task list.
855  *
856  * Tasks are signalled one at a time by writing into ORB_POINTER register.
857  * While SBP-2 allows dynamic task list updates and using DOORBELL register,
858  * some devices have bugs that prevent using this strategy: e.g. some LaCie
859  * HDD's can corrupt data. Data integrity is more important than performance.
860  */
861 int
862 sbp2_ses_submit_task(sbp2_ses_t *sp, sbp2_task_t *new_task)
863 {
864 	sbp2_agent_t	*ap = &sp->s_agent;
865 	sbp2_tgt_t	*tp = sp->s_tgt;
866 	sbp2_task_t	*task;		/* task actually being submitted */
867 	boolean_t	callback;
868 	timeout_id_t	timeout_id;
869 	int		ret;
870 
871 	if (!sbp2_lun_accepting_tasks(sp->s_lun)) {
872 		return (SBP2_ENODEV);
873 	}
874 
875 	sbp2_agent_acquire(ap);	/* serialize */
876 
877 	mutex_enter(&ap->a_mutex);
878 
879 	/* if task provided, append it to the list */
880 	if (new_task != NULL) {
881 		ASSERT(new_task->ts_state == SBP2_TASK_INIT);
882 		sbp2_ses_append_task(sp, new_task);
883 	}
884 
885 	/* if there is already a task in flight, exit */
886 	if ((ap->a_active_task != NULL) &&
887 	    (ap->a_active_task->ts_state == SBP2_TASK_PEND)) {
888 		mutex_exit(&ap->a_mutex);
889 		sbp2_agent_release(ap);
890 		return (SBP2_SUCCESS);
891 	}
892 
893 	/* no active task, grab the first one on the list in INIT state */
894 	ap->a_active_task = sbp2_ses_find_task_state(sp, SBP2_TASK_INIT);
895 	if (ap->a_active_task == NULL) {
896 		mutex_exit(&ap->a_mutex);
897 		sbp2_agent_release(ap);
898 		return (SBP2_SUCCESS);
899 	}
900 	task = ap->a_active_task;
901 	task->ts_ses = sp;
902 	task->ts_state = SBP2_TASK_PEND;
903 
904 	/* can't work with a dead agent */
905 	if (sbp2_agent_keepalive(ap, &task->ts_bus_error) != SBP2_SUCCESS) {
906 		task->ts_error = SBP2_TASK_ERR_DEAD;
907 		goto error;
908 	}
909 
910 	/*
911 	 * In theory, we should schedule task timeout after it's been submitted.
912 	 * However, some fast tasks complete even before timeout is scheduled.
913 	 * To avoid additional complications in the code, schedule timeout now.
914 	 */
915 	ASSERT(task->ts_timeout_id == 0);
916 	task->ts_time_start = gethrtime();
917 	if (task->ts_timeout > 0) {
918 		task->ts_timeout_id = timeout(sbp2_task_timeout, task,
919 		    task->ts_timeout * drv_usectohz(1000000));
920 	}
921 
922 	/* notify fetch agent */
923 	ap->a_state = SBP2_AGENT_STATE_ACTIVE;
924 	mutex_exit(&ap->a_mutex);
925 	ret = sbp2_agent_write_orbp(ap, task->ts_buf->bb_baddr,
926 	    &task->ts_bus_error);
927 	tp->t_stat.stat_submit_orbp++;
928 	mutex_enter(&ap->a_mutex);
929 
930 	if (ret != SBP2_SUCCESS) {
931 		ap->a_state = SBP2_AGENT_STATE_DEAD;
932 		tp->t_stat.stat_status_dead++;
933 
934 		if (task->ts_timeout_id != 0) {
935 			timeout_id = task->ts_timeout_id;
936 			task->ts_timeout_id = 0;
937 			(void) untimeout(timeout_id);
938 		}
939 		task->ts_error = SBP2_TASK_ERR_BUS;
940 		goto error;
941 	}
942 
943 	mutex_exit(&ap->a_mutex);
944 
945 	sbp2_agent_release(ap);
946 	return (SBP2_SUCCESS);
947 
948 error:
949 	/*
950 	 * Return immediate error if failed task is the one being submitted,
951 	 * otherwise use callback.
952 	 */
953 	callback = (ap->a_active_task != new_task);
954 	task = ap->a_active_task;
955 	ap->a_active_task = NULL;
956 	mutex_exit(&ap->a_mutex);
957 	sbp2_agent_release(ap);
958 
959 	/*
960 	 * Remove task from the list. It is important not to change task state
961 	 * to SBP2_TASK_COMP while it's still on the list, to avoid race with
962 	 * upper layer driver (e.g. scsa1394).
963 	 */
964 	ret = sbp2_ses_remove_task(sp, new_task);
965 	ASSERT(ret == SBP2_SUCCESS);
966 	new_task->ts_state = SBP2_TASK_COMP;
967 
968 	if (callback) {
969 		sp->s_status_cb(sp->s_status_cb_arg, new_task);
970 		return (SBP2_SUCCESS);
971 	} else {
972 		/* upper layer driver is responsible to call nudge */
973 		return (SBP2_FAILURE);
974 	}
975 }
976 
977 void
978 sbp2_ses_nudge(sbp2_ses_t *sp)
979 {
980 	(void) sbp2_ses_submit_task(sp, NULL);
981 }
982 
983 /*
984  * append task to the task list
985  */
986 static void
987 sbp2_ses_append_task(sbp2_ses_t *sp, sbp2_task_t *task)
988 {
989 	sbp2_tgt_t	*tp = sp->s_tgt;
990 
991 	mutex_enter(&sp->s_task_mutex);
992 	if (sp->s_task_head == NULL) {
993 		ASSERT(sp->s_task_tail == NULL);
994 		ASSERT(sp->s_task_cnt == 0);
995 		task->ts_prev = task->ts_next = NULL;
996 		sp->s_task_head = sp->s_task_tail = task;
997 	} else {
998 		ASSERT(sp->s_task_cnt > 0);
999 		task->ts_next = NULL;
1000 		task->ts_prev = sp->s_task_tail;
1001 		sp->s_task_tail->ts_next = task;
1002 		sp->s_task_tail = task;
1003 	}
1004 	ASSERT(task != task->ts_prev);
1005 	ASSERT(task != task->ts_next);
1006 
1007 	sp->s_task_cnt++;
1008 	if (sp->s_task_cnt > tp->t_stat.stat_task_max) {
1009 		tp->t_stat.stat_task_max = sp->s_task_cnt;
1010 	}
1011 	mutex_exit(&sp->s_task_mutex);
1012 }
1013 
1014 /*
1015  * remove task from the task list
1016  */
1017 static int
1018 sbp2_ses_remove_task_locked(sbp2_ses_t *sp, sbp2_task_t *task)
1019 {
1020 	sp->s_task_cnt--;
1021 	if (task == sp->s_task_head) {			/* first */
1022 		ASSERT(task->ts_prev == NULL);
1023 		if (task->ts_next == NULL) {		/*   and last */
1024 			ASSERT(sp->s_task_cnt == 0);
1025 			sp->s_task_head = sp->s_task_tail = NULL;
1026 		} else {				/*   but not last */
1027 			sp->s_task_head = task->ts_next;
1028 			sp->s_task_head->ts_prev = NULL;
1029 		}
1030 	} else if (task == sp->s_task_tail) {		/* last but not first */
1031 		ASSERT(task->ts_next == NULL);
1032 		sp->s_task_tail = task->ts_prev;
1033 		sp->s_task_tail->ts_next = NULL;
1034 	} else {					/* in the middle */
1035 		task->ts_prev->ts_next = task->ts_next;
1036 		task->ts_next->ts_prev = task->ts_prev;
1037 	}
1038 	task->ts_prev = task->ts_next = NULL;
1039 	ASSERT(sp->s_task_cnt >= 0);
1040 
1041 	return (SBP2_SUCCESS);
1042 }
1043 
1044 int
1045 sbp2_ses_remove_task(sbp2_ses_t *sp, sbp2_task_t *task)
1046 {
1047 	int	ret;
1048 
1049 	mutex_enter(&sp->s_task_mutex);
1050 	ret = sbp2_ses_remove_task_locked(sp, task);
1051 	mutex_exit(&sp->s_task_mutex);
1052 
1053 	return (ret);
1054 }
1055 
1056 /*
1057  * Return first task on the list in specified state.
1058  */
1059 sbp2_task_t *
1060 sbp2_ses_find_task_state(sbp2_ses_t *sp, sbp2_task_state_t state)
1061 {
1062 	sbp2_task_t	*task = NULL;
1063 
1064 	mutex_enter(&sp->s_task_mutex);
1065 	for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
1066 		if (task->ts_state == state) {
1067 			break;
1068 		}
1069 	}
1070 	mutex_exit(&sp->s_task_mutex);
1071 
1072 	return (task);
1073 }
1074 
1075 /*
1076  * Remove first task on the list. Returns pointer to the removed task or NULL.
1077  */
1078 sbp2_task_t *
1079 sbp2_ses_remove_first_task(sbp2_ses_t *sp)
1080 {
1081 	sbp2_task_t	*task = NULL;
1082 
1083 	mutex_enter(&sp->s_task_mutex);
1084 	task = sp->s_task_head;
1085 	if (task != NULL) {
1086 		(void) sbp2_ses_remove_task_locked(sp, task);
1087 	}
1088 	mutex_exit(&sp->s_task_mutex);
1089 
1090 	return (task);
1091 }
1092 
1093 /*
1094  * Remove first task on the list only if it's in specified state.
1095  * Returns pointer to the removed task or NULL.
1096  */
1097 sbp2_task_t *
1098 sbp2_ses_remove_first_task_state(sbp2_ses_t *sp, sbp2_task_state_t state)
1099 {
1100 	sbp2_task_t	*task = NULL;
1101 
1102 	mutex_enter(&sp->s_task_mutex);
1103 	if ((sp->s_task_head != NULL) && (sp->s_task_head->ts_state == state)) {
1104 		task = sp->s_task_head;
1105 		(void) sbp2_ses_remove_task_locked(sp, task);
1106 	}
1107 	mutex_exit(&sp->s_task_mutex);
1108 
1109 	return (task);
1110 }
1111 
1112 /*
1113  * Remove first task on the list. If there's timeout, untimeout it.
1114  * Returns pointer to the removed task or NULL.
1115  */
1116 sbp2_task_t *
1117 sbp2_ses_cancel_first_task(sbp2_ses_t *sp)
1118 {
1119 	sbp2_task_t	*task = NULL;
1120 	timeout_id_t	timeout_id;
1121 
1122 	mutex_enter(&sp->s_task_mutex);
1123 	task = sp->s_task_head;
1124 	if (task != NULL) {
1125 		(void) sbp2_ses_remove_task_locked(sp, task);
1126 	}
1127 	mutex_exit(&sp->s_task_mutex);
1128 
1129 	if ((task != NULL) && ((timeout_id = task->ts_timeout_id) != 0)) {
1130 		task->ts_timeout_id = 0;
1131 		(void) untimeout(timeout_id);
1132 	}
1133 
1134 	return (task);
1135 }
1136 
1137 /*
1138  * Reset pending tasks on the list to their initial state.
1139  */
1140 static void
1141 sbp2_ses_reset_pending_tasks(sbp2_ses_t *sp, uint16_t nodeID)
1142 {
1143 	sbp2_agent_t	*ap = &sp->s_agent;
1144 	sbp2_task_t	*task = NULL;
1145 	timeout_id_t	timeout_id;
1146 	sbp2_cmd_orb_t	*orb;
1147 
1148 	mutex_enter(&sp->s_task_mutex);
1149 	for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
1150 		task->ts_state = SBP2_TASK_INIT;
1151 
1152 		/* cancel timeout */
1153 		if ((timeout_id = task->ts_timeout_id) != 0) {
1154 			task->ts_timeout_id = 0;
1155 			(void) untimeout(timeout_id);
1156 		}
1157 
1158 		/* update ORB nodeID */
1159 		orb = (sbp2_cmd_orb_t *)sbp2_task_orb_kaddr(task);
1160 		*(uint16_t *)orb->co_data_descr = SBP2_SWAP16(nodeID);
1161 		sbp2_task_orb_sync(sp->s_lun, task, DDI_DMA_SYNC_FORDEV);
1162 	}
1163 	mutex_exit(&sp->s_task_mutex);
1164 
1165 	mutex_enter(&ap->a_mutex);
1166 	ap->a_active_task = NULL;
1167 	mutex_exit(&ap->a_mutex);
1168 }
1169 
1170 int
1171 sbp2_ses_agent_reset(sbp2_ses_t *sp, int *berr)
1172 {
1173 	return (sbp2_agent_reset(&sp->s_agent, berr));
1174 }
1175 
1176 int
1177 sbp2_ses_abort_task(sbp2_ses_t *sp, sbp2_task_t *task, int *berr)
1178 {
1179 	sbp2_tgt_t	*tp = sp->s_tgt;
1180 	sbp2_lun_t	*lp = sp->s_lun;
1181 	uint16_t	params;
1182 	sbp2_cmd_orb_t	*orb = (sbp2_cmd_orb_t *)task->ts_buf->bb_kaddr;
1183 	int		ret = SBP2_SUCCESS;
1184 
1185 	/* mark ORB as dummy ORB */
1186 	params = (orb->co_params & ~SBP2_ORB_RQ_FMT) | SBP2_ORB_RQ_FMT_DUMMY;
1187 	orb->co_params = params;
1188 	(void) SBP2_SYNC_BUF(tp, task->ts_buf, 0, 0, DDI_DMA_SYNC_FORDEV);
1189 
1190 	ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
1191 	    SBP2_ORB_MGT_FUNC_ABORT_TASK, task->ts_buf->bb_baddr, berr);
1192 
1193 	return (ret);
1194 }
1195 
1196 
1197 int
1198 sbp2_ses_abort_task_set(sbp2_ses_t *sp, int *berr)
1199 {
1200 	sbp2_tgt_t	*tp = sp->s_tgt;
1201 	sbp2_lun_t	*lp = sp->s_lun;
1202 	int		ret;
1203 
1204 	ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
1205 	    SBP2_ORB_MGT_FUNC_ABORT_TASK_SET, 0, berr);
1206 
1207 	return (ret);
1208 }
1209 
1210 
1211 /*
1212  *
1213  * ORB functions
1214  *
1215  * allocate ORB resources
1216  *
1217  * we maintain a freelist of ORB's for faster allocation
1218  */
1219 /*ARGSUSED*/
1220 static sbp2_bus_buf_t *
1221 sbp2_orb_freelist_get(sbp2_lun_t *lp, sbp2_task_t *task, int len)
1222 {
1223 	sbp2_buf_list_t	*bl = &lp->l_orb_freelist;
1224 	sbp2_bus_buf_t	*buf = NULL;
1225 
1226 	mutex_enter(&bl->bl_mutex);
1227 	if ((bl->bl_head != NULL) && (bl->bl_head->bb_len == len)) {
1228 		buf = bl->bl_head;
1229 		bl->bl_head = buf->bb_next;
1230 		if (bl->bl_tail == buf) {	/* last one? */
1231 			ASSERT(bl->bl_head == NULL);
1232 			bl->bl_tail = NULL;
1233 		}
1234 		bl->bl_len--;
1235 		buf->bb_next = NULL;
1236 	}
1237 	mutex_exit(&bl->bl_mutex);
1238 
1239 	return (buf);
1240 }
1241 
1242 static int
1243 sbp2_orb_freelist_put(sbp2_lun_t *lp, sbp2_bus_buf_t *buf)
1244 {
1245 	sbp2_buf_list_t	*bl = &lp->l_orb_freelist;
1246 	int		ret;
1247 
1248 	mutex_enter(&bl->bl_mutex);
1249 	if (bl->bl_len < SBP2_ORB_FREELIST_MAX) {
1250 		if (bl->bl_head == NULL) {
1251 			ASSERT(bl->bl_tail == NULL);
1252 			bl->bl_head = bl->bl_tail = buf;
1253 		} else {
1254 			bl->bl_tail->bb_next = buf;
1255 			bl->bl_tail = buf;
1256 		}
1257 		buf->bb_next = NULL;
1258 		bl->bl_len++;
1259 		ret = SBP2_SUCCESS;
1260 	} else {
1261 		ret = SBP2_FAILURE;
1262 	}
1263 	mutex_exit(&bl->bl_mutex);
1264 
1265 	return (ret);
1266 }
1267 
1268 static void
1269 sbp2_orb_freelist_destroy(sbp2_lun_t *lp)
1270 {
1271 	sbp2_tgt_t	*tp = lp->l_tgt;
1272 	sbp2_buf_list_t	*bl = &lp->l_orb_freelist;
1273 	sbp2_bus_buf_t	*buf, *buf_next;
1274 
1275 	mutex_enter(&bl->bl_mutex);
1276 	for (buf = bl->bl_head; buf != NULL; ) {
1277 		SBP2_FREE_BUF(tp, buf);
1278 		buf_next = buf->bb_next;
1279 		kmem_free(buf, sizeof (sbp2_bus_buf_t));
1280 		buf = buf_next;
1281 	}
1282 	bl->bl_head = bl->bl_tail = NULL;
1283 	mutex_exit(&bl->bl_mutex);
1284 }
1285 
1286 int
1287 sbp2_task_orb_alloc(sbp2_lun_t *lp, sbp2_task_t *task, int len)
1288 {
1289 	sbp2_tgt_t	*tp = lp->l_tgt;
1290 	int		buf_len;
1291 	int		ret;
1292 
1293 	buf_len = SBP2_ORB_SIZE_ROUNDUP(tp, len);
1294 
1295 	/* try freelist first */
1296 	if ((task->ts_buf = sbp2_orb_freelist_get(lp, task, buf_len)) != NULL) {
1297 		return (SBP2_SUCCESS);
1298 	}
1299 
1300 	/* if no free buffers, allocate new */
1301 	task->ts_buf = kmem_zalloc(sizeof (sbp2_bus_buf_t), KM_SLEEP);
1302 	task->ts_buf->bb_len = buf_len;
1303 	task->ts_buf->bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RD;
1304 	if ((ret = SBP2_ALLOC_BUF(tp, task->ts_buf)) != SBP2_SUCCESS) {
1305 		kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t));
1306 		task->ts_buf = NULL;
1307 	}
1308 
1309 	return (ret);
1310 }
1311 
1312 void
1313 sbp2_task_orb_free(sbp2_lun_t *lp, sbp2_task_t *task)
1314 {
1315 	sbp2_tgt_t	*tp = lp->l_tgt;
1316 
1317 	if (task->ts_buf != NULL) {
1318 		if (sbp2_orb_freelist_put(lp, task->ts_buf) != SBP2_SUCCESS) {
1319 			SBP2_FREE_BUF(tp, task->ts_buf);
1320 			kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t));
1321 		}
1322 		task->ts_buf = NULL;
1323 	}
1324 }
1325 
1326 void *
1327 sbp2_task_orb_kaddr(sbp2_task_t *task)
1328 {
1329 	return (task->ts_buf->bb_kaddr);
1330 }
1331 
1332 void
1333 sbp2_task_orb_sync(sbp2_lun_t *lp, sbp2_task_t *task, int flags)
1334 {
1335 	(void) SBP2_SYNC_BUF(lp->l_tgt, task->ts_buf, 0, 0, flags);
1336 }
1337 
1338 /*
1339  *
1340  * --- fetch agent routines
1341  *
1342  */
1343 static int
1344 sbp2_agent_init(sbp2_agent_t *ap, uint64_t offset, sbp2_tgt_t *tp)
1345 {
1346 	int	ret;
1347 
1348 	/* paranoia */
1349 	if (offset == 0) {
1350 		return (SBP2_FAILURE);
1351 	}
1352 
1353 	ap->a_tgt = tp;
1354 
1355 	ap->a_reg_agent_state = offset + SBP2_AGENT_STATE_OFFSET;
1356 	ap->a_reg_agent_reset = offset + SBP2_AGENT_RESET_OFFSET;
1357 	ap->a_reg_orbp = offset + SBP2_ORB_POINTER_OFFSET;
1358 	ap->a_reg_doorbell = offset + SBP2_DOORBELL_OFFSET;
1359 	ap->a_reg_unsol_status_enable = offset +
1360 	    SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET;
1361 
1362 	/*
1363 	 * allocate bus commands
1364 	 */
1365 	if ((ret = SBP2_ALLOC_CMD(tp, &ap->a_cmd, 0)) != SBP2_SUCCESS) {
1366 		return (ret);
1367 	}
1368 	ap->a_cmd_data = allocb(sizeof (sbp2_orbp_t), BPRI_HI);
1369 	if (ap->a_cmd_data == NULL) {
1370 		sbp2_agent_fini(ap);
1371 		return (SBP2_ENOMEM);
1372 	}
1373 
1374 	mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER,
1375 	    SBP2_GET_IBLOCK_COOKIE(tp));
1376 	cv_init(&ap->a_cv, NULL, CV_DRIVER, NULL);
1377 
1378 #ifndef __lock_lint
1379 	ap->a_state = SBP2_AGENT_STATE_RESET;
1380 #endif
1381 
1382 	return (SBP2_SUCCESS);
1383 }
1384 
1385 
1386 static void
1387 sbp2_agent_fini(sbp2_agent_t *ap)
1388 {
1389 	sbp2_tgt_t	*tp = ap->a_tgt;
1390 
1391 	/* free bus commands */
1392 	if (ap->a_cmd != NULL) {
1393 		SBP2_FREE_CMD(tp, ap->a_cmd);
1394 	}
1395 	if (ap->a_cmd_data != NULL) {
1396 		freeb(ap->a_cmd_data);
1397 	}
1398 	cv_destroy(&ap->a_cv);
1399 	mutex_destroy(&ap->a_mutex);
1400 }
1401 
1402 
1403 static void
1404 sbp2_agent_acquire_locked(sbp2_agent_t *ap)
1405 {
1406 	while (ap->a_acquired) {
1407 		cv_wait(&ap->a_cv, &ap->a_mutex);
1408 	}
1409 	ap->a_acquired = B_TRUE;
1410 }
1411 
1412 
1413 static void
1414 sbp2_agent_release_locked(sbp2_agent_t *ap)
1415 {
1416 	ap->a_acquired = B_FALSE;
1417 	cv_signal(&ap->a_cv);		/* wake next waiter */
1418 }
1419 
1420 
1421 static void
1422 sbp2_agent_acquire(sbp2_agent_t *ap)
1423 {
1424 	mutex_enter(&ap->a_mutex);
1425 	sbp2_agent_acquire_locked(ap);
1426 	mutex_exit(&ap->a_mutex);
1427 }
1428 
1429 
1430 static void
1431 sbp2_agent_release(sbp2_agent_t *ap)
1432 {
1433 	mutex_enter(&ap->a_mutex);
1434 	sbp2_agent_release_locked(ap);
1435 	mutex_exit(&ap->a_mutex);
1436 }
1437 
1438 
1439 static int
1440 sbp2_agent_keepalive(sbp2_agent_t *ap, int *berr)
1441 {
1442 	boolean_t	acquired;
1443 	int		ret = SBP2_SUCCESS;
1444 
1445 	ASSERT(mutex_owned(&ap->a_mutex));
1446 
1447 	if (ap->a_state == SBP2_AGENT_STATE_DEAD) {
1448 		acquired = ap->a_acquired;
1449 		if (!acquired) {
1450 			sbp2_agent_acquire_locked(ap);
1451 		}
1452 
1453 		mutex_exit(&ap->a_mutex);
1454 		ret = sbp2_agent_reset(ap, berr);
1455 		mutex_enter(&ap->a_mutex);
1456 
1457 		if (!acquired) {
1458 			sbp2_agent_release_locked(ap);
1459 		}
1460 	}
1461 
1462 	return (ret);
1463 }
1464 
1465 #ifndef __lock_lint
1466 static int
1467 sbp2_agent_doorbell(sbp2_agent_t *ap, int *berr)
1468 {
1469 	return (SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_doorbell, 0, berr));
1470 }
1471 #endif
1472 
1473 /*
1474  * write into ORB_POINTER register and make sure it reached target
1475  *
1476  * From E.2: "If no acknowledgement is received by the initiator after a write
1477  * 	to the ORB_POINTER register, the initiator should not retry the write.
1478  *	The recommended method for error recovery is a write to the AGENT_RESET
1479  *	register." So we can retry, but not in case of timeout.
1480  */
1481 static int
1482 sbp2_agent_write_orbp(sbp2_agent_t *ap, uint64_t baddr, int *berr)
1483 {
1484 	int		i = 0;
1485 	int		ret;
1486 
1487 	SBP2_ORBP_SET(ap->a_cmd_data->b_rptr, baddr);
1488 	ap->a_cmd_data->b_wptr = ap->a_cmd_data->b_rptr + 8;
1489 
1490 	for (;;) {
1491 		ap->a_tgt->t_stat.stat_agent_worbp++;
1492 		if ((ret = SBP2_WB(ap->a_tgt, ap->a_cmd, ap->a_reg_orbp,
1493 		    ap->a_cmd_data, 8, berr)) == SBP2_SUCCESS) {
1494 			return (ret);
1495 		}
1496 		ap->a_tgt->t_stat.stat_agent_worbp_fail++;
1497 
1498 		if ((ret == SBP2_ETIMEOUT) ||
1499 		    (++i > sbp2_write_orbp_nretries)) {
1500 			break;
1501 		}
1502 		if (sbp2_write_orbp_delay > 0) {
1503 			drv_usecwait(sbp2_write_orbp_delay);
1504 		}
1505 	}
1506 
1507 	return (ret);
1508 }
1509 
1510 
1511 /*
1512  * reset fetch agent by writing into AGENT_RESET register
1513  */
1514 static int
1515 sbp2_agent_reset(sbp2_agent_t *ap, int *berr)
1516 {
1517 	int	i = 0;
1518 	int	ret;
1519 
1520 	for (;;) {
1521 		ap->a_tgt->t_stat.stat_agent_wreset++;
1522 		if ((ret = SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_agent_reset,
1523 		    0, berr)) == SBP2_SUCCESS) {
1524 			mutex_enter(&ap->a_mutex);
1525 			ap->a_state = SBP2_AGENT_STATE_RESET;
1526 			mutex_exit(&ap->a_mutex);
1527 			break;
1528 		}
1529 
1530 		ap->a_tgt->t_stat.stat_agent_wreset_fail++;
1531 		if (++i > sbp2_submit_reset_nretries) {
1532 			break;
1533 		}
1534 		if (sbp2_submit_reset_delay > 0) {
1535 			drv_usecwait(sbp2_submit_reset_delay);
1536 		}
1537 	}
1538 	return (ret);
1539 }
1540 
1541 /*
1542  *
1543  * --- callbacks and timeouts
1544  *
1545  */
1546 /*
1547  * Status FIFO callback for mgt ORB's.
1548  */
1549 /*ARGSUSED*/
1550 static void
1551 sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp)
1552 {
1553 	sbp2_tgt_t	*tp = buf->bb_sbp2_priv;
1554 	int		len;
1555 	sbp2_status_t	*st;
1556 	uint64_t	orbp;
1557 
1558 	len = MBLKL(*bpp);
1559 
1560 	/* 8 bytes minimum */
1561 	if (len < 8) {
1562 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH);
1563 		tp->t_stat.stat_status_short++;
1564 		return;
1565 	}
1566 
1567 	/* convert 2-quadlet header from BE to native endianness */
1568 	st = (sbp2_status_t *)(*bpp)->b_rptr;
1569 	SBP2_SWAP16_1(st->st_orb_offset_hi);
1570 	SBP2_SWAP32_1(st->st_orb_offset_lo);
1571 	orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo;
1572 
1573 	if (orbp != tp->t_mgt_orb_buf.bb_baddr) {
1574 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1575 		tp->t_stat.stat_status_mgt_notask++;
1576 		return;
1577 	}
1578 
1579 	/* make a local copy of status block */
1580 	bzero(&tp->t_mgt_status, sizeof (sbp2_status_t));
1581 	bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len);
1582 
1583 	SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1584 
1585 	/* wake up waiter */
1586 	mutex_enter(&tp->t_mutex);
1587 	tp->t_mgt_status_rcvd = B_TRUE;
1588 	cv_signal(&tp->t_mgt_status_cv);
1589 	mutex_exit(&tp->t_mutex);
1590 }
1591 
1592 static void
1593 sbp2_task_timeout(void *arg)
1594 {
1595 	sbp2_task_t	*task = arg;
1596 	sbp2_ses_t	*sp = task->ts_ses;
1597 	sbp2_agent_t	*ap = &sp->s_agent;
1598 
1599 	mutex_enter(&ap->a_mutex);
1600 
1601 	/* cancelled? */
1602 	if (task->ts_timeout_id == 0) {
1603 		mutex_exit(&ap->a_mutex);
1604 		return;
1605 	}
1606 	task->ts_timeout_id = 0;
1607 	task->ts_time_comp = gethrtime();
1608 
1609 	/* avoid race with other callbacks */
1610 	if (task->ts_state != SBP2_TASK_PEND) {
1611 		mutex_exit(&ap->a_mutex);
1612 		return;
1613 	}
1614 
1615 	if (task == ap->a_active_task) {
1616 		ap->a_active_task = NULL;
1617 	}
1618 	task->ts_error = SBP2_TASK_ERR_TIMEOUT;
1619 	task->ts_state = SBP2_TASK_COMP;
1620 
1621 	/* we mark agent DEAD so it's reset before next task is submitted */
1622 	ap->a_state = SBP2_AGENT_STATE_DEAD;
1623 	sp->s_tgt->t_stat.stat_status_dead++;
1624 	mutex_exit(&ap->a_mutex);
1625 
1626 	sp->s_status_cb(sp->s_status_cb_arg, task);
1627 }
1628 
1629 /*
1630  * Status FIFO callback for command ORB's. Also used for login ORB.
1631  */
1632 /*ARGSUSED*/
1633 static void
1634 sbp2_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp)
1635 {
1636 	sbp2_ses_t	*sp = buf->bb_sbp2_priv;
1637 	sbp2_tgt_t	*tp = sp->s_tgt;
1638 	sbp2_agent_t	*ap = &sp->s_agent;
1639 	int		len;
1640 	sbp2_status_t	*st;
1641 	uint8_t		src;
1642 	uint64_t	orbp;
1643 	sbp2_task_t	*task;
1644 	timeout_id_t	timeout_id;
1645 
1646 	len = MBLKL(*bpp);
1647 
1648 	/* 8 bytes minimum */
1649 	if (len < 8) {
1650 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH);
1651 		tp->t_stat.stat_status_short++;
1652 		return;
1653 	}
1654 
1655 	/* convert 2-quadlet header from BE32 to native endianness */
1656 	st = (sbp2_status_t *)(*bpp)->b_rptr;
1657 	SBP2_SWAP16_1(st->st_orb_offset_hi);
1658 	SBP2_SWAP32_1(st->st_orb_offset_lo);
1659 
1660 	orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo;
1661 
1662 	/* login ORB status? */
1663 	if (orbp == tp->t_mgt_orb_buf.bb_baddr) {
1664 		bzero(&tp->t_mgt_status, sizeof (sbp2_status_t));
1665 		bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len);
1666 
1667 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1668 
1669 		/* wake up waiter */
1670 		mutex_enter(&tp->t_mutex);
1671 		tp->t_mgt_status_rcvd = B_TRUE;
1672 		cv_signal(&tp->t_mgt_status_cv);
1673 		mutex_exit(&tp->t_mutex);
1674 		return;
1675 	}
1676 
1677 	/* dismiss unsolicited status */
1678 	src = st->st_param & SBP2_ST_SRC;
1679 	if (src == SBP2_ST_SRC_UNSOLICITED) {
1680 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1681 		tp->t_stat.stat_status_unsolicited++;
1682 		return;
1683 	}
1684 
1685 	/* find task corresponding to this ORB pointer */
1686 	if ((task = sbp2_ses_orbp2task(sp, orbp)) == NULL) {
1687 		SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1688 		tp->t_stat.stat_status_notask++;
1689 		return;
1690 	}
1691 
1692 	/*
1693 	 * Copy status block into a local buffer.
1694 	 *
1695 	 * Note: (ref: B.2) "SBP-2 permits the return of a status block between
1696 	 *	two and eight quadlets in length. When a truncated status block
1697 	 *	is stored, the omited quadlets shall be interpreted as if zero
1698 	 *	values were stored."
1699 	 */
1700 	bzero(&task->ts_status, sizeof (sbp2_status_t));
1701 	bcopy((*bpp)->b_rptr, &task->ts_status, len);
1702 
1703 	SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1704 
1705 	mutex_enter(&ap->a_mutex);
1706 
1707 	if ((timeout_id = task->ts_timeout_id) != 0) {
1708 		task->ts_timeout_id = 0;
1709 		(void) untimeout(timeout_id);
1710 	}
1711 
1712 	/* determine agent state */
1713 	if (st->st_param & SBP2_ST_DEAD) {
1714 		ap->a_state = SBP2_AGENT_STATE_DEAD;
1715 		tp->t_stat.stat_status_dead++;
1716 	}
1717 
1718 	/* avoid race with other callbacks */
1719 	if (task->ts_state != SBP2_TASK_PEND) {
1720 		mutex_exit(&ap->a_mutex);
1721 		return;
1722 	}
1723 
1724 	if (task == ap->a_active_task) {
1725 		ap->a_active_task = NULL;
1726 	}
1727 	task->ts_error = SBP2_TASK_ERR_NONE;
1728 	task->ts_state = SBP2_TASK_COMP;
1729 
1730 	mutex_exit(&ap->a_mutex);
1731 
1732 	sp->s_status_cb(sp->s_status_cb_arg, task);	/* notify the driver */
1733 }
1734 
1735 /*
1736  *
1737  * --- other
1738  *
1739  * since mgt agent is shared between LUNs and login sessions,
1740  * it is safer to serialize mgt requests
1741  */
1742 static void
1743 sbp2_mgt_agent_acquire(sbp2_tgt_t *tp)
1744 {
1745 	mutex_enter(&tp->t_mutex);
1746 	while (tp->t_mgt_agent_acquired) {
1747 		cv_wait(&tp->t_mgt_agent_cv, &tp->t_mutex);
1748 	}
1749 	tp->t_mgt_agent_acquired = B_TRUE;
1750 	mutex_exit(&tp->t_mutex);
1751 }
1752 
1753 static void
1754 sbp2_mgt_agent_release(sbp2_tgt_t *tp)
1755 {
1756 	mutex_enter(&tp->t_mutex);
1757 	tp->t_mgt_agent_acquired = B_FALSE;
1758 	cv_signal(&tp->t_mgt_agent_cv);	/* wake next waiter */
1759 	mutex_exit(&tp->t_mutex);
1760 }
1761