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