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