xref: /freebsd/sys/dev/firewire/sbp_targ.c (revision f5dc2263ab1be8a35a7e27e82103f9ccd41ae584)
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (C) 2003
5  * 	Hidetoshi Shimokawa. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *
18  *	This product includes software developed by Hidetoshi Shimokawa.
19  *
20  * 4. Neither the name of the author nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
42 #include <sys/conf.h>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
45 
46 #include <sys/bus.h>
47 #include <machine/bus.h>
48 
49 #include <dev/firewire/firewire.h>
50 #include <dev/firewire/firewirereg.h>
51 #include <dev/firewire/iec13213.h>
52 #include <dev/firewire/sbp.h>
53 #include <dev/firewire/fwmem.h>
54 
55 #include <cam/cam.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/cam_sim.h>
58 #include <cam/cam_xpt_sim.h>
59 #include <cam/cam_debug.h>
60 #include <cam/cam_periph.h>
61 #include <cam/scsi/scsi_all.h>
62 #include <cam/scsi/scsi_message.h>
63 
64 #define SBP_TARG_RECV_LEN	8
65 #define MAX_INITIATORS		8
66 #define MAX_LUN			63
67 #define MAX_LOGINS		63
68 #define MAX_NODES		63
69 /*
70  * management/command block agent registers
71  *
72  * BASE 0xffff f001 0000 management port
73  * BASE 0xffff f001 0020 command port for login id 0
74  * BASE 0xffff f001 0040 command port for login id 1
75  *
76  */
77 #define SBP_TARG_MGM	 0x10000	/* offset from 0xffff f000 000 */
78 #define SBP_TARG_BIND_HI	0xffff
79 #define SBP_TARG_BIND_LO(l)	(0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1))
80 #define SBP_TARG_BIND_START	(((u_int64_t)SBP_TARG_BIND_HI << 32) | \
81 				    SBP_TARG_BIND_LO(-1))
82 #define SBP_TARG_BIND_END	(((u_int64_t)SBP_TARG_BIND_HI << 32) | \
83 				    SBP_TARG_BIND_LO(MAX_LOGINS))
84 #define SBP_TARG_LOGIN_ID(lo)	(((lo) - SBP_TARG_BIND_LO(0))/0x20)
85 #define SBP_TARG_MAX_CHUNK	2048	/* max DMA chunk per xfer */
86 
87 #define FETCH_MGM	0
88 #define FETCH_CMD	1
89 #define FETCH_POINTER	2
90 
91 #define F_LINK_ACTIVE	(1 << 0)
92 #define F_ATIO_STARVED	(1 << 1)
93 #define F_LOGIN		(1 << 2)
94 #define F_HOLD		(1 << 3)
95 #define F_FREEZED	(1 << 4)
96 
97 static MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode");
98 
99 static int debug = 0;
100 
101 SYSCTL_INT(_debug, OID_AUTO, sbp_targ_debug, CTLFLAG_RW, &debug, 0,
102         "SBP target mode debug flag");
103 
104 struct sbp_targ_login {
105 	struct sbp_targ_lstate *lstate;
106 	struct fw_device *fwdev;
107 	struct sbp_login_res loginres;
108 	uint16_t fifo_hi;
109 	uint16_t last_hi;
110 	uint32_t fifo_lo;
111 	uint32_t last_lo;
112 	STAILQ_HEAD(, orb_info) orbs;
113 	STAILQ_ENTRY(sbp_targ_login) link;
114 	uint16_t hold_sec;
115 	uint16_t id;
116 	uint8_t flags;
117 	uint8_t spd;
118 	struct callout hold_callout;
119 };
120 
121 struct sbp_targ_lstate {
122 	uint16_t lun;
123 	struct sbp_targ_softc *sc;
124 	struct cam_path *path;
125 	struct ccb_hdr_slist accept_tios;
126 	struct ccb_hdr_slist immed_notifies;
127 	struct crom_chunk model;
128 	uint32_t flags;
129 	STAILQ_HEAD(, sbp_targ_login) logins;
130 };
131 
132 struct sbp_targ_softc {
133         struct firewire_dev_comm fd;
134 	struct cam_sim *sim;
135 	struct cam_path *path;
136 	struct fw_bind fwb;
137 	int ndevs;
138 	int flags;
139 	struct crom_chunk unit;
140 	struct sbp_targ_lstate *lstate[MAX_LUN];
141 	struct sbp_targ_lstate *black_hole;
142 	struct sbp_targ_login *logins[MAX_LOGINS];
143 	struct mtx mtx;
144 };
145 #define SBP_LOCK(sc) mtx_lock(&(sc)->mtx)
146 #define SBP_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
147 
148 struct corb4 {
149 #if BYTE_ORDER == BIG_ENDIAN
150 	uint32_t n:1,
151 		  rq_fmt:2,
152 		  :1,
153 		  dir:1,
154 		  spd:3,
155 		  max_payload:4,
156 		  page_table_present:1,
157 		  page_size:3,
158 		  data_size:16;
159 #else
160 	uint32_t data_size:16,
161 		  page_size:3,
162 		  page_table_present:1,
163 		  max_payload:4,
164 		  spd:3,
165 		  dir:1,
166 		  :1,
167 		  rq_fmt:2,
168 		  n:1;
169 #endif
170 };
171 
172 struct morb4 {
173 #if BYTE_ORDER == BIG_ENDIAN
174 	uint32_t n:1,
175 		  rq_fmt:2,
176 		  :9,
177 		  fun:4,
178 		  id:16;
179 #else
180 	uint32_t id:16,
181 		  fun:4,
182 		  :9,
183 		  rq_fmt:2,
184 		  n:1;
185 #endif
186 };
187 
188 
189 /*
190  * Urestricted page table format
191  * states that the segment length
192  * and high base addr are in the first
193  * 32 bits and the base low is in
194  * the second
195  */
196 struct unrestricted_page_table_fmt {
197 	uint16_t segment_len;
198 	uint16_t segment_base_high;
199 	uint32_t segment_base_low;
200 };
201 
202 
203 struct orb_info {
204 	struct sbp_targ_softc *sc;
205 	struct fw_device *fwdev;
206 	struct sbp_targ_login *login;
207 	union ccb *ccb;
208 	struct ccb_accept_tio *atio;
209 	uint8_t state;
210 #define ORBI_STATUS_NONE	0
211 #define ORBI_STATUS_FETCH	1
212 #define ORBI_STATUS_ATIO	2
213 #define ORBI_STATUS_CTIO	3
214 #define ORBI_STATUS_STATUS	4
215 #define ORBI_STATUS_POINTER	5
216 #define ORBI_STATUS_ABORTED	7
217 	uint8_t refcount;
218 	uint16_t orb_hi;
219 	uint32_t orb_lo;
220 	uint32_t data_hi;
221 	uint32_t data_lo;
222 	struct corb4 orb4;
223 	STAILQ_ENTRY(orb_info) link;
224 	uint32_t orb[8];
225 	struct unrestricted_page_table_fmt *page_table;
226 	struct unrestricted_page_table_fmt *cur_pte;
227 	struct unrestricted_page_table_fmt *last_pte;
228 	uint32_t  last_block_read;
229 	struct sbp_status status;
230 };
231 
232 static char *orb_fun_name[] = {
233 	ORB_FUN_NAMES
234 };
235 
236 static void sbp_targ_recv(struct fw_xfer *);
237 static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *,
238     uint16_t, uint32_t, struct sbp_targ_login *, int);
239 static void sbp_targ_xfer_pt(struct orb_info *);
240 static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *);
241 
242 static void
243 sbp_targ_identify(driver_t *driver, device_t parent)
244 {
245 	BUS_ADD_CHILD(parent, 0, "sbp_targ", device_get_unit(parent));
246 }
247 
248 static int
249 sbp_targ_probe(device_t dev)
250 {
251 	device_t pa;
252 
253 	if (fw_get_unit(dev) != NULL)
254 		return (ENXIO);
255 
256 	pa = device_get_parent(dev);
257 	if (device_get_unit(dev) != device_get_unit(pa))
258 		return (ENXIO);
259 
260 	device_set_desc(dev, "SBP-2/SCSI over FireWire target mode");
261 	return (0);
262 }
263 
264 static void
265 sbp_targ_dealloc_login(struct sbp_targ_login *login)
266 {
267 	struct orb_info *orbi, *next;
268 
269 	if (login == NULL) {
270 		printf("%s: login = NULL\n", __func__);
271 		return;
272 	}
273 	for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) {
274 		next = STAILQ_NEXT(orbi, link);
275 		if (debug)
276 			printf("%s: free orbi %p\n", __func__, orbi);
277 		free(orbi, M_SBP_TARG);
278 		orbi = NULL;
279 	}
280 	callout_stop(&login->hold_callout);
281 
282 	STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link);
283 	login->lstate->sc->logins[login->id] = NULL;
284 	if (debug)
285 		printf("%s: free login %p\n", __func__, login);
286 	free((void *)login, M_SBP_TARG);
287 	login = NULL;
288 }
289 
290 static void
291 sbp_targ_hold_expire(void *arg)
292 {
293 	struct sbp_targ_login *login;
294 
295 	login = (struct sbp_targ_login *)arg;
296 
297 	if (login->flags & F_HOLD) {
298 		printf("%s: login_id=%d expired\n", __func__, login->id);
299 		sbp_targ_dealloc_login(login);
300 	} else {
301 		printf("%s: login_id=%d not hold\n", __func__, login->id);
302 	}
303 }
304 
305 static void
306 sbp_targ_post_busreset(void *arg)
307 {
308 	struct sbp_targ_softc *sc;
309 	struct crom_src *src;
310 	struct crom_chunk *root;
311 	struct crom_chunk *unit;
312 	struct sbp_targ_lstate *lstate;
313 	struct sbp_targ_login *login;
314 	int i;
315 
316 	sc = (struct sbp_targ_softc *)arg;
317 	src = sc->fd.fc->crom_src;
318 	root = sc->fd.fc->crom_root;
319 
320 	unit = &sc->unit;
321 
322 	if ((sc->flags & F_FREEZED) == 0) {
323 		sc->flags |= F_FREEZED;
324 		xpt_freeze_simq(sc->sim, /*count*/1);
325 	} else {
326 		printf("%s: already freezed\n", __func__);
327 	}
328 
329 	bzero(unit, sizeof(struct crom_chunk));
330 
331 	crom_add_chunk(src, root, unit, CROM_UDIR);
332 	crom_add_entry(unit, CSRKEY_SPEC, CSRVAL_ANSIT10);
333 	crom_add_entry(unit, CSRKEY_VER, CSRVAL_T10SBP2);
334 	crom_add_entry(unit, CSRKEY_COM_SPEC, CSRVAL_ANSIT10);
335 	crom_add_entry(unit, CSRKEY_COM_SET, CSRVAL_SCSI);
336 
337 	crom_add_entry(unit, CROM_MGM, SBP_TARG_MGM >> 2);
338 	crom_add_entry(unit, CSRKEY_UNIT_CH, (10<<8) | 8);
339 
340 	for (i = 0; i < MAX_LUN; i++) {
341 		lstate = sc->lstate[i];
342 		if (lstate == NULL)
343 			continue;
344 		crom_add_entry(unit, CSRKEY_FIRM_VER, 1);
345 		crom_add_entry(unit, CROM_LUN, i);
346 		crom_add_entry(unit, CSRKEY_MODEL, 1);
347 		crom_add_simple_text(src, unit, &lstate->model, "TargetMode");
348 	}
349 
350 	/* Process for reconnection hold time */
351 	for (i = 0; i < MAX_LOGINS; i++) {
352 		login = sc->logins[i];
353 		if (login == NULL)
354 			continue;
355 		sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
356 		if (login->flags & F_LOGIN) {
357 			login->flags |= F_HOLD;
358 			callout_reset(&login->hold_callout,
359 			    hz * login->hold_sec,
360 			    sbp_targ_hold_expire, (void *)login);
361 		}
362 	}
363 }
364 
365 static void
366 sbp_targ_post_explore(void *arg)
367 {
368 	struct sbp_targ_softc *sc;
369 
370 	sc = (struct sbp_targ_softc *)arg;
371 	sc->flags &= ~F_FREEZED;
372 	xpt_release_simq(sc->sim, /*run queue*/TRUE);
373 	return;
374 }
375 
376 static cam_status
377 sbp_targ_find_devs(struct sbp_targ_softc *sc, union ccb *ccb,
378     struct sbp_targ_lstate **lstate, int notfound_failure)
379 {
380 	u_int lun;
381 
382 	/* XXX 0 is the only vaild target_id */
383 	if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD &&
384 	    ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
385 		*lstate = sc->black_hole;
386 		if (debug)
387 			printf("setting black hole for this target id(%d)\n", ccb->ccb_h.target_id);
388 		return (CAM_REQ_CMP);
389 	}
390 
391 	lun = ccb->ccb_h.target_lun;
392 	if (lun >= MAX_LUN)
393 		return (CAM_LUN_INVALID);
394 
395 	*lstate = sc->lstate[lun];
396 
397 	if (notfound_failure != 0 && *lstate == NULL) {
398 		if (debug)
399 			printf("%s: lstate for lun is invalid, target(%d), lun(%d)\n",
400 				__func__, ccb->ccb_h.target_id, lun);
401 		return (CAM_PATH_INVALID);
402 	} else
403 		if (debug)
404 			printf("%s: setting lstate for tgt(%d) lun(%d)\n",
405 				__func__,ccb->ccb_h.target_id, lun);
406 
407 	return (CAM_REQ_CMP);
408 }
409 
410 static void
411 sbp_targ_en_lun(struct sbp_targ_softc *sc, union ccb *ccb)
412 {
413 	struct ccb_en_lun *cel = &ccb->cel;
414 	struct sbp_targ_lstate *lstate;
415 	cam_status status;
416 
417 	status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
418 	if (status != CAM_REQ_CMP) {
419 		ccb->ccb_h.status = status;
420 		return;
421 	}
422 
423 	if (cel->enable != 0) {
424 		if (lstate != NULL) {
425 			xpt_print_path(ccb->ccb_h.path);
426 			printf("Lun already enabled\n");
427 			ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
428 			return;
429 		}
430 		if (cel->grp6_len != 0 || cel->grp7_len != 0) {
431 			ccb->ccb_h.status = CAM_REQ_INVALID;
432 			printf("Non-zero Group Codes\n");
433 			return;
434 		}
435 		lstate = (struct sbp_targ_lstate *)
436 		    malloc(sizeof(*lstate), M_SBP_TARG, M_NOWAIT | M_ZERO);
437 		if (lstate == NULL) {
438 			xpt_print_path(ccb->ccb_h.path);
439 			printf("Couldn't allocate lstate\n");
440 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
441 			return;
442 		} else {
443 			if (debug)
444 				printf("%s: malloc'd lstate %p\n",__func__, lstate);
445 		}
446 		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) {
447 			sc->black_hole = lstate;
448 			if (debug)
449 				printf("Blackhole set due to target id == %d\n",
450 					ccb->ccb_h.target_id);
451 		} else
452 			sc->lstate[ccb->ccb_h.target_lun] = lstate;
453 
454 		memset(lstate, 0, sizeof(*lstate));
455 		lstate->sc = sc;
456 		status = xpt_create_path(&lstate->path, /*periph*/NULL,
457 					 xpt_path_path_id(ccb->ccb_h.path),
458 					 xpt_path_target_id(ccb->ccb_h.path),
459 					 xpt_path_lun_id(ccb->ccb_h.path));
460 		if (status != CAM_REQ_CMP) {
461 			free(lstate, M_SBP_TARG);
462 			lstate = NULL;
463 			xpt_print_path(ccb->ccb_h.path);
464 			printf("Couldn't allocate path\n");
465 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
466 			return;
467 		}
468 		SLIST_INIT(&lstate->accept_tios);
469 		SLIST_INIT(&lstate->immed_notifies);
470 		STAILQ_INIT(&lstate->logins);
471 
472 		ccb->ccb_h.status = CAM_REQ_CMP;
473 		xpt_print_path(ccb->ccb_h.path);
474 		printf("Lun now enabled for target mode\n");
475 		/* bus reset */
476 		sc->fd.fc->ibr(sc->fd.fc);
477 	} else {
478 		struct sbp_targ_login *login, *next;
479 
480 		if (lstate == NULL) {
481 			ccb->ccb_h.status = CAM_LUN_INVALID;
482 			printf("Invalid lstate for this target\n");
483 			return;
484 		}
485 		ccb->ccb_h.status = CAM_REQ_CMP;
486 
487 		if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
488 			printf("ATIOs pending\n");
489 			ccb->ccb_h.status = CAM_REQ_INVALID;
490 		}
491 
492 		if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
493 			printf("INOTs pending\n");
494 			ccb->ccb_h.status = CAM_REQ_INVALID;
495 		}
496 
497 		if (ccb->ccb_h.status != CAM_REQ_CMP) {
498 			printf("status != CAM_REQ_CMP\n");
499 			return;
500 		}
501 
502 		xpt_print_path(ccb->ccb_h.path);
503 		printf("Target mode disabled\n");
504 		xpt_free_path(lstate->path);
505 
506 		for (login = STAILQ_FIRST(&lstate->logins); login != NULL;
507 		    login = next) {
508 			next = STAILQ_NEXT(login, link);
509 			sbp_targ_dealloc_login(login);
510 		}
511 
512 		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
513 			sc->black_hole = NULL;
514 		else
515 			sc->lstate[ccb->ccb_h.target_lun] = NULL;
516 		if (debug)
517 			printf("%s: free lstate %p\n", __func__, lstate);
518 		free(lstate, M_SBP_TARG);
519 		lstate = NULL;
520 
521 		/* bus reset */
522 		sc->fd.fc->ibr(sc->fd.fc);
523 	}
524 }
525 
526 static void
527 sbp_targ_send_lstate_events(struct sbp_targ_softc *sc,
528     struct sbp_targ_lstate *lstate)
529 {
530 }
531 
532 
533 static __inline void
534 sbp_targ_remove_orb_info_locked(struct sbp_targ_login *login, struct orb_info *orbi)
535 {
536 	STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
537 }
538 
539 static __inline void
540 sbp_targ_remove_orb_info(struct sbp_targ_login *login, struct orb_info *orbi)
541 {
542 	SBP_LOCK(orbi->sc);
543 	STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
544 	SBP_UNLOCK(orbi->sc);
545 }
546 
547 /*
548  * tag_id/init_id encoding
549  *
550  * tag_id and init_id has only 32bit for each.
551  * scsi_target can handle very limited number(up to 15) of init_id.
552  * we have to encode 48bit orb and 64bit EUI64 into these
553  * variables.
554  *
555  * tag_id represents lower 32bit of ORB address.
556  * init_id represents login_id.
557  *
558  */
559 
560 static struct orb_info *
561 sbp_targ_get_orb_info(struct sbp_targ_lstate *lstate,
562     u_int tag_id, u_int init_id)
563 {
564 	struct sbp_targ_login *login;
565 	struct orb_info *orbi;
566 
567 	login = lstate->sc->logins[init_id];
568 	if (login == NULL) {
569 		printf("%s: no such login\n", __func__);
570 		return (NULL);
571 	}
572 	STAILQ_FOREACH(orbi, &login->orbs, link)
573 		if (orbi->orb_lo == tag_id)
574 			goto found;
575 	printf("%s: orb not found tag_id=0x%08x init_id=%d\n",
576 			 __func__, tag_id, init_id);
577 	return (NULL);
578 found:
579 	return (orbi);
580 }
581 
582 static void
583 sbp_targ_abort(struct sbp_targ_softc *sc, struct orb_info *orbi)
584 {
585 	struct orb_info *norbi;
586 
587 	SBP_LOCK(sc);
588 	for (; orbi != NULL; orbi = norbi) {
589 		printf("%s: status=%d ccb=%p\n", __func__, orbi->state, orbi->ccb);
590 		norbi = STAILQ_NEXT(orbi, link);
591 		if (orbi->state != ORBI_STATUS_ABORTED) {
592 			if (orbi->ccb != NULL) {
593 				orbi->ccb->ccb_h.status = CAM_REQ_ABORTED;
594 				xpt_done(orbi->ccb);
595 				orbi->ccb = NULL;
596 			}
597 			if (orbi->state <= ORBI_STATUS_ATIO) {
598 				sbp_targ_remove_orb_info_locked(orbi->login, orbi);
599 				if (debug)
600 					printf("%s: free orbi %p\n", __func__, orbi);
601 				free(orbi, M_SBP_TARG);
602 				orbi = NULL;
603 			} else
604 				orbi->state = ORBI_STATUS_ABORTED;
605 		}
606 	}
607 	SBP_UNLOCK(sc);
608 }
609 
610 static void
611 sbp_targ_free_orbi(struct fw_xfer *xfer)
612 {
613 	struct orb_info *orbi;
614 
615 	if (xfer->resp != 0) {
616 		/* XXX */
617 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
618 	}
619 	orbi = (struct orb_info *)xfer->sc;
620 	if ( orbi->page_table != NULL ) {
621 		if (debug)
622 			printf("%s:  free orbi->page_table %p\n", __func__, orbi->page_table);
623 		free(orbi->page_table, M_SBP_TARG);
624 		orbi->page_table = NULL;
625 	}
626 	if (debug)
627 		printf("%s: free orbi %p\n", __func__, orbi);
628 	free(orbi, M_SBP_TARG);
629 	orbi = NULL;
630 	fw_xfer_free(xfer);
631 }
632 
633 static void
634 sbp_targ_status_FIFO(struct orb_info *orbi,
635     uint32_t fifo_hi, uint32_t fifo_lo, int dequeue)
636 {
637 	struct fw_xfer *xfer;
638 
639 	if (dequeue)
640 		sbp_targ_remove_orb_info(orbi->login, orbi);
641 
642 	xfer = fwmem_write_block(orbi->fwdev, (void *)orbi,
643 	    /*spd*/FWSPD_S400, fifo_hi, fifo_lo,
644 	    sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status,
645 	    sbp_targ_free_orbi);
646 
647 	if (xfer == NULL) {
648 		/* XXX */
649 		printf("%s: xfer == NULL\n", __func__);
650 	}
651 }
652 
653 /*
654  * Generate the appropriate CAM status for the
655  * target.
656  */
657 static void
658 sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb)
659 {
660 	struct sbp_status *sbp_status;
661 #if	0
662 	struct orb_info *norbi;
663 #endif
664 
665 	sbp_status = &orbi->status;
666 
667 	orbi->state = ORBI_STATUS_STATUS;
668 
669 	sbp_status->resp = 0; /* XXX */
670 	sbp_status->status = 0; /* XXX */
671 	sbp_status->dead = 0; /* XXX */
672 
673 	ccb->ccb_h.status= CAM_REQ_CMP;
674 
675 	switch (ccb->csio.scsi_status) {
676 	case SCSI_STATUS_OK:
677 		if (debug)
678 			printf("%s: STATUS_OK\n", __func__);
679 		sbp_status->len = 1;
680 		break;
681 	case SCSI_STATUS_CHECK_COND:
682 		if (debug)
683 			printf("%s: STATUS SCSI_STATUS_CHECK_COND\n", __func__);
684 		goto process_scsi_status;
685 	case SCSI_STATUS_BUSY:
686 		if (debug)
687 			printf("%s: STATUS SCSI_STATUS_BUSY\n", __func__);
688 		goto process_scsi_status;
689 	case SCSI_STATUS_CMD_TERMINATED:
690 process_scsi_status:
691 	{
692 		struct sbp_cmd_status *sbp_cmd_status;
693 		struct scsi_sense_data *sense;
694 		int error_code, sense_key, asc, ascq;
695 		uint8_t stream_bits;
696 		uint8_t sks[3];
697 		uint64_t info;
698 		int64_t sinfo;
699 		int sense_len;
700 
701 		sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0];
702 		sbp_cmd_status->status = ccb->csio.scsi_status;
703 		sense = &ccb->csio.sense_data;
704 
705 
706 		sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
707 		scsi_extract_sense_len(sense, sense_len, &error_code,
708 		    &sense_key, &asc, &ascq, /*show_errors*/ 0);
709 
710 		switch (error_code) {
711 		case SSD_CURRENT_ERROR:
712 		case SSD_DESC_CURRENT_ERROR:
713 			sbp_cmd_status->sfmt = SBP_SFMT_CURR;
714 			break;
715 		default:
716 			sbp_cmd_status->sfmt = SBP_SFMT_DEFER;
717 			break;
718 		}
719 
720 		if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info,
721 					&sinfo) == 0) {
722 			uint32_t info_trunc;
723 			sbp_cmd_status->valid = 1;
724 			info_trunc = info;
725 
726 			sbp_cmd_status->info = htobe32(info_trunc);
727 		} else {
728 			sbp_cmd_status->valid = 0;
729 		}
730 
731 		sbp_cmd_status->s_key = sense_key;
732 
733 		if (scsi_get_stream_info(sense, sense_len, NULL,
734 					 &stream_bits) == 0) {
735 			sbp_cmd_status->mark =
736 			    (stream_bits & SSD_FILEMARK) ? 1 : 0;
737 			sbp_cmd_status->eom =
738 			    (stream_bits & SSD_EOM) ? 1 : 0;
739 			sbp_cmd_status->ill_len =
740 			    (stream_bits & SSD_ILI) ? 1 : 0;
741 		} else {
742 			sbp_cmd_status->mark = 0;
743 			sbp_cmd_status->eom = 0;
744 			sbp_cmd_status->ill_len = 0;
745 		}
746 
747 
748 		/* add_sense_code(_qual), info, cmd_spec_info */
749 		sbp_status->len = 4;
750 
751 		if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND,
752 					&info, &sinfo) == 0) {
753 			uint32_t cmdspec_trunc;
754 
755 			cmdspec_trunc = info;
756 
757 			sbp_cmd_status->cdb = htobe32(cmdspec_trunc);
758 		}
759 
760 		sbp_cmd_status->s_code = asc;
761 		sbp_cmd_status->s_qlfr = ascq;
762 
763 		if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU, &info,
764 					&sinfo) == 0) {
765 			sbp_cmd_status->fru = (uint8_t)info;
766 			sbp_status->len = 5;
767 		} else {
768 			sbp_cmd_status->fru = 0;
769 		}
770 
771 		if (scsi_get_sks(sense, sense_len, sks) == 0) {
772 			bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks));
773 			sbp_status->len = 5;
774 			ccb->ccb_h.status |= CAM_SENT_SENSE;
775 		}
776 
777 		break;
778 	}
779 	default:
780 		printf("%s: unknown scsi status 0x%x\n", __func__,
781 		    sbp_status->status);
782 	}
783 
784 
785 	sbp_targ_status_FIFO(orbi,
786 	    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
787 }
788 
789 /*
790  * Invoked as a callback handler from fwmem_read/write_block
791  *
792  * Process read/write of initiator address space
793  * completion and pass status onto the backend target.
794  * If this is a partial read/write for a CCB then
795  * we decrement the orbi's refcount to indicate
796  * the status of the read/write is complete
797  */
798 static void
799 sbp_targ_cam_done(struct fw_xfer *xfer)
800 {
801 	struct orb_info *orbi;
802 	union ccb *ccb;
803 
804 	orbi = (struct orb_info *)xfer->sc;
805 
806 	if (debug)
807 		printf("%s: resp=%d refcount=%d\n", __func__,
808 			xfer->resp, orbi->refcount);
809 
810 	if (xfer->resp != 0) {
811 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
812 		orbi->status.resp = SBP_TRANS_FAIL;
813 		orbi->status.status = OBJ_DATA | SBE_TIMEOUT/*XXX*/;
814 		orbi->status.dead = 1;
815 		sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
816 	}
817 
818 	orbi->refcount--;
819 
820 	ccb = orbi->ccb;
821 	if (orbi->refcount == 0) {
822 		orbi->ccb = NULL;
823 		if (orbi->state == ORBI_STATUS_ABORTED) {
824 			if (debug)
825 				printf("%s: orbi aborted\n", __func__);
826 			sbp_targ_remove_orb_info(orbi->login, orbi);
827 			if (orbi->page_table != NULL) {
828 				if (debug)
829 					printf("%s: free orbi->page_table %p\n",
830 						__func__, orbi->page_table);
831 				free(orbi->page_table, M_SBP_TARG);
832 			}
833 			if (debug)
834 				printf("%s: free orbi %p\n", __func__, orbi);
835 			free(orbi, M_SBP_TARG);
836 			orbi = NULL;
837 		} else if (orbi->status.resp == ORBI_STATUS_NONE) {
838 			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
839 				if (debug)
840 					printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags);
841 				sbp_targ_send_status(orbi, ccb);
842 			} else {
843 				if (debug)
844 					printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags);
845 				ccb->ccb_h.status = CAM_REQ_CMP;
846 			}
847 			xpt_done(ccb);
848 		} else {
849 			orbi->status.len = 1;
850 			sbp_targ_status_FIFO(orbi,
851 		    	    orbi->login->fifo_hi, orbi->login->fifo_lo,
852 			    /*dequeue*/1);
853 			ccb->ccb_h.status = CAM_REQ_ABORTED;
854 			xpt_done(ccb);
855 		}
856 	}
857 
858 	fw_xfer_free(xfer);
859 }
860 
861 static cam_status
862 sbp_targ_abort_ccb(struct sbp_targ_softc *sc, union ccb *ccb)
863 {
864 	union ccb *accb;
865 	struct sbp_targ_lstate *lstate;
866 	struct ccb_hdr_slist *list;
867 	struct ccb_hdr *curelm;
868 	int found;
869 	cam_status status;
870 
871 	status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
872 	if (status != CAM_REQ_CMP)
873 		return (status);
874 
875 	accb = ccb->cab.abort_ccb;
876 
877 	if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
878 		list = &lstate->accept_tios;
879 	else if (accb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY)
880 		list = &lstate->immed_notifies;
881 	else
882 		return (CAM_UA_ABORT);
883 
884 	curelm = SLIST_FIRST(list);
885 	found = 0;
886 	if (curelm == &accb->ccb_h) {
887 		found = 1;
888 		SLIST_REMOVE_HEAD(list, sim_links.sle);
889 	} else {
890 		while (curelm != NULL) {
891 			struct ccb_hdr *nextelm;
892 
893 			nextelm = SLIST_NEXT(curelm, sim_links.sle);
894 			if (nextelm == &accb->ccb_h) {
895 				found = 1;
896 				SLIST_NEXT(curelm, sim_links.sle) =
897 				    SLIST_NEXT(nextelm, sim_links.sle);
898 				break;
899 			}
900 			curelm = nextelm;
901 		}
902 	}
903 	if (found) {
904 		accb->ccb_h.status = CAM_REQ_ABORTED;
905 		xpt_done(accb);
906 		return (CAM_REQ_CMP);
907 	}
908 	printf("%s: not found\n", __func__);
909 	return (CAM_PATH_INVALID);
910 }
911 
912 /*
913  * directly execute a read or write to the initiator
914  * address space and set hand(sbp_targ_cam_done) to
915  * process the completion from the SIM to the target.
916  * set orbi->refcount to inidicate that a read/write
917  * is inflight to/from the initiator.
918  */
919 static void
920 sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset,
921     uint16_t dst_hi, uint32_t dst_lo, u_int size,
922     void (*hand)(struct fw_xfer *))
923 {
924 	struct fw_xfer *xfer;
925 	u_int len, ccb_dir, off = 0;
926 	char *ptr;
927 
928 	if (debug > 1)
929 		printf("%s: offset=%d size=%d\n", __func__, offset, size);
930 	ccb_dir = orbi->ccb->ccb_h.flags & CAM_DIR_MASK;
931 	ptr = (char *)orbi->ccb->csio.data_ptr + offset;
932 
933 	while (size > 0) {
934 		/* XXX assume dst_lo + off doesn't overflow */
935 		len = MIN(size, SBP_TARG_MAX_CHUNK);
936 		size -= len;
937 		orbi->refcount ++;
938 		if (ccb_dir == CAM_DIR_OUT) {
939 			if (debug)
940 				printf("%s: CAM_DIR_OUT --> read block in?\n",__func__);
941 			xfer = fwmem_read_block(orbi->fwdev,
942 			   (void *)orbi, /*spd*/FWSPD_S400,
943 			    dst_hi, dst_lo + off, len,
944 			    ptr + off, hand);
945 		} else {
946 			if (debug)
947 				printf("%s: CAM_DIR_IN --> write block out?\n",__func__);
948 			xfer = fwmem_write_block(orbi->fwdev,
949 			   (void *)orbi, /*spd*/FWSPD_S400,
950 			    dst_hi, dst_lo + off, len,
951 			    ptr + off, hand);
952 		}
953 		if (xfer == NULL) {
954 			printf("%s: xfer == NULL", __func__);
955 			/* XXX what should we do?? */
956 			orbi->refcount--;
957 		}
958 		off += len;
959 	}
960 }
961 
962 static void
963 sbp_targ_pt_done(struct fw_xfer *xfer)
964 {
965 	struct orb_info *orbi;
966 	struct unrestricted_page_table_fmt *pt;
967 	uint32_t i;
968 
969 	orbi = (struct orb_info *)xfer->sc;
970 
971 	if (orbi->state == ORBI_STATUS_ABORTED) {
972 		if (debug)
973 			printf("%s: orbi aborted\n", __func__);
974 		sbp_targ_remove_orb_info(orbi->login, orbi);
975 		if (debug) {
976 			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
977 			printf("%s: free orbi %p\n", __func__, orbi);
978 		}
979 		free(orbi->page_table, M_SBP_TARG);
980 		free(orbi, M_SBP_TARG);
981 		orbi = NULL;
982 		fw_xfer_free(xfer);
983 		return;
984 	}
985 	if (xfer->resp != 0) {
986 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
987 		orbi->status.resp = SBP_TRANS_FAIL;
988 		orbi->status.status = OBJ_PT | SBE_TIMEOUT/*XXX*/;
989 		orbi->status.dead = 1;
990 		orbi->status.len = 1;
991 		sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
992 
993 		if (debug)
994 			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
995 
996 		sbp_targ_status_FIFO(orbi,
997 		    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
998 		free(orbi->page_table, M_SBP_TARG);
999 		orbi->page_table = NULL;
1000 		fw_xfer_free(xfer);
1001 		return;
1002 	}
1003 	orbi->refcount++;
1004 /*
1005  * Set endianness here so we don't have
1006  * to deal with is later
1007  */
1008 	for (i = 0, pt = orbi->page_table; i < orbi->orb4.data_size; i++, pt++) {
1009 		pt->segment_len = ntohs(pt->segment_len);
1010 		if (debug)
1011 			printf("%s:segment_len = %u\n", __func__,pt->segment_len);
1012 		pt->segment_base_high = ntohs(pt->segment_base_high);
1013 		pt->segment_base_low = ntohl(pt->segment_base_low);
1014 	}
1015 
1016 	sbp_targ_xfer_pt(orbi);
1017 
1018 	orbi->refcount--;
1019 	if (orbi->refcount == 0)
1020 		printf("%s: refcount == 0\n", __func__);
1021 
1022 	fw_xfer_free(xfer);
1023 	return;
1024 }
1025 
1026 static void sbp_targ_xfer_pt(struct orb_info *orbi)
1027 {
1028 	union ccb *ccb;
1029 	uint32_t res, offset, len;
1030 
1031 	ccb = orbi->ccb;
1032 	if (debug)
1033 		printf("%s: dxfer_len=%d\n", __func__, ccb->csio.dxfer_len);
1034 	res = ccb->csio.dxfer_len;
1035 	/*
1036 	 * If the page table required multiple CTIO's to
1037 	 * complete, then cur_pte is non NULL
1038 	 * and we need to start from the last position
1039 	 * If this is the first pass over a page table
1040 	 * then we just start at the beginning of the page
1041 	 * table.
1042 	 *
1043 	 * Parse the unrestricted page table and figure out where we need
1044 	 * to shove the data from this read request.
1045 	 */
1046 	for (offset = 0, len = 0; (res != 0) && (orbi->cur_pte < orbi->last_pte); offset += len) {
1047 		len = MIN(orbi->cur_pte->segment_len, res);
1048 		res -= len;
1049 		if (debug)
1050 			printf("%s:page_table: %04x:%08x segment_len(%u) res(%u) len(%u)\n",
1051 				__func__, orbi->cur_pte->segment_base_high,
1052 				orbi->cur_pte->segment_base_low,
1053 				orbi->cur_pte->segment_len,
1054 				res, len);
1055 		sbp_targ_xfer_buf(orbi, offset,
1056 				orbi->cur_pte->segment_base_high,
1057 				orbi->cur_pte->segment_base_low,
1058 				len, sbp_targ_cam_done);
1059 		/*
1060 		 * If we have only written partially to
1061 		 * this page table, then we need to save
1062 		 * our position for the next CTIO.  If we
1063 		 * have completed the page table, then we
1064 		 * are safe to move on to the next entry.
1065 		 */
1066 		if (len == orbi->cur_pte->segment_len) {
1067 			orbi->cur_pte++;
1068 		} else {
1069 			uint32_t saved_base_low;
1070 
1071 			/* Handle transfers that cross a 4GB boundary. */
1072 			saved_base_low = orbi->cur_pte->segment_base_low;
1073 			orbi->cur_pte->segment_base_low += len;
1074 			if (orbi->cur_pte->segment_base_low < saved_base_low)
1075 				orbi->cur_pte->segment_base_high++;
1076 
1077 			orbi->cur_pte->segment_len -= len;
1078 		}
1079 	}
1080 	if (debug) {
1081 		printf("%s: base_low(%08x) page_table_off(%p) last_block(%u)\n",
1082 			__func__, orbi->cur_pte->segment_base_low,
1083 			orbi->cur_pte, orbi->last_block_read);
1084 	}
1085 	if (res != 0)
1086 		printf("Warning - short pt encountered.  "
1087 			"Could not transfer all data.\n");
1088 	return;
1089 }
1090 
1091 /*
1092  * Create page table in local memory
1093  * and transfer it from the initiator
1094  * in order to know where we are supposed
1095  * to put the data.
1096  */
1097 
1098 static void
1099 sbp_targ_fetch_pt(struct orb_info *orbi)
1100 {
1101 	struct fw_xfer *xfer;
1102 
1103 	/*
1104 	 * Pull in page table from initiator
1105 	 * and setup for data from our
1106 	 * backend device.
1107 	 */
1108 	if (orbi->page_table == NULL) {
1109 		orbi->page_table = malloc(orbi->orb4.data_size*
1110 					  sizeof(struct unrestricted_page_table_fmt),
1111 					  M_SBP_TARG, M_NOWAIT|M_ZERO);
1112 		if (orbi->page_table == NULL)
1113 			goto error;
1114 		orbi->cur_pte = orbi->page_table;
1115 		orbi->last_pte = orbi->page_table + orbi->orb4.data_size;
1116 		orbi->last_block_read = orbi->orb4.data_size;
1117 		if (debug && orbi->page_table != NULL)
1118 			printf("%s: malloc'd orbi->page_table(%p), orb4.data_size(%u)\n",
1119  				__func__, orbi->page_table, orbi->orb4.data_size);
1120 
1121 		xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/FWSPD_S400,
1122 					orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*
1123 					sizeof(struct unrestricted_page_table_fmt),
1124 					(void *)orbi->page_table, sbp_targ_pt_done);
1125 
1126 		if (xfer != NULL)
1127 			return;
1128 	} else {
1129 		/*
1130 		 * This is a CTIO for a page table we have
1131 		 * already malloc'd, so just directly invoke
1132 		 * the xfer function on the orbi.
1133 		 */
1134 		sbp_targ_xfer_pt(orbi);
1135 		return;
1136 	}
1137 error:
1138 	orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1139 	if (debug)
1140 		printf("%s: free orbi->page_table %p due to xfer == NULL\n", __func__, orbi->page_table);
1141 	if (orbi->page_table != NULL) {
1142 		free(orbi->page_table, M_SBP_TARG);
1143 		orbi->page_table = NULL;
1144 	}
1145 	xpt_done(orbi->ccb);
1146 	return;
1147 }
1148 
1149 static void
1150 sbp_targ_action1(struct cam_sim *sim, union ccb *ccb)
1151 {
1152 	struct sbp_targ_softc *sc;
1153 	struct sbp_targ_lstate *lstate;
1154 	cam_status status;
1155 	u_int ccb_dir;
1156 
1157 	sc =  (struct sbp_targ_softc *)cam_sim_softc(sim);
1158 
1159 	status = sbp_targ_find_devs(sc, ccb, &lstate, TRUE);
1160 
1161 	switch (ccb->ccb_h.func_code) {
1162 	case XPT_CONT_TARGET_IO:
1163 	{
1164 		struct orb_info *orbi;
1165 
1166 		if (debug)
1167 			printf("%s: XPT_CONT_TARGET_IO (0x%08x)\n",
1168 					 __func__, ccb->csio.tag_id);
1169 
1170 		if (status != CAM_REQ_CMP) {
1171 			ccb->ccb_h.status = status;
1172 			xpt_done(ccb);
1173 			break;
1174 		}
1175 		/* XXX transfer from/to initiator */
1176 		orbi = sbp_targ_get_orb_info(lstate,
1177 		    ccb->csio.tag_id, ccb->csio.init_id);
1178 		if (orbi == NULL) {
1179 			ccb->ccb_h.status = CAM_REQ_ABORTED; /* XXX */
1180 			xpt_done(ccb);
1181 			break;
1182 		}
1183 		if (orbi->state == ORBI_STATUS_ABORTED) {
1184 			if (debug)
1185 				printf("%s: ctio aborted\n", __func__);
1186 			sbp_targ_remove_orb_info_locked(orbi->login, orbi);
1187 			if (debug)
1188 				printf("%s: free orbi %p\n", __func__, orbi);
1189 			free(orbi, M_SBP_TARG);
1190 			ccb->ccb_h.status = CAM_REQ_ABORTED;
1191 			xpt_done(ccb);
1192 			break;
1193 		}
1194 		orbi->state = ORBI_STATUS_CTIO;
1195 
1196 		orbi->ccb = ccb;
1197 		ccb_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1198 
1199 		/* XXX */
1200 		if (ccb->csio.dxfer_len == 0)
1201 			ccb_dir = CAM_DIR_NONE;
1202 
1203 		/* Sanity check */
1204 		if (ccb_dir == CAM_DIR_IN && orbi->orb4.dir == 0)
1205 			printf("%s: direction mismatch\n", __func__);
1206 
1207 		/* check page table */
1208 		if (ccb_dir != CAM_DIR_NONE && orbi->orb4.page_table_present) {
1209 			if (debug)
1210 				printf("%s: page_table_present\n",
1211 				    __func__);
1212 			if (orbi->orb4.page_size != 0) {
1213 				printf("%s: unsupported pagesize %d != 0\n",
1214 			 	    __func__, orbi->orb4.page_size);
1215 				ccb->ccb_h.status = CAM_REQ_INVALID;
1216 				xpt_done(ccb);
1217 				break;
1218 			}
1219 			sbp_targ_fetch_pt(orbi);
1220 			break;
1221 		}
1222 
1223 		/* Sanity check */
1224 		if (ccb_dir != CAM_DIR_NONE) {
1225 			sbp_targ_xfer_buf(orbi, 0, orbi->data_hi,
1226 			    orbi->data_lo,
1227 			    MIN(orbi->orb4.data_size, ccb->csio.dxfer_len),
1228 			    sbp_targ_cam_done);
1229 			if ( orbi->orb4.data_size > ccb->csio.dxfer_len ) {
1230 				orbi->data_lo += ccb->csio.dxfer_len;
1231 				orbi->orb4.data_size -= ccb->csio.dxfer_len;
1232 			}
1233 		}
1234 
1235 		if (ccb_dir == CAM_DIR_NONE) {
1236 			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1237 				/* XXX */
1238 				SBP_UNLOCK(sc);
1239 				sbp_targ_send_status(orbi, ccb);
1240 				SBP_LOCK(sc);
1241 			}
1242 			ccb->ccb_h.status = CAM_REQ_CMP;
1243 			xpt_done(ccb);
1244 		}
1245 		break;
1246 	}
1247 	case XPT_ACCEPT_TARGET_IO:	/* Add Accept Target IO Resource */
1248 		if (status != CAM_REQ_CMP) {
1249 			ccb->ccb_h.status = status;
1250 			xpt_done(ccb);
1251 			break;
1252 		}
1253 		SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
1254 		    sim_links.sle);
1255 		ccb->ccb_h.status = CAM_REQ_INPROG;
1256 		if ((lstate->flags & F_ATIO_STARVED) != 0) {
1257 			struct sbp_targ_login *login;
1258 
1259 			if (debug)
1260 				printf("%s: new atio arrived\n", __func__);
1261 			lstate->flags &= ~F_ATIO_STARVED;
1262 			STAILQ_FOREACH(login, &lstate->logins, link)
1263 				if ((login->flags & F_ATIO_STARVED) != 0) {
1264 					login->flags &= ~F_ATIO_STARVED;
1265 					sbp_targ_fetch_orb(lstate->sc,
1266 					    login->fwdev,
1267 					    login->last_hi, login->last_lo,
1268 					    login, FETCH_CMD);
1269 				}
1270 		}
1271 		break;
1272 	case XPT_NOTIFY_ACKNOWLEDGE:	/* recycle notify ack */
1273 	case XPT_IMMEDIATE_NOTIFY:	/* Add Immediate Notify Resource */
1274 		if (status != CAM_REQ_CMP) {
1275 			ccb->ccb_h.status = status;
1276 			xpt_done(ccb);
1277 			break;
1278 		}
1279 		SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
1280 		    sim_links.sle);
1281 		ccb->ccb_h.status = CAM_REQ_INPROG;
1282 		sbp_targ_send_lstate_events(sc, lstate);
1283 		break;
1284 	case XPT_EN_LUN:
1285 		sbp_targ_en_lun(sc, ccb);
1286 		xpt_done(ccb);
1287 		break;
1288 	case XPT_PATH_INQ:
1289 	{
1290 		struct ccb_pathinq *cpi = &ccb->cpi;
1291 
1292 		cpi->version_num = 1; /* XXX??? */
1293 		cpi->hba_inquiry = PI_TAG_ABLE;
1294 		cpi->target_sprt = PIT_PROCESSOR
1295 				 | PIT_DISCONNECT
1296 				 | PIT_TERM_IO;
1297 		cpi->transport = XPORT_SPI; /* FIXME add XPORT_FW type to cam */
1298 		cpi->hba_misc = PIM_NOINITIATOR | PIM_NOBUSRESET |
1299 		    PIM_NO_6_BYTE;
1300 		cpi->hba_eng_cnt = 0;
1301 		cpi->max_target = 7; /* XXX */
1302 		cpi->max_lun = MAX_LUN - 1;
1303 		cpi->initiator_id = 7; /* XXX */
1304 		cpi->bus_id = sim->bus_id;
1305 		cpi->base_transfer_speed = 400 * 1000 / 8;
1306 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1307 		strlcpy(cpi->hba_vid, "SBP_TARG", HBA_IDLEN);
1308 		strlcpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
1309 		cpi->unit_number = sim->unit_number;
1310 
1311 		cpi->ccb_h.status = CAM_REQ_CMP;
1312 		xpt_done(ccb);
1313 		break;
1314 	}
1315 	case XPT_ABORT:
1316 	{
1317 		union ccb *accb = ccb->cab.abort_ccb;
1318 
1319 		switch (accb->ccb_h.func_code) {
1320 		case XPT_ACCEPT_TARGET_IO:
1321 		case XPT_IMMEDIATE_NOTIFY:
1322 			ccb->ccb_h.status = sbp_targ_abort_ccb(sc, ccb);
1323 			break;
1324 		case XPT_CONT_TARGET_IO:
1325 			/* XXX */
1326 			ccb->ccb_h.status = CAM_UA_ABORT;
1327 			break;
1328 		default:
1329 			printf("%s: aborting unknown function %d\n",
1330 				__func__, accb->ccb_h.func_code);
1331 			ccb->ccb_h.status = CAM_REQ_INVALID;
1332 			break;
1333 		}
1334 		xpt_done(ccb);
1335 		break;
1336 	}
1337 #ifdef CAM_NEW_TRAN_CODE
1338 	case XPT_SET_TRAN_SETTINGS:
1339 		ccb->ccb_h.status = CAM_REQ_INVALID;
1340 		xpt_done(ccb);
1341 		break;
1342 	case XPT_GET_TRAN_SETTINGS:
1343 	{
1344 		struct ccb_trans_settings *cts = &ccb->cts;
1345 		struct ccb_trans_settings_scsi *scsi =
1346 			&cts->proto_specific.scsi;
1347 		struct ccb_trans_settings_spi *spi =
1348 			&cts->xport_specific.spi;
1349 
1350 		cts->protocol = PROTO_SCSI;
1351 		cts->protocol_version = SCSI_REV_2;
1352 		cts->transport = XPORT_FW;     /* should have a FireWire */
1353 		cts->transport_version = 2;
1354 		spi->valid = CTS_SPI_VALID_DISC;
1355 		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
1356 		scsi->valid = CTS_SCSI_VALID_TQ;
1357 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1358 		cts->ccb_h.status = CAM_REQ_CMP;
1359 		xpt_done(ccb);
1360 		break;
1361 	}
1362 #endif
1363 
1364 	default:
1365 		printf("%s: unknown function 0x%x\n",
1366 		    __func__, ccb->ccb_h.func_code);
1367 		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1368 		xpt_done(ccb);
1369 		break;
1370 	}
1371 	return;
1372 }
1373 
1374 static void
1375 sbp_targ_action(struct cam_sim *sim, union ccb *ccb)
1376 {
1377 
1378 	sbp_targ_action1(sim, ccb);
1379 }
1380 
1381 static void
1382 sbp_targ_poll(struct cam_sim *sim)
1383 {
1384 	/* XXX */
1385 	return;
1386 }
1387 
1388 static void
1389 sbp_targ_cmd_handler(struct fw_xfer *xfer)
1390 {
1391 	uint32_t *orb;
1392 	struct corb4 *orb4;
1393 	struct orb_info *orbi;
1394 	struct ccb_accept_tio *atio;
1395 	u_char *bytes;
1396 	int i;
1397 
1398 	orbi = (struct orb_info *)xfer->sc;
1399 	if (xfer->resp != 0) {
1400 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1401 		orbi->status.resp = SBP_TRANS_FAIL;
1402 		orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1403 		orbi->status.dead = 1;
1404 		orbi->status.len = 1;
1405 		sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1406 
1407 		sbp_targ_status_FIFO(orbi,
1408 		    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
1409 		fw_xfer_free(xfer);
1410 		return;
1411 	}
1412 
1413 	atio = orbi->atio;
1414 
1415 	if (orbi->state == ORBI_STATUS_ABORTED) {
1416 		printf("%s: aborted\n", __func__);
1417 		sbp_targ_remove_orb_info(orbi->login, orbi);
1418 		free(orbi, M_SBP_TARG);
1419 		atio->ccb_h.status = CAM_REQ_ABORTED;
1420 		xpt_done((union ccb*)atio);
1421 		goto done0;
1422 	}
1423 	orbi->state = ORBI_STATUS_ATIO;
1424 
1425 	orb = orbi->orb;
1426 	/* swap payload except SCSI command */
1427 	for (i = 0; i < 5; i++)
1428 		orb[i] = ntohl(orb[i]);
1429 
1430 	orb4 = (struct corb4 *)&orb[4];
1431 	if (orb4->rq_fmt != 0) {
1432 		/* XXX */
1433 		printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt);
1434 	}
1435 
1436 	atio->ccb_h.target_id = 0; /* XXX */
1437 	atio->ccb_h.target_lun = orbi->login->lstate->lun;
1438 	atio->sense_len = 0;
1439 	atio->tag_action = MSG_SIMPLE_TASK;
1440 	atio->tag_id = orbi->orb_lo;
1441 	atio->init_id = orbi->login->id;
1442 
1443 	atio->ccb_h.flags |= CAM_TAG_ACTION_VALID;
1444 	bytes = (u_char *)&orb[5];
1445 	if (debug)
1446 		printf("%s: %p %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1447 		    __func__, (void *)atio,
1448 		    bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
1449 		    bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
1450 	switch (bytes[0] >> 5) {
1451 	case 0:
1452 		atio->cdb_len = 6;
1453 		break;
1454 	case 1:
1455 	case 2:
1456 		atio->cdb_len = 10;
1457 		break;
1458 	case 4:
1459 		atio->cdb_len = 16;
1460 		break;
1461 	case 5:
1462 		atio->cdb_len = 12;
1463 		break;
1464 	case 3:
1465 	default:
1466 		/* Only copy the opcode. */
1467 		atio->cdb_len = 1;
1468 		printf("Reserved or VU command code type encountered\n");
1469 		break;
1470 	}
1471 
1472 	memcpy(atio->cdb_io.cdb_bytes, bytes, atio->cdb_len);
1473 
1474 	atio->ccb_h.status |= CAM_CDB_RECVD;
1475 
1476 	/* next ORB */
1477 	if ((orb[0] & (1<<31)) == 0) {
1478 		if (debug)
1479 			printf("%s: fetch next orb\n", __func__);
1480 		orbi->status.src = SRC_NEXT_EXISTS;
1481 		sbp_targ_fetch_orb(orbi->sc, orbi->fwdev,
1482 		    orb[0], orb[1], orbi->login, FETCH_CMD);
1483 	} else {
1484 		orbi->status.src = SRC_NO_NEXT;
1485 		orbi->login->flags &= ~F_LINK_ACTIVE;
1486 	}
1487 
1488 	orbi->data_hi = orb[2];
1489 	orbi->data_lo = orb[3];
1490 	orbi->orb4 = *orb4;
1491 
1492 	xpt_done((union ccb*)atio);
1493 done0:
1494 	fw_xfer_free(xfer);
1495 	return;
1496 }
1497 
1498 static struct sbp_targ_login *
1499 sbp_targ_get_login(struct sbp_targ_softc *sc, struct fw_device *fwdev, int lun)
1500 {
1501 	struct sbp_targ_lstate *lstate;
1502 	struct sbp_targ_login *login;
1503 	int i;
1504 
1505 	lstate = sc->lstate[lun];
1506 
1507 	STAILQ_FOREACH(login, &lstate->logins, link)
1508 		if (login->fwdev == fwdev)
1509 			return (login);
1510 
1511 	for (i = 0; i < MAX_LOGINS; i++)
1512 		if (sc->logins[i] == NULL)
1513 			goto found;
1514 
1515 	printf("%s: increase MAX_LOGIN\n", __func__);
1516 	return (NULL);
1517 
1518 found:
1519 	login = (struct sbp_targ_login *)malloc(
1520 	    sizeof(struct sbp_targ_login), M_SBP_TARG, M_NOWAIT | M_ZERO);
1521 
1522 	if (login == NULL) {
1523 		printf("%s: malloc failed\n", __func__);
1524 		return (NULL);
1525 	}
1526 
1527 	login->id = i;
1528 	login->fwdev = fwdev;
1529 	login->lstate = lstate;
1530 	login->last_hi = 0xffff;
1531 	login->last_lo = 0xffffffff;
1532 	login->hold_sec = 1;
1533 	STAILQ_INIT(&login->orbs);
1534 	CALLOUT_INIT(&login->hold_callout);
1535 	sc->logins[i] = login;
1536 	return (login);
1537 }
1538 
1539 static void
1540 sbp_targ_mgm_handler(struct fw_xfer *xfer)
1541 {
1542 	struct sbp_targ_lstate *lstate;
1543 	struct sbp_targ_login *login;
1544 	uint32_t *orb;
1545 	struct morb4 *orb4;
1546 	struct orb_info *orbi;
1547 	int i;
1548 
1549 	orbi = (struct orb_info *)xfer->sc;
1550 	if (xfer->resp != 0) {
1551 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1552 		orbi->status.resp = SBP_TRANS_FAIL;
1553 		orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1554 		orbi->status.dead = 1;
1555 		orbi->status.len = 1;
1556 		sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1557 
1558 		sbp_targ_status_FIFO(orbi,
1559 		    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/0);
1560 		fw_xfer_free(xfer);
1561 		return;
1562 	}
1563 
1564 	orb = orbi->orb;
1565 	/* swap payload */
1566 	for (i = 0; i < 8; i++) {
1567 		orb[i] = ntohl(orb[i]);
1568 	}
1569 	orb4 = (struct morb4 *)&orb[4];
1570 	if (debug)
1571 		printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]);
1572 
1573 	orbi->status.src = SRC_NO_NEXT;
1574 
1575 	switch (orb4->fun << 16) {
1576 	case ORB_FUN_LGI:
1577 	{
1578 		int exclusive = 0, lun;
1579 
1580 		if (orb[4] & ORB_EXV)
1581 			exclusive = 1;
1582 
1583 		lun = orb4->id;
1584 		lstate = orbi->sc->lstate[lun];
1585 
1586 		if (lun >= MAX_LUN || lstate == NULL ||
1587 		    (exclusive &&
1588 		    STAILQ_FIRST(&lstate->logins) != NULL &&
1589 		    STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)
1590 		   ) {
1591 			/* error */
1592 			orbi->status.dead = 1;
1593 			orbi->status.status = STATUS_ACCESS_DENY;
1594 			orbi->status.len = 1;
1595 			break;
1596 		}
1597 
1598 		/* allocate login */
1599 		login = sbp_targ_get_login(orbi->sc, orbi->fwdev, lun);
1600 		if (login == NULL) {
1601 			printf("%s: sbp_targ_get_login failed\n",
1602 			    __func__);
1603 			orbi->status.dead = 1;
1604 			orbi->status.status = STATUS_RES_UNAVAIL;
1605 			orbi->status.len = 1;
1606 			break;
1607 		}
1608 		printf("%s: login id=%d\n", __func__, login->id);
1609 
1610 		login->fifo_hi = orb[6];
1611 		login->fifo_lo = orb[7];
1612 		login->loginres.len = htons(sizeof(uint32_t) * 4);
1613 		login->loginres.id = htons(login->id);
1614 		login->loginres.cmd_hi = htons(SBP_TARG_BIND_HI);
1615 		login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id));
1616 		login->loginres.recon_hold = htons(login->hold_sec);
1617 
1618 		STAILQ_INSERT_TAIL(&lstate->logins, login, link);
1619 		fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3],
1620 		    sizeof(struct sbp_login_res), (void *)&login->loginres,
1621 		    fw_asy_callback_free);
1622 		/* XXX return status after loginres is successfully written */
1623 		break;
1624 	}
1625 	case ORB_FUN_RCN:
1626 		login = orbi->sc->logins[orb4->id];
1627 		if (login != NULL && login->fwdev == orbi->fwdev) {
1628 			login->flags &= ~F_HOLD;
1629 			callout_stop(&login->hold_callout);
1630 			printf("%s: reconnected id=%d\n",
1631 			    __func__, login->id);
1632 		} else {
1633 			orbi->status.dead = 1;
1634 			orbi->status.status = STATUS_ACCESS_DENY;
1635 			printf("%s: reconnection failed id=%d\n",
1636 			    __func__, orb4->id);
1637 		}
1638 		break;
1639 	case ORB_FUN_LGO:
1640 		login = orbi->sc->logins[orb4->id];
1641 		if (login->fwdev != orbi->fwdev) {
1642 			printf("%s: wrong initiator\n", __func__);
1643 			break;
1644 		}
1645 		sbp_targ_dealloc_login(login);
1646 		break;
1647 	default:
1648 		printf("%s: %s not implemented yet\n",
1649 		    __func__, orb_fun_name[orb4->fun]);
1650 		break;
1651 	}
1652 	orbi->status.len = 1;
1653 	sbp_targ_status_FIFO(orbi, orb[6], orb[7], /*dequeue*/0);
1654 	fw_xfer_free(xfer);
1655 	return;
1656 }
1657 
1658 static void
1659 sbp_targ_pointer_handler(struct fw_xfer *xfer)
1660 {
1661 	struct orb_info *orbi;
1662 	uint32_t orb0, orb1;
1663 
1664 	orbi = (struct orb_info *)xfer->sc;
1665 	if (xfer->resp != 0) {
1666 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1667 		goto done;
1668 	}
1669 
1670 	orb0 = ntohl(orbi->orb[0]);
1671 	orb1 = ntohl(orbi->orb[1]);
1672 	if ((orb0 & (1U << 31)) != 0) {
1673 		printf("%s: invalid pointer\n", __func__);
1674 		goto done;
1675 	}
1676 	sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev,
1677 	    (uint16_t)orb0, orb1, orbi->login, FETCH_CMD);
1678 done:
1679 	free(orbi, M_SBP_TARG);
1680 	fw_xfer_free(xfer);
1681 	return;
1682 }
1683 
1684 static void
1685 sbp_targ_fetch_orb(struct sbp_targ_softc *sc, struct fw_device *fwdev,
1686     uint16_t orb_hi, uint32_t orb_lo, struct sbp_targ_login *login,
1687     int mode)
1688 {
1689 	struct orb_info *orbi;
1690 
1691 	if (debug)
1692 		printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo);
1693 	orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO);
1694 	if (orbi == NULL) {
1695 		printf("%s: malloc failed\n", __func__);
1696 		return;
1697 	}
1698 	orbi->sc = sc;
1699 	orbi->fwdev = fwdev;
1700 	orbi->login = login;
1701 	orbi->orb_hi = orb_hi;
1702 	orbi->orb_lo = orb_lo;
1703 	orbi->status.orb_hi = htons(orb_hi);
1704 	orbi->status.orb_lo = htonl(orb_lo);
1705 	orbi->page_table = NULL;
1706 
1707 	switch (mode) {
1708 	case FETCH_MGM:
1709 		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1710 		    sizeof(uint32_t) * 8, &orbi->orb[0],
1711 		    sbp_targ_mgm_handler);
1712 		break;
1713 	case FETCH_CMD:
1714 		orbi->state = ORBI_STATUS_FETCH;
1715 		login->last_hi = orb_hi;
1716 		login->last_lo = orb_lo;
1717 		login->flags |= F_LINK_ACTIVE;
1718 		/* dequeue */
1719 		SBP_LOCK(sc);
1720 		orbi->atio = (struct ccb_accept_tio *)
1721 		    SLIST_FIRST(&login->lstate->accept_tios);
1722 		if (orbi->atio == NULL) {
1723 			SBP_UNLOCK(sc);
1724 			printf("%s: no free atio\n", __func__);
1725 			login->lstate->flags |= F_ATIO_STARVED;
1726 			login->flags |= F_ATIO_STARVED;
1727 			break;
1728 		}
1729 		SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
1730 		STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
1731 		SBP_UNLOCK(sc);
1732 		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1733 		    sizeof(uint32_t) * 8, &orbi->orb[0],
1734 		    sbp_targ_cmd_handler);
1735 		break;
1736 	case FETCH_POINTER:
1737 		orbi->state = ORBI_STATUS_POINTER;
1738 		login->flags |= F_LINK_ACTIVE;
1739 		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
1740 		    sizeof(uint32_t) * 2, &orbi->orb[0],
1741 		    sbp_targ_pointer_handler);
1742 		break;
1743 	default:
1744 		printf("%s: invalid mode %d\n", __func__, mode);
1745 	}
1746 }
1747 
1748 static void
1749 sbp_targ_resp_callback(struct fw_xfer *xfer)
1750 {
1751 	struct sbp_targ_softc *sc;
1752 
1753 	if (debug)
1754 		printf("%s: xfer=%p\n", __func__, xfer);
1755 	sc = (struct sbp_targ_softc *)xfer->sc;
1756 	fw_xfer_unload(xfer);
1757 	xfer->recv.pay_len = SBP_TARG_RECV_LEN;
1758 	xfer->hand = sbp_targ_recv;
1759 	STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link);
1760 }
1761 
1762 static int
1763 sbp_targ_cmd(struct fw_xfer *xfer, struct fw_device *fwdev, int login_id,
1764     int reg)
1765 {
1766 	struct sbp_targ_login *login;
1767 	struct sbp_targ_softc *sc;
1768 	int rtcode = 0;
1769 
1770 	if (login_id < 0 || login_id >= MAX_LOGINS)
1771 		return (RESP_ADDRESS_ERROR);
1772 
1773 	sc = (struct sbp_targ_softc *)xfer->sc;
1774 	login = sc->logins[login_id];
1775 	if (login == NULL)
1776 		return (RESP_ADDRESS_ERROR);
1777 
1778 	if (login->fwdev != fwdev) {
1779 		/* XXX */
1780 		return (RESP_ADDRESS_ERROR);
1781 	}
1782 
1783 	switch (reg) {
1784 	case 0x08:	/* ORB_POINTER */
1785 		if (debug)
1786 			printf("%s: ORB_POINTER(%d)\n", __func__, login_id);
1787 		if ((login->flags & F_LINK_ACTIVE) != 0) {
1788 			if (debug)
1789 				printf("link active (ORB_POINTER)\n");
1790 			break;
1791 		}
1792 		sbp_targ_fetch_orb(sc, fwdev,
1793 		    ntohl(xfer->recv.payload[0]),
1794 		    ntohl(xfer->recv.payload[1]),
1795 		    login, FETCH_CMD);
1796 		break;
1797 	case 0x04:	/* AGENT_RESET */
1798 		if (debug)
1799 			printf("%s: AGENT RESET(%d)\n", __func__, login_id);
1800 		login->last_hi = 0xffff;
1801 		login->last_lo = 0xffffffff;
1802 		sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
1803 		break;
1804 	case 0x10:	/* DOORBELL */
1805 		if (debug)
1806 			printf("%s: DOORBELL(%d)\n", __func__, login_id);
1807 		if (login->last_hi == 0xffff &&
1808 		    login->last_lo == 0xffffffff) {
1809 			printf("%s: no previous pointer(DOORBELL)\n",
1810 			    __func__);
1811 			break;
1812 		}
1813 		if ((login->flags & F_LINK_ACTIVE) != 0) {
1814 			if (debug)
1815 				printf("link active (DOORBELL)\n");
1816 			break;
1817 		}
1818 		sbp_targ_fetch_orb(sc, fwdev,
1819 		    login->last_hi, login->last_lo,
1820 		    login, FETCH_POINTER);
1821 		break;
1822 	case 0x00:	/* AGENT_STATE */
1823 		printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id);
1824 		break;
1825 	case 0x14:	/* UNSOLICITED_STATE_ENABLE */
1826 		printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n",
1827 							 __func__, login_id);
1828 		break;
1829 	default:
1830 		printf("%s: invalid register %d(%d)\n",
1831 						 __func__, reg, login_id);
1832 		rtcode = RESP_ADDRESS_ERROR;
1833 	}
1834 
1835 	return (rtcode);
1836 }
1837 
1838 static int
1839 sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev)
1840 {
1841 	struct sbp_targ_softc *sc;
1842 	struct fw_pkt *fp;
1843 
1844 	sc = (struct sbp_targ_softc *)xfer->sc;
1845 
1846 	fp = &xfer->recv.hdr;
1847 	if (fp->mode.wreqb.tcode != FWTCODE_WREQB) {
1848 		printf("%s: tcode = %d\n", __func__, fp->mode.wreqb.tcode);
1849 		return (RESP_TYPE_ERROR);
1850         }
1851 
1852 	sbp_targ_fetch_orb(sc, fwdev,
1853 	    ntohl(xfer->recv.payload[0]),
1854 	    ntohl(xfer->recv.payload[1]),
1855 	    NULL, FETCH_MGM);
1856 
1857 	return (0);
1858 }
1859 
1860 static void
1861 sbp_targ_recv(struct fw_xfer *xfer)
1862 {
1863 	struct fw_pkt *fp, *sfp;
1864 	struct fw_device *fwdev;
1865 	uint32_t lo;
1866 	int rtcode;
1867 	struct sbp_targ_softc *sc;
1868 
1869 	sc = (struct sbp_targ_softc *)xfer->sc;
1870 	fp = &xfer->recv.hdr;
1871 	fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
1872 	if (fwdev == NULL) {
1873 		printf("%s: cannot resolve nodeid=%d\n",
1874 		    __func__, fp->mode.wreqb.src & 0x3f);
1875 		rtcode = RESP_TYPE_ERROR; /* XXX */
1876 		goto done;
1877 	}
1878 	lo = fp->mode.wreqb.dest_lo;
1879 
1880 	if (lo == SBP_TARG_BIND_LO(-1))
1881 		rtcode = sbp_targ_mgm(xfer, fwdev);
1882 	else if (lo >= SBP_TARG_BIND_LO(0))
1883 		rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
1884 		    lo % 0x20);
1885 	else
1886 		rtcode = RESP_ADDRESS_ERROR;
1887 
1888 done:
1889 	if (rtcode != 0)
1890 		printf("%s: rtcode = %d\n", __func__, rtcode);
1891 	sfp = &xfer->send.hdr;
1892 	xfer->send.spd = FWSPD_S400;
1893 	xfer->hand = sbp_targ_resp_callback;
1894 	sfp->mode.wres.dst = fp->mode.wreqb.src;
1895 	sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
1896 	sfp->mode.wres.tcode = FWTCODE_WRES;
1897 	sfp->mode.wres.rtcode = rtcode;
1898 	sfp->mode.wres.pri = 0;
1899 
1900 	fw_asyreq(xfer->fc, -1, xfer);
1901 }
1902 
1903 static int
1904 sbp_targ_attach(device_t dev)
1905 {
1906 	struct sbp_targ_softc *sc;
1907 	struct cam_devq *devq;
1908 	struct firewire_comm *fc;
1909 
1910         sc = (struct sbp_targ_softc *) device_get_softc(dev);
1911 	bzero((void *)sc, sizeof(struct sbp_targ_softc));
1912 
1913 	mtx_init(&sc->mtx, "sbp_targ", NULL, MTX_DEF);
1914 	sc->fd.fc = fc = fw_get_comm(dev);
1915 	sc->fd.dev = dev;
1916 	sc->fd.post_explore = (void *) sbp_targ_post_explore;
1917 	sc->fd.post_busreset = (void *) sbp_targ_post_busreset;
1918 
1919         devq = cam_simq_alloc(/*maxopenings*/MAX_LUN*MAX_INITIATORS);
1920 	if (devq == NULL)
1921 		return (ENXIO);
1922 
1923 	sc->sim = cam_sim_alloc(sbp_targ_action, sbp_targ_poll,
1924 	    "sbp_targ", sc, device_get_unit(dev), &sc->mtx,
1925 	    /*untagged*/ 1, /*tagged*/ 1, devq);
1926 	if (sc->sim == NULL) {
1927 		cam_simq_free(devq);
1928 		return (ENXIO);
1929 	}
1930 
1931 	SBP_LOCK(sc);
1932 	if (xpt_bus_register(sc->sim, dev, /*bus*/0) != CAM_SUCCESS)
1933 		goto fail;
1934 
1935 	if (xpt_create_path(&sc->path, /*periph*/ NULL, cam_sim_path(sc->sim),
1936 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1937 		xpt_bus_deregister(cam_sim_path(sc->sim));
1938 		goto fail;
1939 	}
1940 	SBP_UNLOCK(sc);
1941 
1942 	sc->fwb.start = SBP_TARG_BIND_START;
1943 	sc->fwb.end = SBP_TARG_BIND_END;
1944 
1945 	/* pre-allocate xfer */
1946 	STAILQ_INIT(&sc->fwb.xferlist);
1947 	fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
1948 	    /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
1949 	    fc, (void *)sc, sbp_targ_recv);
1950 	fw_bindadd(fc, &sc->fwb);
1951 	return 0;
1952 
1953 fail:
1954 	SBP_UNLOCK(sc);
1955 	cam_sim_free(sc->sim, /*free_devq*/TRUE);
1956 	return (ENXIO);
1957 }
1958 
1959 static int
1960 sbp_targ_detach(device_t dev)
1961 {
1962 	struct sbp_targ_softc *sc;
1963 	struct sbp_targ_lstate *lstate;
1964 	int i;
1965 
1966 	sc = (struct sbp_targ_softc *)device_get_softc(dev);
1967 	sc->fd.post_busreset = NULL;
1968 
1969 	SBP_LOCK(sc);
1970 	xpt_free_path(sc->path);
1971 	xpt_bus_deregister(cam_sim_path(sc->sim));
1972 	cam_sim_free(sc->sim, /*free_devq*/TRUE);
1973 	SBP_UNLOCK(sc);
1974 
1975 	for (i = 0; i < MAX_LUN; i++) {
1976 		lstate = sc->lstate[i];
1977 		if (lstate != NULL) {
1978 			xpt_free_path(lstate->path);
1979 			free(lstate, M_SBP_TARG);
1980 		}
1981 	}
1982 	if (sc->black_hole != NULL) {
1983 		xpt_free_path(sc->black_hole->path);
1984 		free(sc->black_hole, M_SBP_TARG);
1985 	}
1986 
1987 	fw_bindremove(sc->fd.fc, &sc->fwb);
1988 	fw_xferlist_remove(&sc->fwb.xferlist);
1989 
1990 	mtx_destroy(&sc->mtx);
1991 
1992 	return 0;
1993 }
1994 
1995 static device_method_t sbp_targ_methods[] = {
1996 	/* device interface */
1997 	DEVMETHOD(device_identify,	sbp_targ_identify),
1998 	DEVMETHOD(device_probe,		sbp_targ_probe),
1999 	DEVMETHOD(device_attach,	sbp_targ_attach),
2000 	DEVMETHOD(device_detach,	sbp_targ_detach),
2001 	DEVMETHOD_END
2002 };
2003 
2004 static driver_t sbp_targ_driver = {
2005 	"sbp_targ",
2006 	sbp_targ_methods,
2007 	sizeof(struct sbp_targ_softc),
2008 };
2009 
2010 DRIVER_MODULE(sbp_targ, firewire, sbp_targ_driver, 0, 0);
2011 MODULE_VERSION(sbp_targ, 1);
2012 MODULE_DEPEND(sbp_targ, firewire, 1, 1, 1);
2013 MODULE_DEPEND(sbp_targ, cam, 1, 1, 1);
2014