1139749Simp/*-
2122526Ssimokawa * Copyright (c) 2003 Hidetoshi Shimokawa
3122526Ssimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
4103285Sikob * All rights reserved.
5103285Sikob *
6103285Sikob * Redistribution and use in source and binary forms, with or without
7103285Sikob * modification, are permitted provided that the following conditions
8103285Sikob * are met:
9103285Sikob * 1. Redistributions of source code must retain the above copyright
10103285Sikob *    notice, this list of conditions and the following disclaimer.
11103285Sikob * 2. Redistributions in binary form must reproduce the above copyright
12103285Sikob *    notice, this list of conditions and the following disclaimer in the
13103285Sikob *    documentation and/or other materials provided with the distribution.
14103285Sikob * 3. All advertising materials mentioning features or use of this software
15103285Sikob *    must display the acknowledgement as bellow:
16103285Sikob *
17103285Sikob *    This product includes software developed by K. Kobayashi and H. Shimokawa
18103285Sikob *
19103285Sikob * 4. The name of the author may not be used to endorse or promote products
20103285Sikob *    derived from this software without specific prior written permission.
21103285Sikob *
22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23103285Sikob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24103285Sikob * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25103285Sikob * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26103285Sikob * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27103285Sikob * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28103285Sikob * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30103285Sikob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31103285Sikob * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32103285Sikob * POSSIBILITY OF SUCH DAMAGE.
33272214Skan *
34103285Sikob * $FreeBSD: releng/11.0/sys/dev/firewire/sbp.c 274819 2014-11-21 21:01:24Z smh $
35103285Sikob *
36103285Sikob */
37103285Sikob
38103285Sikob#include <sys/param.h>
39103285Sikob#include <sys/systm.h>
40103285Sikob#include <sys/module.h>
41103285Sikob#include <sys/bus.h>
42127468Ssimokawa#include <sys/kernel.h>
43103285Sikob#include <sys/sysctl.h>
44103285Sikob#include <machine/bus.h>
45103285Sikob#include <sys/malloc.h>
46117126Sscottl#include <sys/lock.h>
47117126Sscottl#include <sys/mutex.h>
48103285Sikob
49103285Sikob#include <cam/cam.h>
50103285Sikob#include <cam/cam_ccb.h>
51103285Sikob#include <cam/cam_sim.h>
52103285Sikob#include <cam/cam_xpt_sim.h>
53103285Sikob#include <cam/cam_debug.h>
54103285Sikob#include <cam/cam_periph.h>
55103285Sikob#include <cam/scsi/scsi_all.h>
56103285Sikob
57103285Sikob#include <dev/firewire/firewire.h>
58103285Sikob#include <dev/firewire/firewirereg.h>
59113584Ssimokawa#include <dev/firewire/fwdma.h>
60103285Sikob#include <dev/firewire/iec13213.h>
61120660Ssimokawa#include <dev/firewire/sbp.h>
62103285Sikob
63103285Sikob#define ccb_sdev_ptr	spriv_ptr0
64103285Sikob#define ccb_sbp_ptr	spriv_ptr1
65103285Sikob
66111615Ssimokawa#define SBP_NUM_TARGETS 8 /* MAX 64 */
67121185Ssimokawa/*
68121185Ssimokawa * Scan_bus doesn't work for more than 8 LUNs
69121185Ssimokawa * because of CAM_SCSI2_MAXLUN in cam_xpt.c
70121185Ssimokawa */
71121185Ssimokawa#define SBP_NUM_LUNS 64
72167622Ssimokawa#define SBP_MAXPHYS  MIN(MAXPHYS, (512*1024) /* 512KB */)
73113584Ssimokawa#define SBP_DMA_SIZE PAGE_SIZE
74113584Ssimokawa#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res)
75113584Ssimokawa#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb))
76103285Sikob#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS)
77113584Ssimokawa
78272214Skan/*
79111615Ssimokawa * STATUS FIFO addressing
80111615Ssimokawa *   bit
81272214Skan *-----------------------
82130532Sdfr *  0- 1( 2): 0 (alignment)
83111615Ssimokawa *  2- 7( 6): target
84111615Ssimokawa *  8-15( 8): lun
85120660Ssimokawa * 16-31( 8): reserved
86272214Skan * 32-47(16): SBP_BIND_HI
87272214Skan * 48-64(16): bus_id, node_id
88111615Ssimokawa */
89103285Sikob#define SBP_BIND_HI 0x1
90120660Ssimokawa#define SBP_DEV2ADDR(t, l) \
91120660Ssimokawa	(((u_int64_t)SBP_BIND_HI << 32) \
92120660Ssimokawa	| (((l) & 0xff) << 8) \
93120660Ssimokawa	| (((t) & 0x3f) << 2))
94103285Sikob#define SBP_ADDR2TRG(a)	(((a) >> 2) & 0x3f)
95103285Sikob#define SBP_ADDR2LUN(a)	(((a) >> 8) & 0xff)
96120660Ssimokawa#define SBP_INITIATOR 7
97103285Sikob
98103285Sikobstatic char *orb_fun_name[] = {
99120660Ssimokawa	ORB_FUN_NAMES
100103285Sikob};
101103285Sikob
102111203Ssimokawastatic int debug = 0;
103103285Sikobstatic int auto_login = 1;
104124251Ssimokawastatic int max_speed = -1;
105111199Ssimokawastatic int sbp_cold = 1;
106122387Ssimokawastatic int ex_login = 1;
107122387Ssimokawastatic int login_delay = 1000;	/* msec */
108122387Ssimokawastatic int scan_delay = 500;	/* msec */
109127468Ssimokawastatic int use_doorbell = 0;
110127468Ssimokawastatic int sbp_tags = 0;
111103285Sikob
112103285SikobSYSCTL_DECL(_hw_firewire);
113227309Sedstatic SYSCTL_NODE(_hw_firewire, OID_AUTO, sbp, CTLFLAG_RD, 0,
114227309Sed	"SBP-II Subsystem");
115267992ShselaskySYSCTL_INT(_debug, OID_AUTO, sbp_debug, CTLFLAG_RWTUN, &debug, 0,
116103285Sikob	"SBP debug flag");
117267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RWTUN, &auto_login, 0,
118103285Sikob	"SBP perform login automatically");
119267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RWTUN, &max_speed, 0,
120103285Sikob	"SBP transfer max speed");
121267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, exclusive_login, CTLFLAG_RWTUN,
122130677Ssimokawa	&ex_login, 0, "SBP enable exclusive login");
123267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, login_delay, CTLFLAG_RWTUN,
124122387Ssimokawa	&login_delay, 0, "SBP login delay in msec");
125267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, scan_delay, CTLFLAG_RWTUN,
126122387Ssimokawa	&scan_delay, 0, "SBP scan delay in msec");
127267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, use_doorbell, CTLFLAG_RWTUN,
128127468Ssimokawa	&use_doorbell, 0, "SBP use doorbell request");
129267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, tags, CTLFLAG_RWTUN, &sbp_tags, 0,
130127468Ssimokawa	"SBP tagged queuing support");
131103285Sikob
132103285Sikob#define NEED_RESPONSE 0
133103285Sikob
134113584Ssimokawa#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE)
135113584Ssimokawa#ifdef __sparc64__ /* iommu */
136167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, SBP_SEG_MAX)
137113584Ssimokawa#else
138167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, PAGE_SIZE)
139113584Ssimokawa#endif
140103285Sikobstruct sbp_ocb {
141103285Sikob	STAILQ_ENTRY(sbp_ocb)	ocb;
142103285Sikob	union ccb	*ccb;
143113584Ssimokawa	bus_addr_t	bus_addr;
144129585Sdfr	uint32_t	orb[8];
145129585Sdfr#define IND_PTR_OFFSET	(8*sizeof(uint32_t))
146120660Ssimokawa	struct ind_ptr  ind_ptr[SBP_IND_MAX];
147103285Sikob	struct sbp_dev	*sdev;
148113584Ssimokawa	int		flags; /* XXX should be removed */
149103285Sikob	bus_dmamap_t	dmamap;
150266772Sjhb	struct callout	timer;
151103285Sikob};
152113584Ssimokawa
153103285Sikob#define OCB_ACT_MGM 0
154103285Sikob#define OCB_ACT_CMD 1
155113584Ssimokawa#define OCB_MATCH(o,s)	((o)->bus_addr == ntohl((s)->orb_lo))
156103285Sikob
157272214Skanstruct sbp_dev {
158103285Sikob#define SBP_DEV_RESET		0	/* accept login */
159114732Ssimokawa#define SBP_DEV_LOGIN		1	/* to login */
160110336Ssimokawa#if 0
161103285Sikob#define SBP_DEV_RECONN		2	/* to reconnect */
162110336Ssimokawa#endif
163103285Sikob#define SBP_DEV_TOATTACH	3	/* to attach */
164103285Sikob#define SBP_DEV_PROBE		4	/* scan lun */
165103285Sikob#define SBP_DEV_ATTACHED	5	/* in operation */
166103285Sikob#define SBP_DEV_DEAD		6	/* unavailable unit */
167103285Sikob#define SBP_DEV_RETRY		7	/* unavailable unit */
168129585Sdfr	uint8_t status:4,
169114732Ssimokawa		 timeout:4;
170129585Sdfr	uint8_t type;
171129585Sdfr	uint16_t lun_id;
172129585Sdfr	uint16_t freeze;
173121185Ssimokawa#define	ORB_LINK_DEAD		(1 << 0)
174121185Ssimokawa#define	VALID_LUN		(1 << 1)
175121185Ssimokawa#define	ORB_POINTER_ACTIVE	(1 << 2)
176121185Ssimokawa#define	ORB_POINTER_NEED	(1 << 3)
177127468Ssimokawa#define	ORB_DOORBELL_ACTIVE	(1 << 4)
178127468Ssimokawa#define	ORB_DOORBELL_NEED	(1 << 5)
179127468Ssimokawa#define	ORB_SHORTAGE		(1 << 6)
180129585Sdfr	uint16_t flags;
181103285Sikob	struct cam_path *path;
182103285Sikob	struct sbp_target *target;
183113584Ssimokawa	struct fwdma_alloc dma;
184113584Ssimokawa	struct sbp_login_res *login;
185111615Ssimokawa	struct callout login_callout;
186113584Ssimokawa	struct sbp_ocb *ocb;
187103285Sikob	STAILQ_HEAD(, sbp_ocb) ocbs;
188113584Ssimokawa	STAILQ_HEAD(, sbp_ocb) free_ocbs;
189127468Ssimokawa	struct sbp_ocb *last_ocb;
190103285Sikob	char vendor[32];
191103285Sikob	char product[32];
192103285Sikob	char revision[10];
193188756Ssbruno	char bustgtlun[32];
194103285Sikob};
195103285Sikob
196103285Sikobstruct sbp_target {
197103285Sikob	int target_id;
198103285Sikob	int num_lun;
199121185Ssimokawa	struct sbp_dev	**luns;
200103285Sikob	struct sbp_softc *sbp;
201103285Sikob	struct fw_device *fwdev;
202129585Sdfr	uint32_t mgm_hi, mgm_lo;
203111615Ssimokawa	struct sbp_ocb *mgm_ocb_cur;
204111615Ssimokawa	STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue;
205111615Ssimokawa	struct callout mgm_ocb_timeout;
206111615Ssimokawa	struct callout scan_callout;
207113584Ssimokawa	STAILQ_HEAD(, fw_xfer) xferlist;
208113584Ssimokawa	int n_xfer;
209103285Sikob};
210103285Sikob
211103285Sikobstruct sbp_softc {
212103285Sikob	struct firewire_dev_comm fd;
213103285Sikob	struct cam_sim  *sim;
214111615Ssimokawa	struct cam_path  *path;
215103285Sikob	struct sbp_target targets[SBP_NUM_TARGETS];
216103285Sikob	struct fw_bind fwb;
217103285Sikob	bus_dma_tag_t	dmat;
218122387Ssimokawa	struct timeval last_busreset;
219124145Ssimokawa#define SIMQ_FREEZED 1
220124145Ssimokawa	int flags;
221170374Ssimokawa	struct mtx mtx;
222103285Sikob};
223266772Sjhb#define	SBP_LOCK(sbp)		mtx_lock(&(sbp)->mtx)
224266772Sjhb#define	SBP_UNLOCK(sbp)		mtx_unlock(&(sbp)->mtx)
225266772Sjhb#define	SBP_LOCK_ASSERT(sbp)	mtx_assert(&(sbp)->mtx, MA_OWNED)
226122387Ssimokawa
227124169Ssimokawastatic void sbp_post_explore (void *);
228124169Ssimokawastatic void sbp_recv (struct fw_xfer *);
229124169Ssimokawastatic void sbp_mgm_callback (struct fw_xfer *);
230121185Ssimokawa#if 0
231124169Ssimokawastatic void sbp_cmd_callback (struct fw_xfer *);
232121185Ssimokawa#endif
233124169Ssimokawastatic void sbp_orb_pointer (struct sbp_dev *, struct sbp_ocb *);
234127468Ssimokawastatic void sbp_doorbell(struct sbp_dev *);
235272214Skanstatic void sbp_execute_ocb (void *, bus_dma_segment_t *, int, int);
236124169Ssimokawastatic void sbp_free_ocb (struct sbp_dev *, struct sbp_ocb *);
237124169Ssimokawastatic void sbp_abort_ocb (struct sbp_ocb *, int);
238124169Ssimokawastatic void sbp_abort_all_ocbs (struct sbp_dev *, int);
239124169Ssimokawastatic struct fw_xfer * sbp_write_cmd (struct sbp_dev *, int, int);
240124169Ssimokawastatic struct sbp_ocb * sbp_get_ocb (struct sbp_dev *);
241124169Ssimokawastatic struct sbp_ocb * sbp_enqueue_ocb (struct sbp_dev *, struct sbp_ocb *);
242124169Ssimokawastatic struct sbp_ocb * sbp_dequeue_ocb (struct sbp_dev *, struct sbp_status *);
243121185Ssimokawastatic void sbp_cam_detach_sdev(struct sbp_dev *);
244121185Ssimokawastatic void sbp_free_sdev(struct sbp_dev *);
245124169Ssimokawastatic void sbp_cam_detach_target (struct sbp_target *);
246124169Ssimokawastatic void sbp_free_target (struct sbp_target *);
247124169Ssimokawastatic void sbp_mgm_timeout (void *arg);
248124169Ssimokawastatic void sbp_timeout (void *arg);
249124169Ssimokawastatic void sbp_mgm_orb (struct sbp_dev *, int, struct sbp_ocb *);
250103285Sikob
251227293Sedstatic MALLOC_DEFINE(M_SBP, "sbp", "SBP-II/FireWire");
252103285Sikob
253103285Sikob/* cam related functions */
254103285Sikobstatic void	sbp_action(struct cam_sim *sim, union ccb *ccb);
255103285Sikobstatic void	sbp_poll(struct cam_sim *sim);
256111615Ssimokawastatic void	sbp_cam_scan_lun(struct cam_periph *, union ccb *);
257111615Ssimokawastatic void	sbp_cam_scan_target(void *arg);
258103285Sikob
259103285Sikobstatic char *orb_status0[] = {
260103285Sikob	/* 0 */ "No additional information to report",
261103285Sikob	/* 1 */ "Request type not supported",
262103285Sikob	/* 2 */ "Speed not supported",
263103285Sikob	/* 3 */ "Page size not supported",
264103285Sikob	/* 4 */ "Access denied",
265103285Sikob	/* 5 */ "Logical unit not supported",
266103285Sikob	/* 6 */ "Maximum payload too small",
267103285Sikob	/* 7 */ "Reserved for future standardization",
268103285Sikob	/* 8 */ "Resources unavailable",
269103285Sikob	/* 9 */ "Function rejected",
270103285Sikob	/* A */ "Login ID not recognized",
271103285Sikob	/* B */ "Dummy ORB completed",
272103285Sikob	/* C */ "Request aborted",
273103285Sikob	/* FF */ "Unspecified error"
274103285Sikob#define MAX_ORB_STATUS0 0xd
275103285Sikob};
276103285Sikob
277103285Sikobstatic char *orb_status1_object[] = {
278103285Sikob	/* 0 */ "Operation request block (ORB)",
279103285Sikob	/* 1 */ "Data buffer",
280103285Sikob	/* 2 */ "Page table",
281103285Sikob	/* 3 */ "Unable to specify"
282103285Sikob};
283103285Sikob
284103285Sikobstatic char *orb_status1_serial_bus_error[] = {
285103285Sikob	/* 0 */ "Missing acknowledge",
286103285Sikob	/* 1 */ "Reserved; not to be used",
287103285Sikob	/* 2 */ "Time-out error",
288103285Sikob	/* 3 */ "Reserved; not to be used",
289103285Sikob	/* 4 */ "Busy retry limit exceeded(X)",
290103285Sikob	/* 5 */ "Busy retry limit exceeded(A)",
291103285Sikob	/* 6 */ "Busy retry limit exceeded(B)",
292103285Sikob	/* 7 */ "Reserved for future standardization",
293103285Sikob	/* 8 */ "Reserved for future standardization",
294103285Sikob	/* 9 */ "Reserved for future standardization",
295103285Sikob	/* A */ "Reserved for future standardization",
296103285Sikob	/* B */ "Tardy retry limit exceeded",
297103285Sikob	/* C */ "Conflict error",
298103285Sikob	/* D */ "Data error",
299103285Sikob	/* E */ "Type error",
300103285Sikob	/* F */ "Address error"
301103285Sikob};
302103285Sikob
303103285Sikobstatic void
304103285Sikobsbp_identify(driver_t *driver, device_t parent)
305103285Sikob{
306103285SikobSBP_DEBUG(0)
307103285Sikob	printf("sbp_identify\n");
308103285SikobEND_DEBUG
309103285Sikob
310266772Sjhb	if (device_find_child(parent, "sbp", -1) == NULL)
311266772Sjhb		BUS_ADD_CHILD(parent, 0, "sbp", -1);
312103285Sikob}
313103285Sikob
314103285Sikob/*
315103285Sikob * sbp_probe()
316103285Sikob */
317103285Sikobstatic int
318103285Sikobsbp_probe(device_t dev)
319103285Sikob{
320103285Sikob
321103285SikobSBP_DEBUG(0)
322103285Sikob	printf("sbp_probe\n");
323103285SikobEND_DEBUG
324103285Sikob
325120660Ssimokawa	device_set_desc(dev, "SBP-2/SCSI over FireWire");
326111615Ssimokawa
327132432Ssimokawa#if 0
328111615Ssimokawa	if (bootverbose)
329111615Ssimokawa		debug = bootverbose;
330132432Ssimokawa#endif
331132432Ssimokawa
332103285Sikob	return (0);
333103285Sikob}
334103285Sikob
335188756Ssbruno/*
336188756Ssbruno * Display device characteristics on the console
337188756Ssbruno */
338103285Sikobstatic void
339188756Ssbrunosbp_show_sdev_info(struct sbp_dev *sdev)
340103285Sikob{
341103285Sikob	struct fw_device *fwdev;
342103285Sikob
343103285Sikob	fwdev = sdev->target->fwdev;
344188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
345188756Ssbruno		"%s: %s: ordered:%d type:%d EUI:%08x%08x node:%d "
346188756Ssbruno		"speed:%d maxrec:%d\n",
347188756Ssbruno		__func__,
348188756Ssbruno		sdev->bustgtlun,
349108503Ssimokawa		(sdev->type & 0x40) >> 6,
350108503Ssimokawa		(sdev->type & 0x1f),
351103285Sikob		fwdev->eui.hi,
352103285Sikob		fwdev->eui.lo,
353103285Sikob		fwdev->dst,
354103285Sikob		fwdev->speed,
355188756Ssbruno		fwdev->maxrec);
356188756Ssbruno
357188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
358188756Ssbruno			"%s: %s '%s' '%s' '%s'\n",
359188756Ssbruno			__func__,
360188756Ssbruno			sdev->bustgtlun,
361188756Ssbruno			sdev->vendor,
362188756Ssbruno			sdev->product,
363188756Ssbruno			sdev->revision);
364103285Sikob}
365103285Sikob
366110184Ssimokawastatic struct {
367110184Ssimokawa	int bus;
368110184Ssimokawa	int target;
369110184Ssimokawa	struct fw_eui64 eui;
370110184Ssimokawa} wired[] = {
371110184Ssimokawa	/* Bus	Target	EUI64 */
372110184Ssimokawa#if 0
373110184Ssimokawa	{0,	2,	{0x00018ea0, 0x01fd0154}},	/* Logitec HDD */
374110184Ssimokawa	{0,	0,	{0x00018ea6, 0x00100682}},	/* Logitec DVD */
375110184Ssimokawa	{0,	1,	{0x00d03200, 0xa412006a}},	/* Yano HDD */
376110184Ssimokawa#endif
377110184Ssimokawa	{-1,	-1,	{0,0}}
378110184Ssimokawa};
379110184Ssimokawa
380110184Ssimokawastatic int
381110184Ssimokawasbp_new_target(struct sbp_softc *sbp, struct fw_device *fwdev)
382110184Ssimokawa{
383110184Ssimokawa	int bus, i, target=-1;
384110184Ssimokawa	char w[SBP_NUM_TARGETS];
385110184Ssimokawa
386110184Ssimokawa	bzero(w, sizeof(w));
387110184Ssimokawa	bus = device_get_unit(sbp->fd.dev);
388110184Ssimokawa
389110184Ssimokawa	/* XXX wired-down configuration should be gotten from
390110184Ssimokawa					tunable or device hint */
391272214Skan	for (i = 0; wired[i].bus >= 0; i++) {
392110184Ssimokawa		if (wired[i].bus == bus) {
393110184Ssimokawa			w[wired[i].target] = 1;
394110184Ssimokawa			if (wired[i].eui.hi == fwdev->eui.hi &&
395110184Ssimokawa					wired[i].eui.lo == fwdev->eui.lo)
396110184Ssimokawa				target = wired[i].target;
397110184Ssimokawa		}
398110184Ssimokawa	}
399110184Ssimokawa	if (target >= 0) {
400272214Skan		if (target < SBP_NUM_TARGETS &&
401110184Ssimokawa				sbp->targets[target].fwdev == NULL)
402272214Skan			return (target);
403110184Ssimokawa		device_printf(sbp->fd.dev,
404272214Skan			"target %d is not free for %08x:%08x\n",
405110184Ssimokawa			target, fwdev->eui.hi, fwdev->eui.lo);
406110184Ssimokawa		target = -1;
407110184Ssimokawa	}
408110184Ssimokawa	/* non-wired target */
409272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++)
410110184Ssimokawa		if (sbp->targets[i].fwdev == NULL && w[i] == 0) {
411110184Ssimokawa			target = i;
412110184Ssimokawa			break;
413110184Ssimokawa		}
414110184Ssimokawa
415110184Ssimokawa	return target;
416110184Ssimokawa}
417110184Ssimokawa
418121185Ssimokawastatic void
419121185Ssimokawasbp_alloc_lun(struct sbp_target *target)
420103285Sikob{
421108503Ssimokawa	struct crom_context cc;
422108503Ssimokawa	struct csrreg *reg;
423121185Ssimokawa	struct sbp_dev *sdev, **newluns;
424121185Ssimokawa	struct sbp_softc *sbp;
425121185Ssimokawa	int maxlun, lun, i;
426103285Sikob
427121185Ssimokawa	sbp = target->sbp;
428266772Sjhb	SBP_LOCK_ASSERT(sbp);
429114069Ssimokawa	crom_init_context(&cc, target->fwdev->csrrom);
430108503Ssimokawa	/* XXX shoud parse appropriate unit directories only */
431108503Ssimokawa	maxlun = -1;
432108503Ssimokawa	while (cc.depth >= 0) {
433108503Ssimokawa		reg = crom_search_key(&cc, CROM_LUN);
434108503Ssimokawa		if (reg == NULL)
435108503Ssimokawa			break;
436110839Ssimokawa		lun = reg->val & 0xffff;
437108642SsimokawaSBP_DEBUG(0)
438108642Ssimokawa		printf("target %d lun %d found\n", target->target_id, lun);
439108642SsimokawaEND_DEBUG
440108503Ssimokawa		if (maxlun < lun)
441108503Ssimokawa			maxlun = lun;
442108503Ssimokawa		crom_next(&cc);
443108503Ssimokawa	}
444110839Ssimokawa	if (maxlun < 0)
445266772Sjhb		device_printf(target->sbp->fd.dev, "%d no LUN found\n",
446121185Ssimokawa		    target->target_id);
447121185Ssimokawa
448272214Skan	maxlun++;
449110839Ssimokawa	if (maxlun >= SBP_NUM_LUNS)
450110839Ssimokawa		maxlun = SBP_NUM_LUNS;
451121185Ssimokawa
452121185Ssimokawa	/* Invalidiate stale devices */
453272214Skan	for (lun = 0; lun < target->num_lun; lun++) {
454121185Ssimokawa		sdev = target->luns[lun];
455121185Ssimokawa		if (sdev == NULL)
456121185Ssimokawa			continue;
457121185Ssimokawa		sdev->flags &= ~VALID_LUN;
458121185Ssimokawa		if (lun >= maxlun) {
459121185Ssimokawa			/* lost device */
460121185Ssimokawa			sbp_cam_detach_sdev(sdev);
461121185Ssimokawa			sbp_free_sdev(sdev);
462187993Ssbruno			target->luns[lun] = NULL;
463121185Ssimokawa		}
464103285Sikob	}
465121185Ssimokawa
466121185Ssimokawa	/* Reallocate */
467121185Ssimokawa	if (maxlun != target->num_lun) {
468121185Ssimokawa		newluns = (struct sbp_dev **) realloc(target->luns,
469121185Ssimokawa		    sizeof(struct sbp_dev *) * maxlun,
470121185Ssimokawa		    M_SBP, M_NOWAIT | M_ZERO);
471272214Skan
472121185Ssimokawa		if (newluns == NULL) {
473127468Ssimokawa			printf("%s: realloc failed\n", __func__);
474121185Ssimokawa			newluns = target->luns;
475121185Ssimokawa			maxlun = target->num_lun;
476121185Ssimokawa		}
477121185Ssimokawa
478121185Ssimokawa		/*
479121185Ssimokawa		 * We must zero the extended region for the case
480121185Ssimokawa		 * realloc() doesn't allocate new buffer.
481121185Ssimokawa		 */
482121185Ssimokawa		if (maxlun > target->num_lun)
483121185Ssimokawa			bzero(&newluns[target->num_lun],
484121185Ssimokawa			    sizeof(struct sbp_dev *) *
485121185Ssimokawa			    (maxlun - target->num_lun));
486121185Ssimokawa
487121185Ssimokawa		target->luns = newluns;
488121185Ssimokawa		target->num_lun = maxlun;
489121185Ssimokawa	}
490121185Ssimokawa
491108503Ssimokawa	crom_init_context(&cc, target->fwdev->csrrom);
492108503Ssimokawa	while (cc.depth >= 0) {
493121185Ssimokawa		int new = 0;
494121185Ssimokawa
495108503Ssimokawa		reg = crom_search_key(&cc, CROM_LUN);
496108503Ssimokawa		if (reg == NULL)
497108503Ssimokawa			break;
498110839Ssimokawa		lun = reg->val & 0xffff;
499110839Ssimokawa		if (lun >= SBP_NUM_LUNS) {
500110839Ssimokawa			printf("too large lun %d\n", lun);
501121185Ssimokawa			goto next;
502110839Ssimokawa		}
503121185Ssimokawa
504121185Ssimokawa		sdev = target->luns[lun];
505121185Ssimokawa		if (sdev == NULL) {
506121185Ssimokawa			sdev = malloc(sizeof(struct sbp_dev),
507121185Ssimokawa			    M_SBP, M_NOWAIT | M_ZERO);
508121185Ssimokawa			if (sdev == NULL) {
509127468Ssimokawa				printf("%s: malloc failed\n", __func__);
510121185Ssimokawa				goto next;
511121185Ssimokawa			}
512121185Ssimokawa			target->luns[lun] = sdev;
513121185Ssimokawa			sdev->lun_id = lun;
514121185Ssimokawa			sdev->target = target;
515121185Ssimokawa			STAILQ_INIT(&sdev->ocbs);
516266772Sjhb			callout_init_mtx(&sdev->login_callout, &sbp->mtx, 0);
517121185Ssimokawa			sdev->status = SBP_DEV_RESET;
518121185Ssimokawa			new = 1;
519188756Ssbruno			snprintf(sdev->bustgtlun, 32, "%s:%d:%d",
520188756Ssbruno					device_get_nameunit(sdev->target->sbp->fd.dev),
521188756Ssbruno					sdev->target->target_id,
522188756Ssbruno					sdev->lun_id);
523121185Ssimokawa		}
524121185Ssimokawa		sdev->flags |= VALID_LUN;
525119196Ssimokawa		sdev->type = (reg->val & 0xff0000) >> 16;
526113584Ssimokawa
527121185Ssimokawa		if (new == 0)
528121185Ssimokawa			goto next;
529121185Ssimokawa
530272214Skan		fwdma_malloc(sbp->fd.fc,
531129585Sdfr			/* alignment */ sizeof(uint32_t),
532219543Smarius			SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT |
533219543Smarius			BUS_DMA_COHERENT);
534113584Ssimokawa		if (sdev->dma.v_addr == NULL) {
535113584Ssimokawa			printf("%s: dma space allocation failed\n",
536127468Ssimokawa							__func__);
537121185Ssimokawa			free(sdev, M_SBP);
538121185Ssimokawa			target->luns[lun] = NULL;
539121185Ssimokawa			goto next;
540113584Ssimokawa		}
541113584Ssimokawa		sdev->login = (struct sbp_login_res *) sdev->dma.v_addr;
542113584Ssimokawa		sdev->ocb = (struct sbp_ocb *)
543113584Ssimokawa				((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE);
544113584Ssimokawa		bzero((char *)sdev->ocb,
545272214Skan			sizeof(struct sbp_ocb) * SBP_QUEUE_LEN);
546113584Ssimokawa
547113584Ssimokawa		STAILQ_INIT(&sdev->free_ocbs);
548113584Ssimokawa		for (i = 0; i < SBP_QUEUE_LEN; i++) {
549113584Ssimokawa			struct sbp_ocb *ocb;
550113584Ssimokawa			ocb = &sdev->ocb[i];
551113584Ssimokawa			ocb->bus_addr = sdev->dma.bus_addr
552113584Ssimokawa				+ SBP_LOGIN_SIZE
553113584Ssimokawa				+ sizeof(struct sbp_ocb) * i
554113584Ssimokawa				+ offsetof(struct sbp_ocb, orb[0]);
555113584Ssimokawa			if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) {
556113584Ssimokawa				printf("sbp_attach: cannot create dmamap\n");
557121185Ssimokawa				/* XXX */
558121185Ssimokawa				goto next;
559113584Ssimokawa			}
560266772Sjhb			callout_init_mtx(&ocb->timer, &sbp->mtx, 0);
561113584Ssimokawa			sbp_free_ocb(sdev, ocb);
562113584Ssimokawa		}
563121185Ssimokawanext:
564108503Ssimokawa		crom_next(&cc);
565103285Sikob	}
566121185Ssimokawa
567272214Skan	for (lun = 0; lun < target->num_lun; lun++) {
568121185Ssimokawa		sdev = target->luns[lun];
569121185Ssimokawa		if (sdev != NULL && (sdev->flags & VALID_LUN) == 0) {
570121185Ssimokawa			sbp_cam_detach_sdev(sdev);
571121185Ssimokawa			sbp_free_sdev(sdev);
572121185Ssimokawa			target->luns[lun] = NULL;
573121185Ssimokawa		}
574121185Ssimokawa	}
575121185Ssimokawa}
576121185Ssimokawa
577121185Ssimokawastatic struct sbp_target *
578121185Ssimokawasbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev)
579121185Ssimokawa{
580121185Ssimokawa	int i;
581121185Ssimokawa	struct sbp_target *target;
582121185Ssimokawa	struct crom_context cc;
583121185Ssimokawa	struct csrreg *reg;
584121185Ssimokawa
585121185SsimokawaSBP_DEBUG(1)
586121185Ssimokawa	printf("sbp_alloc_target\n");
587121185SsimokawaEND_DEBUG
588121185Ssimokawa	i = sbp_new_target(sbp, fwdev);
589121185Ssimokawa	if (i < 0) {
590121185Ssimokawa		device_printf(sbp->fd.dev, "increase SBP_NUM_TARGETS!\n");
591121185Ssimokawa		return NULL;
592121185Ssimokawa	}
593121185Ssimokawa	/* new target */
594121185Ssimokawa	target = &sbp->targets[i];
595121185Ssimokawa	target->fwdev = fwdev;
596121185Ssimokawa	target->target_id = i;
597121185Ssimokawa	/* XXX we may want to reload mgm port after each bus reset */
598121185Ssimokawa	/* XXX there might be multiple management agents */
599121185Ssimokawa	crom_init_context(&cc, target->fwdev->csrrom);
600121185Ssimokawa	reg = crom_search_key(&cc, CROM_MGM);
601121185Ssimokawa	if (reg == NULL || reg->val == 0) {
602121185Ssimokawa		printf("NULL management address\n");
603121185Ssimokawa		target->fwdev = NULL;
604121185Ssimokawa		return NULL;
605121185Ssimokawa	}
606121185Ssimokawa	target->mgm_hi = 0xffff;
607121185Ssimokawa	target->mgm_lo = 0xf0000000 | (reg->val << 2);
608121185Ssimokawa	target->mgm_ocb_cur = NULL;
609121185SsimokawaSBP_DEBUG(1)
610121185Ssimokawa	printf("target:%d mgm_port: %x\n", i, target->mgm_lo);
611121185SsimokawaEND_DEBUG
612121185Ssimokawa	STAILQ_INIT(&target->xferlist);
613121185Ssimokawa	target->n_xfer = 0;
614121185Ssimokawa	STAILQ_INIT(&target->mgm_ocb_queue);
615266772Sjhb	callout_init_mtx(&target->mgm_ocb_timeout, &sbp->mtx, 0);
616266772Sjhb	callout_init_mtx(&target->scan_callout, &sbp->mtx, 0);
617121185Ssimokawa
618121185Ssimokawa	target->luns = NULL;
619121185Ssimokawa	target->num_lun = 0;
620114069Ssimokawa	return target;
621103285Sikob}
622103285Sikob
623103285Sikobstatic void
624103285Sikobsbp_probe_lun(struct sbp_dev *sdev)
625103285Sikob{
626103285Sikob	struct fw_device *fwdev;
627114069Ssimokawa	struct crom_context c, *cc = &c;
628114069Ssimokawa	struct csrreg *reg;
629103285Sikob
630103285Sikob	bzero(sdev->vendor, sizeof(sdev->vendor));
631103285Sikob	bzero(sdev->product, sizeof(sdev->product));
632114069Ssimokawa
633114069Ssimokawa	fwdev = sdev->target->fwdev;
634114069Ssimokawa	crom_init_context(cc, fwdev->csrrom);
635114069Ssimokawa	/* get vendor string */
636114069Ssimokawa	crom_search_key(cc, CSRKEY_VENDOR);
637114069Ssimokawa	crom_next(cc);
638114069Ssimokawa	crom_parse_text(cc, sdev->vendor, sizeof(sdev->vendor));
639114223Ssimokawa	/* skip to the unit directory for SBP-2 */
640114260Ssimokawa	while ((reg = crom_search_key(cc, CSRKEY_VER)) != NULL) {
641114223Ssimokawa		if (reg->val == CSRVAL_T10SBP2)
642114223Ssimokawa			break;
643114260Ssimokawa		crom_next(cc);
644114260Ssimokawa	}
645114069Ssimokawa	/* get firmware revision */
646114069Ssimokawa	reg = crom_search_key(cc, CSRKEY_FIRM_VER);
647114069Ssimokawa	if (reg != NULL)
648114069Ssimokawa		snprintf(sdev->revision, sizeof(sdev->revision),
649114069Ssimokawa						"%06x", reg->val);
650114069Ssimokawa	/* get product string */
651114069Ssimokawa	crom_search_key(cc, CSRKEY_MODEL);
652114069Ssimokawa	crom_next(cc);
653114069Ssimokawa	crom_parse_text(cc, sdev->product, sizeof(sdev->product));
654103285Sikob}
655111615Ssimokawa
656103285Sikobstatic void
657111615Ssimokawasbp_login_callout(void *arg)
658103285Sikob{
659111615Ssimokawa	struct sbp_dev *sdev = (struct sbp_dev *)arg;
660266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
661111615Ssimokawa	sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL);
662111615Ssimokawa}
663111615Ssimokawa
664122387Ssimokawastatic void
665122387Ssimokawasbp_login(struct sbp_dev *sdev)
666122387Ssimokawa{
667122387Ssimokawa	struct timeval delta;
668122387Ssimokawa	struct timeval t;
669122387Ssimokawa	int ticks = 0;
670122387Ssimokawa
671122387Ssimokawa	microtime(&delta);
672122387Ssimokawa	timevalsub(&delta, &sdev->target->sbp->last_busreset);
673122387Ssimokawa	t.tv_sec = login_delay / 1000;
674122387Ssimokawa	t.tv_usec = (login_delay % 1000) * 1000;
675122387Ssimokawa	timevalsub(&t, &delta);
676122387Ssimokawa	if (t.tv_sec >= 0 && t.tv_usec > 0)
677122387Ssimokawa		ticks = (t.tv_sec * 1000 + t.tv_usec / 1000) * hz / 1000;
678122387SsimokawaSBP_DEBUG(0)
679153706Strhodes	printf("%s: sec = %jd usec = %ld ticks = %d\n", __func__,
680153706Strhodes	    (intmax_t)t.tv_sec, t.tv_usec, ticks);
681122387SsimokawaEND_DEBUG
682122387Ssimokawa	callout_reset(&sdev->login_callout, ticks,
683122387Ssimokawa			sbp_login_callout, (void *)(sdev));
684122387Ssimokawa}
685122387Ssimokawa
686114069Ssimokawa#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \
687114069Ssimokawa	&& crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2))
688111615Ssimokawa
689111615Ssimokawastatic void
690111615Ssimokawasbp_probe_target(void *arg)
691111615Ssimokawa{
692111615Ssimokawa	struct sbp_target *target = (struct sbp_target *)arg;
693188756Ssbruno	struct sbp_softc *sbp = target->sbp;
694103285Sikob	struct sbp_dev *sdev;
695111615Ssimokawa	int i, alive;
696103285Sikob
697111615Ssimokawa	alive = SBP_FWDEV_ALIVE(target->fwdev);
698103285SikobSBP_DEBUG(1)
699188756Ssbruno	device_printf(sbp->fd.dev, "%s %d%salive\n",
700188756Ssbruno		 __func__, target->target_id,
701188756Ssbruno		(!alive) ? " not " : "");
702103285SikobEND_DEBUG
703103285Sikob
704103285Sikob	sbp = target->sbp;
705266772Sjhb	SBP_LOCK_ASSERT(sbp);
706121185Ssimokawa	sbp_alloc_lun(target);
707121185Ssimokawa
708111615Ssimokawa	/* XXX untimeout mgm_ocb and dequeue */
709103285Sikob	for (i=0; i < target->num_lun; i++) {
710121185Ssimokawa		sdev = target->luns[i];
711121185Ssimokawa		if (sdev == NULL)
712121185Ssimokawa			continue;
713103285Sikob		if (alive && (sdev->status != SBP_DEV_DEAD)) {
714103285Sikob			if (sdev->path != NULL) {
715103285Sikob				xpt_freeze_devq(sdev->path, 1);
716272214Skan				sdev->freeze++;
717103285Sikob			}
718111615Ssimokawa			sbp_probe_lun(sdev);
719188756Ssbruno			sbp_show_sdev_info(sdev);
720111615Ssimokawa
721111615Ssimokawa			sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET);
722103285Sikob			switch (sdev->status) {
723110336Ssimokawa			case SBP_DEV_RESET:
724103285Sikob				/* new or revived target */
725113584Ssimokawa				if (auto_login)
726111615Ssimokawa					sbp_login(sdev);
727103285Sikob				break;
728111615Ssimokawa			case SBP_DEV_TOATTACH:
729111615Ssimokawa			case SBP_DEV_PROBE:
730111615Ssimokawa			case SBP_DEV_ATTACHED:
731110336Ssimokawa			case SBP_DEV_RETRY:
732110336Ssimokawa			default:
733111615Ssimokawa				sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL);
734110336Ssimokawa				break;
735103285Sikob			}
736103285Sikob		} else {
737103285Sikob			switch (sdev->status) {
738103285Sikob			case SBP_DEV_ATTACHED:
739103285SikobSBP_DEBUG(0)
740103285Sikob				/* the device has gone */
741188756Ssbruno				device_printf(sbp->fd.dev, "%s: lost target\n",
742188756Ssbruno					__func__);
743103285SikobEND_DEBUG
744111615Ssimokawa				if (sdev->path) {
745103285Sikob					xpt_freeze_devq(sdev->path, 1);
746272214Skan					sdev->freeze++;
747111615Ssimokawa				}
748103285Sikob				sdev->status = SBP_DEV_RETRY;
749187993Ssbruno				sbp_cam_detach_sdev(sdev);
750187993Ssbruno				sbp_free_sdev(sdev);
751187993Ssbruno				target->luns[i] = NULL;
752103285Sikob				break;
753103285Sikob			case SBP_DEV_PROBE:
754103285Sikob			case SBP_DEV_TOATTACH:
755103285Sikob				sdev->status = SBP_DEV_RESET;
756103285Sikob				break;
757103285Sikob			case SBP_DEV_RETRY:
758103285Sikob			case SBP_DEV_RESET:
759103285Sikob			case SBP_DEV_DEAD:
760103285Sikob				break;
761103285Sikob			}
762103285Sikob		}
763103285Sikob	}
764103285Sikob}
765103285Sikob
766103285Sikobstatic void
767113584Ssimokawasbp_post_busreset(void *arg)
768113584Ssimokawa{
769113584Ssimokawa	struct sbp_softc *sbp;
770113584Ssimokawa
771113584Ssimokawa	sbp = (struct sbp_softc *)arg;
772113584SsimokawaSBP_DEBUG(0)
773113584Ssimokawa	printf("sbp_post_busreset\n");
774113584SsimokawaEND_DEBUG
775266772Sjhb	SBP_LOCK(sbp);
776124145Ssimokawa	if ((sbp->sim->flags & SIMQ_FREEZED) == 0) {
777124145Ssimokawa		xpt_freeze_simq(sbp->sim, /*count*/1);
778124145Ssimokawa		sbp->sim->flags |= SIMQ_FREEZED;
779124145Ssimokawa	}
780122387Ssimokawa	microtime(&sbp->last_busreset);
781266772Sjhb	SBP_UNLOCK(sbp);
782113584Ssimokawa}
783113584Ssimokawa
784113584Ssimokawastatic void
785103285Sikobsbp_post_explore(void *arg)
786103285Sikob{
787103285Sikob	struct sbp_softc *sbp = (struct sbp_softc *)arg;
788103285Sikob	struct sbp_target *target;
789103285Sikob	struct fw_device *fwdev;
790103285Sikob	int i, alive;
791103285Sikob
792111199SsimokawaSBP_DEBUG(0)
793111199Ssimokawa	printf("sbp_post_explore (sbp_cold=%d)\n", sbp_cold);
794103285SikobEND_DEBUG
795170400Ssimokawa	/* We need physical access */
796170400Ssimokawa	if (!firewire_phydma_enable)
797170400Ssimokawa		return;
798170400Ssimokawa
799122387Ssimokawa	if (sbp_cold > 0)
800272214Skan		sbp_cold--;
801122387Ssimokawa
802266772Sjhb	SBP_LOCK(sbp);
803122387Ssimokawa#if 0
804122387Ssimokawa	/*
805122387Ssimokawa	 * XXX don't let CAM the bus rest.
806122387Ssimokawa	 * CAM tries to do something with freezed (DEV_RETRY) devices.
807111615Ssimokawa	 */
808111615Ssimokawa	xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL);
809103285Sikob#endif
810111615Ssimokawa
811130532Sdfr	/* Garbage Collection */
812272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++) {
813103285Sikob		target = &sbp->targets[i];
814110193Ssimokawa		STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link)
815110193Ssimokawa			if (target->fwdev == NULL || target->fwdev == fwdev)
816110193Ssimokawa				break;
817121185Ssimokawa		if (fwdev == NULL) {
818103285Sikob			/* device has removed in lower driver */
819110145Ssimokawa			sbp_cam_detach_target(target);
820121185Ssimokawa			sbp_free_target(target);
821103285Sikob		}
822103285Sikob	}
823103285Sikob	/* traverse device list */
824110193Ssimokawa	STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) {
825103285SikobSBP_DEBUG(0)
826188756Ssbruno		device_printf(sbp->fd.dev,"%s:: EUI:%08x%08x %s attached, state=%d\n",
827188756Ssbruno				__func__, fwdev->eui.hi, fwdev->eui.lo,
828188756Ssbruno				(fwdev->status != FWDEVATTACHED) ? "not" : "",
829188756Ssbruno				fwdev->status);
830103285SikobEND_DEBUG
831111615Ssimokawa		alive = SBP_FWDEV_ALIVE(fwdev);
832272214Skan		for (i = 0; i < SBP_NUM_TARGETS; i++) {
833103285Sikob			target = &sbp->targets[i];
834272214Skan			if (target->fwdev == fwdev) {
835103285Sikob				/* known target */
836103285Sikob				break;
837103285Sikob			}
838103285Sikob		}
839272214Skan		if (i == SBP_NUM_TARGETS) {
840103285Sikob			if (alive) {
841103285Sikob				/* new target */
842103285Sikob				target = sbp_alloc_target(sbp, fwdev);
843103285Sikob				if (target == NULL)
844103285Sikob					continue;
845103285Sikob			} else {
846103285Sikob				continue;
847103285Sikob			}
848103285Sikob		}
849111615Ssimokawa		sbp_probe_target((void *)target);
850121185Ssimokawa		if (target->num_lun == 0)
851121185Ssimokawa			sbp_free_target(target);
852103285Sikob	}
853124145Ssimokawa	xpt_release_simq(sbp->sim, /*run queue*/TRUE);
854124145Ssimokawa	sbp->sim->flags &= ~SIMQ_FREEZED;
855170374Ssimokawa	SBP_UNLOCK(sbp);
856103285Sikob}
857103285Sikob
858103285Sikob#if NEED_RESPONSE
859103285Sikobstatic void
860272214Skansbp_loginres_callback(struct fw_xfer *xfer)
861272214Skan{
862103285Sikob	struct sbp_dev *sdev;
863103285Sikob	sdev = (struct sbp_dev *)xfer->sc;
864113584SsimokawaSBP_DEBUG(1)
865188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,"%s\n", __func__);
866103285SikobEND_DEBUG
867113584Ssimokawa	/* recycle */
868266772Sjhb	SBP_LOCK(sdev->target->sbp);
869113584Ssimokawa	STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link);
870266772Sjhb	SBP_UNLOCK(sdev->target->sbp);
871103285Sikob	return;
872103285Sikob}
873103285Sikob#endif
874103285Sikob
875113584Ssimokawastatic __inline void
876113584Ssimokawasbp_xfer_free(struct fw_xfer *xfer)
877113584Ssimokawa{
878113584Ssimokawa	struct sbp_dev *sdev;
879113584Ssimokawa
880113584Ssimokawa	sdev = (struct sbp_dev *)xfer->sc;
881113584Ssimokawa	fw_xfer_unload(xfer);
882266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
883113584Ssimokawa	STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link);
884113584Ssimokawa}
885113584Ssimokawa
886103285Sikobstatic void
887114732Ssimokawasbp_reset_start_callback(struct fw_xfer *xfer)
888103285Sikob{
889114732Ssimokawa	struct sbp_dev *tsdev, *sdev = (struct sbp_dev *)xfer->sc;
890114732Ssimokawa	struct sbp_target *target = sdev->target;
891114732Ssimokawa	int i;
892114732Ssimokawa
893114732Ssimokawa	if (xfer->resp != 0) {
894188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
895188756Ssbruno			"%s: %s failed: resp=%d\n", __func__, sdev->bustgtlun, xfer->resp);
896114732Ssimokawa	}
897114732Ssimokawa
898266772Sjhb	SBP_LOCK(target->sbp);
899114732Ssimokawa	for (i = 0; i < target->num_lun; i++) {
900121185Ssimokawa		tsdev = target->luns[i];
901121185Ssimokawa		if (tsdev != NULL && tsdev->status == SBP_DEV_LOGIN)
902121185Ssimokawa			sbp_login(tsdev);
903114732Ssimokawa	}
904266772Sjhb	SBP_UNLOCK(target->sbp);
905114732Ssimokawa}
906114732Ssimokawa
907114732Ssimokawastatic void
908114732Ssimokawasbp_reset_start(struct sbp_dev *sdev)
909114732Ssimokawa{
910114732Ssimokawa	struct fw_xfer *xfer;
911114732Ssimokawa	struct fw_pkt *fp;
912114732Ssimokawa
913114732SsimokawaSBP_DEBUG(0)
914188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
915188756Ssbruno			"%s:%s\n", __func__,sdev->bustgtlun);
916114732SsimokawaEND_DEBUG
917114732Ssimokawa
918114732Ssimokawa	xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
919167632Ssimokawa	xfer->hand = sbp_reset_start_callback;
920120660Ssimokawa	fp = &xfer->send.hdr;
921114732Ssimokawa	fp->mode.wreqq.dest_hi = 0xffff;
922114732Ssimokawa	fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
923114732Ssimokawa	fp->mode.wreqq.data = htonl(0xf);
924114732Ssimokawa	fw_asyreq(xfer->fc, -1, xfer);
925114732Ssimokawa}
926114732Ssimokawa
927114732Ssimokawastatic void
928114732Ssimokawasbp_mgm_callback(struct fw_xfer *xfer)
929114732Ssimokawa{
930103285Sikob	struct sbp_dev *sdev;
931114732Ssimokawa	int resp;
932114732Ssimokawa
933103285Sikob	sdev = (struct sbp_dev *)xfer->sc;
934114732Ssimokawa
935114732SsimokawaSBP_DEBUG(1)
936188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
937188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
938103285SikobEND_DEBUG
939114732Ssimokawa	resp = xfer->resp;
940266772Sjhb	SBP_LOCK(sdev->target->sbp);
941113584Ssimokawa	sbp_xfer_free(xfer);
942266772Sjhb	SBP_UNLOCK(sdev->target->sbp);
943103285Sikob}
944103285Sikob
945111615Ssimokawastatic struct sbp_dev *
946111615Ssimokawasbp_next_dev(struct sbp_target *target, int lun)
947111615Ssimokawa{
948121185Ssimokawa	struct sbp_dev **sdevp;
949111615Ssimokawa	int i;
950111615Ssimokawa
951121185Ssimokawa	for (i = lun, sdevp = &target->luns[lun]; i < target->num_lun;
952121185Ssimokawa	    i++, sdevp++)
953121185Ssimokawa		if (*sdevp != NULL && (*sdevp)->status == SBP_DEV_PROBE)
954272214Skan			return (*sdevp);
955272214Skan	return (NULL);
956111615Ssimokawa}
957111615Ssimokawa
958111615Ssimokawa#define SCAN_PRI 1
959103285Sikobstatic void
960111615Ssimokawasbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb)
961103285Sikob{
962111615Ssimokawa	struct sbp_target *target;
963103285Sikob	struct sbp_dev *sdev;
964111615Ssimokawa
965103285Sikob	sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
966111615Ssimokawa	target = sdev->target;
967266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
968110269SsimokawaSBP_DEBUG(0)
969188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
970188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
971103285SikobEND_DEBUG
972111615Ssimokawa	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
973111615Ssimokawa		sdev->status = SBP_DEV_ATTACHED;
974111615Ssimokawa	} else {
975188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
976188756Ssbruno			"%s:%s failed\n", __func__, sdev->bustgtlun);
977111615Ssimokawa	}
978111615Ssimokawa	sdev = sbp_next_dev(target, sdev->lun_id + 1);
979111615Ssimokawa	if (sdev == NULL) {
980111615Ssimokawa		free(ccb, M_SBP);
981111615Ssimokawa		return;
982111615Ssimokawa	}
983111615Ssimokawa	/* reuse ccb */
984111615Ssimokawa	xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI);
985111615Ssimokawa	ccb->ccb_h.ccb_sdev_ptr = sdev;
986111615Ssimokawa	xpt_action(ccb);
987111615Ssimokawa	xpt_release_devq(sdev->path, sdev->freeze, TRUE);
988111615Ssimokawa	sdev->freeze = 1;
989103285Sikob}
990103285Sikob
991103285Sikobstatic void
992111615Ssimokawasbp_cam_scan_target(void *arg)
993103285Sikob{
994111615Ssimokawa	struct sbp_target *target = (struct sbp_target *)arg;
995111615Ssimokawa	struct sbp_dev *sdev;
996110798Ssimokawa	union ccb *ccb;
997103285Sikob
998266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
999111615Ssimokawa	sdev = sbp_next_dev(target, 0);
1000111615Ssimokawa	if (sdev == NULL) {
1001111615Ssimokawa		printf("sbp_cam_scan_target: nothing to do for target%d\n",
1002111615Ssimokawa							target->target_id);
1003110798Ssimokawa		return;
1004110798Ssimokawa	}
1005103285SikobSBP_DEBUG(0)
1006188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1007188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1008103285SikobEND_DEBUG
1009111615Ssimokawa	ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO);
1010111615Ssimokawa	if (ccb == NULL) {
1011111615Ssimokawa		printf("sbp_cam_scan_target: malloc failed\n");
1012111615Ssimokawa		return;
1013111615Ssimokawa	}
1014111615Ssimokawa	xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI);
1015103285Sikob	ccb->ccb_h.func_code = XPT_SCAN_LUN;
1016111615Ssimokawa	ccb->ccb_h.cbfcnp = sbp_cam_scan_lun;
1017111615Ssimokawa	ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
1018103285Sikob	ccb->crcn.flags = CAM_FLAG_NONE;
1019103285Sikob	ccb->ccb_h.ccb_sdev_ptr = sdev;
1020103285Sikob
1021103285Sikob	/* The scan is in progress now. */
1022111040Ssimokawa	xpt_action(ccb);
1023111615Ssimokawa	xpt_release_devq(sdev->path, sdev->freeze, TRUE);
1024111615Ssimokawa	sdev->freeze = 1;
1025103285Sikob}
1026103285Sikob
1027111615Ssimokawastatic __inline void
1028111615Ssimokawasbp_scan_dev(struct sbp_dev *sdev)
1029111615Ssimokawa{
1030111040Ssimokawa	sdev->status = SBP_DEV_PROBE;
1031274819Ssmh	callout_reset_sbt(&sdev->target->scan_callout, SBT_1MS * scan_delay, 0,
1032274819Ssmh	    sbp_cam_scan_target, (void *)sdev->target, 0);
1033103285Sikob}
1034103285Sikob
1035103285Sikobstatic void
1036103285Sikobsbp_do_attach(struct fw_xfer *xfer)
1037103285Sikob{
1038103285Sikob	struct sbp_dev *sdev;
1039111615Ssimokawa	struct sbp_target *target;
1040111615Ssimokawa	struct sbp_softc *sbp;
1041103285Sikob
1042103285Sikob	sdev = (struct sbp_dev *)xfer->sc;
1043111615Ssimokawa	target = sdev->target;
1044111615Ssimokawa	sbp = target->sbp;
1045266772Sjhb	SBP_LOCK(sbp);
1046103285SikobSBP_DEBUG(0)
1047188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1048188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1049103285SikobEND_DEBUG
1050113584Ssimokawa	sbp_xfer_free(xfer);
1051111199Ssimokawa
1052103285Sikob	if (sdev->path == NULL)
1053249468Smav		xpt_create_path(&sdev->path, NULL,
1054111615Ssimokawa			cam_sim_path(target->sbp->sim),
1055111615Ssimokawa			target->target_id, sdev->lun_id);
1056103285Sikob
1057111199Ssimokawa	/*
1058111199Ssimokawa	 * Let CAM scan the bus if we are in the boot process.
1059111199Ssimokawa	 * XXX xpt_scan_bus cannot detect LUN larger than 0
1060266772Sjhb	 * if LUN 0 doesn't exist.
1061111199Ssimokawa	 */
1062111199Ssimokawa	if (sbp_cold > 0) {
1063111615Ssimokawa		sdev->status = SBP_DEV_ATTACHED;
1064266772Sjhb		SBP_UNLOCK(sbp);
1065111199Ssimokawa		return;
1066111199Ssimokawa	}
1067111199Ssimokawa
1068111615Ssimokawa	sbp_scan_dev(sdev);
1069266772Sjhb	SBP_UNLOCK(sbp);
1070103285Sikob}
1071103285Sikob
1072103285Sikobstatic void
1073103285Sikobsbp_agent_reset_callback(struct fw_xfer *xfer)
1074103285Sikob{
1075103285Sikob	struct sbp_dev *sdev;
1076103285Sikob
1077103285Sikob	sdev = (struct sbp_dev *)xfer->sc;
1078103285SikobSBP_DEBUG(1)
1079188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1080188756Ssbruno			"%s:%s\n", __func__, sdev->bustgtlun);
1081103285SikobEND_DEBUG
1082114732Ssimokawa	if (xfer->resp != 0) {
1083188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1084188756Ssbruno			"%s:%s resp=%d\n", __func__, sdev->bustgtlun, xfer->resp);
1085114732Ssimokawa	}
1086114732Ssimokawa
1087266772Sjhb	SBP_LOCK(sdev->target->sbp);
1088113584Ssimokawa	sbp_xfer_free(xfer);
1089111615Ssimokawa	if (sdev->path) {
1090111615Ssimokawa		xpt_release_devq(sdev->path, sdev->freeze, TRUE);
1091111615Ssimokawa		sdev->freeze = 0;
1092111615Ssimokawa	}
1093266772Sjhb	SBP_UNLOCK(sdev->target->sbp);
1094103285Sikob}
1095103285Sikob
1096103285Sikobstatic void
1097110336Ssimokawasbp_agent_reset(struct sbp_dev *sdev)
1098103285Sikob{
1099103285Sikob	struct fw_xfer *xfer;
1100103285Sikob	struct fw_pkt *fp;
1101103285Sikob
1102266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
1103103285SikobSBP_DEBUG(0)
1104188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1105188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1106103285SikobEND_DEBUG
1107103285Sikob	xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04);
1108103285Sikob	if (xfer == NULL)
1109103285Sikob		return;
1110115788Ssimokawa	if (sdev->status == SBP_DEV_ATTACHED || sdev->status == SBP_DEV_PROBE)
1111167632Ssimokawa		xfer->hand = sbp_agent_reset_callback;
1112110336Ssimokawa	else
1113167632Ssimokawa		xfer->hand = sbp_do_attach;
1114120660Ssimokawa	fp = &xfer->send.hdr;
1115103285Sikob	fp->mode.wreqq.data = htonl(0xf);
1116103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
1117111615Ssimokawa	sbp_abort_all_ocbs(sdev, CAM_BDR_SENT);
1118103285Sikob}
1119103285Sikob
1120103285Sikobstatic void
1121103285Sikobsbp_busy_timeout_callback(struct fw_xfer *xfer)
1122103285Sikob{
1123103285Sikob	struct sbp_dev *sdev;
1124103285Sikob
1125103285Sikob	sdev = (struct sbp_dev *)xfer->sc;
1126103285SikobSBP_DEBUG(1)
1127188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1128188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1129103285SikobEND_DEBUG
1130266772Sjhb	SBP_LOCK(sdev->target->sbp);
1131113584Ssimokawa	sbp_xfer_free(xfer);
1132110336Ssimokawa	sbp_agent_reset(sdev);
1133266772Sjhb	SBP_UNLOCK(sdev->target->sbp);
1134103285Sikob}
1135103285Sikob
1136103285Sikobstatic void
1137103285Sikobsbp_busy_timeout(struct sbp_dev *sdev)
1138103285Sikob{
1139103285Sikob	struct fw_pkt *fp;
1140103285Sikob	struct fw_xfer *xfer;
1141103285SikobSBP_DEBUG(0)
1142188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1143188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1144103285SikobEND_DEBUG
1145103285Sikob	xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0);
1146103285Sikob
1147167632Ssimokawa	xfer->hand = sbp_busy_timeout_callback;
1148120660Ssimokawa	fp = &xfer->send.hdr;
1149113584Ssimokawa	fp->mode.wreqq.dest_hi = 0xffff;
1150113584Ssimokawa	fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT;
1151272214Skan	fp->mode.wreqq.data = htonl((1 << (13 + 12)) | 0xf);
1152103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
1153103285Sikob}
1154103285Sikob
1155103285Sikobstatic void
1156121185Ssimokawasbp_orb_pointer_callback(struct fw_xfer *xfer)
1157121185Ssimokawa{
1158121185Ssimokawa	struct sbp_dev *sdev;
1159121185Ssimokawa	sdev = (struct sbp_dev *)xfer->sc;
1160121185Ssimokawa
1161170807SsimokawaSBP_DEBUG(2)
1162188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1163188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1164121185SsimokawaEND_DEBUG
1165121185Ssimokawa	if (xfer->resp != 0) {
1166121185Ssimokawa		/* XXX */
1167127468Ssimokawa		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1168121185Ssimokawa	}
1169266772Sjhb	SBP_LOCK(sdev->target->sbp);
1170121185Ssimokawa	sbp_xfer_free(xfer);
1171170807Ssimokawa
1172121185Ssimokawa	sdev->flags &= ~ORB_POINTER_ACTIVE;
1173121185Ssimokawa
1174121185Ssimokawa	if ((sdev->flags & ORB_POINTER_NEED) != 0) {
1175121185Ssimokawa		struct sbp_ocb *ocb;
1176121185Ssimokawa
1177121185Ssimokawa		sdev->flags &= ~ORB_POINTER_NEED;
1178121185Ssimokawa		ocb = STAILQ_FIRST(&sdev->ocbs);
1179121185Ssimokawa		if (ocb != NULL)
1180121185Ssimokawa			sbp_orb_pointer(sdev, ocb);
1181121185Ssimokawa	}
1182170807Ssimokawa	SBP_UNLOCK(sdev->target->sbp);
1183121185Ssimokawa	return;
1184121185Ssimokawa}
1185121185Ssimokawa
1186121185Ssimokawastatic void
1187103285Sikobsbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb)
1188103285Sikob{
1189103285Sikob	struct fw_xfer *xfer;
1190103285Sikob	struct fw_pkt *fp;
1191121185SsimokawaSBP_DEBUG(1)
1192188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1193188756Ssbruno		"%s:%s 0x%08x\n",
1194188756Ssbruno		__func__, sdev->bustgtlun,
1195188756Ssbruno		(uint32_t)ocb->bus_addr);
1196103285SikobEND_DEBUG
1197103285Sikob
1198266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
1199170807Ssimokawa
1200121185Ssimokawa	if ((sdev->flags & ORB_POINTER_ACTIVE) != 0) {
1201122421SsimokawaSBP_DEBUG(0)
1202127468Ssimokawa		printf("%s: orb pointer active\n", __func__);
1203122421SsimokawaEND_DEBUG
1204121185Ssimokawa		sdev->flags |= ORB_POINTER_NEED;
1205121185Ssimokawa		return;
1206121185Ssimokawa	}
1207121185Ssimokawa
1208121185Ssimokawa	sdev->flags |= ORB_POINTER_ACTIVE;
1209266772Sjhb	xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08);
1210103285Sikob	if (xfer == NULL)
1211103285Sikob		return;
1212167632Ssimokawa	xfer->hand = sbp_orb_pointer_callback;
1213103285Sikob
1214120660Ssimokawa	fp = &xfer->send.hdr;
1215113584Ssimokawa	fp->mode.wreqb.len = 8;
1216103285Sikob	fp->mode.wreqb.extcode = 0;
1217272214Skan	xfer->send.payload[0] =
1218272214Skan		htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS) << 16));
1219129585Sdfr	xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr);
1220103285Sikob
1221266772Sjhb	if (fw_asyreq(xfer->fc, -1, xfer) != 0) {
1222266772Sjhb		sbp_xfer_free(xfer);
1223266772Sjhb		ocb->ccb->ccb_h.status = CAM_REQ_INVALID;
1224266772Sjhb		xpt_done(ocb->ccb);
1225103285Sikob	}
1226103285Sikob}
1227103285Sikob
1228103285Sikobstatic void
1229127468Ssimokawasbp_doorbell_callback(struct fw_xfer *xfer)
1230121185Ssimokawa{
1231121185Ssimokawa	struct sbp_dev *sdev;
1232121185Ssimokawa	sdev = (struct sbp_dev *)xfer->sc;
1233127468Ssimokawa
1234127468SsimokawaSBP_DEBUG(1)
1235188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1236188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1237121185SsimokawaEND_DEBUG
1238121185Ssimokawa	if (xfer->resp != 0) {
1239121185Ssimokawa		/* XXX */
1240188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1241188756Ssbruno			"%s: xfer->resp = %d\n", __func__, xfer->resp);
1242121185Ssimokawa	}
1243266772Sjhb	SBP_LOCK(sdev->target->sbp);
1244121185Ssimokawa	sbp_xfer_free(xfer);
1245127468Ssimokawa	sdev->flags &= ~ORB_DOORBELL_ACTIVE;
1246127468Ssimokawa	if ((sdev->flags & ORB_DOORBELL_NEED) != 0) {
1247127468Ssimokawa		sdev->flags &= ~ORB_DOORBELL_NEED;
1248127468Ssimokawa		sbp_doorbell(sdev);
1249127468Ssimokawa	}
1250266772Sjhb	SBP_UNLOCK(sdev->target->sbp);
1251121185Ssimokawa}
1252121185Ssimokawa
1253121185Ssimokawastatic void
1254103285Sikobsbp_doorbell(struct sbp_dev *sdev)
1255103285Sikob{
1256103285Sikob	struct fw_xfer *xfer;
1257103285Sikob	struct fw_pkt *fp;
1258103285SikobSBP_DEBUG(1)
1259188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1260188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1261103285SikobEND_DEBUG
1262103285Sikob
1263127468Ssimokawa	if ((sdev->flags & ORB_DOORBELL_ACTIVE) != 0) {
1264127468Ssimokawa		sdev->flags |= ORB_DOORBELL_NEED;
1265127468Ssimokawa		return;
1266127468Ssimokawa	}
1267127468Ssimokawa	sdev->flags |= ORB_DOORBELL_ACTIVE;
1268266772Sjhb	xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10);
1269103285Sikob	if (xfer == NULL)
1270103285Sikob		return;
1271167632Ssimokawa	xfer->hand = sbp_doorbell_callback;
1272127468Ssimokawa	fp = &xfer->send.hdr;
1273103285Sikob	fp->mode.wreqq.data = htonl(0xf);
1274103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
1275103285Sikob}
1276103285Sikob
1277103285Sikobstatic struct fw_xfer *
1278266772Sjhbsbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
1279103285Sikob{
1280103285Sikob	struct fw_xfer *xfer;
1281103285Sikob	struct fw_pkt *fp;
1282113584Ssimokawa	struct sbp_target *target;
1283266772Sjhb	int new = 0;
1284103285Sikob
1285266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
1286170807Ssimokawa
1287113584Ssimokawa	target = sdev->target;
1288113584Ssimokawa	xfer = STAILQ_FIRST(&target->xferlist);
1289113584Ssimokawa	if (xfer == NULL) {
1290113584Ssimokawa		if (target->n_xfer > 5 /* XXX */) {
1291113584Ssimokawa			printf("sbp: no more xfer for this target\n");
1292272214Skan			return (NULL);
1293113584Ssimokawa		}
1294120660Ssimokawa		xfer = fw_xfer_alloc_buf(M_SBP, 8, 0);
1295272214Skan		if (xfer == NULL) {
1296113584Ssimokawa			printf("sbp: fw_xfer_alloc_buf failed\n");
1297113584Ssimokawa			return NULL;
1298113584Ssimokawa		}
1299272214Skan		target->n_xfer++;
1300113584Ssimokawa		if (debug)
1301113584Ssimokawa			printf("sbp: alloc %d xfer\n", target->n_xfer);
1302113584Ssimokawa		new = 1;
1303113584Ssimokawa	} else {
1304113584Ssimokawa		STAILQ_REMOVE_HEAD(&target->xferlist, link);
1305103285Sikob	}
1306113584Ssimokawa
1307113584Ssimokawa	if (new) {
1308120660Ssimokawa		xfer->recv.pay_len = 0;
1309120660Ssimokawa		xfer->send.spd = min(sdev->target->fwdev->speed, max_speed);
1310113584Ssimokawa		xfer->fc = sdev->target->sbp->fd.fc;
1311103285Sikob	}
1312120660Ssimokawa
1313120660Ssimokawa	if (tcode == FWTCODE_WREQB)
1314120660Ssimokawa		xfer->send.pay_len = 8;
1315120660Ssimokawa	else
1316120660Ssimokawa		xfer->send.pay_len = 0;
1317120660Ssimokawa
1318103285Sikob	xfer->sc = (caddr_t)sdev;
1319120660Ssimokawa	fp = &xfer->send.hdr;
1320113584Ssimokawa	fp->mode.wreqq.dest_hi = sdev->login->cmd_hi;
1321113584Ssimokawa	fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset;
1322103285Sikob	fp->mode.wreqq.tlrt = 0;
1323103285Sikob	fp->mode.wreqq.tcode = tcode;
1324103285Sikob	fp->mode.wreqq.pri = 0;
1325120660Ssimokawa	fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst;
1326103285Sikob
1327103285Sikob	return xfer;
1328103285Sikob}
1329103285Sikob
1330103285Sikobstatic void
1331111615Ssimokawasbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb)
1332103285Sikob{
1333103285Sikob	struct fw_xfer *xfer;
1334103285Sikob	struct fw_pkt *fp;
1335103285Sikob	struct sbp_ocb *ocb;
1336111615Ssimokawa	struct sbp_target *target;
1337266772Sjhb	int nid;
1338103285Sikob
1339111615Ssimokawa	target = sdev->target;
1340111615Ssimokawa	nid = target->sbp->fd.fc->nodeid | FWLOCALBUS;
1341111615Ssimokawa
1342266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
1343111615Ssimokawa	if (func == ORB_FUN_RUNQUEUE) {
1344111615Ssimokawa		ocb = STAILQ_FIRST(&target->mgm_ocb_queue);
1345111615Ssimokawa		if (target->mgm_ocb_cur != NULL || ocb == NULL) {
1346111615Ssimokawa			return;
1347111615Ssimokawa		}
1348111615Ssimokawa		STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb);
1349111615Ssimokawa		goto start;
1350111615Ssimokawa	}
1351113584Ssimokawa	if ((ocb = sbp_get_ocb(sdev)) == NULL) {
1352122528Ssimokawa		/* XXX */
1353103285Sikob		return;
1354103285Sikob	}
1355103285Sikob	ocb->flags = OCB_ACT_MGM;
1356103285Sikob	ocb->sdev = sdev;
1357103285Sikob
1358120660Ssimokawa	bzero((void *)ocb->orb, sizeof(ocb->orb));
1359103285Sikob	ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI);
1360120660Ssimokawa	ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id));
1361103285Sikob
1362107653SsimokawaSBP_DEBUG(0)
1363188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1364188756Ssbruno		 "%s:%s %s\n",
1365188756Ssbruno		 __func__,sdev->bustgtlun,
1366272214Skan		 orb_fun_name[(func >> 16) & 0xf]);
1367107653SsimokawaEND_DEBUG
1368103285Sikob	switch (func) {
1369103285Sikob	case ORB_FUN_LGI:
1370120660Ssimokawa		ocb->orb[0] = ocb->orb[1] = 0; /* password */
1371103285Sikob		ocb->orb[2] = htonl(nid << 16);
1372113584Ssimokawa		ocb->orb[3] = htonl(sdev->dma.bus_addr);
1373121792Ssimokawa		ocb->orb[4] = htonl(ORB_NOTIFY | sdev->lun_id);
1374122387Ssimokawa		if (ex_login)
1375121792Ssimokawa			ocb->orb[4] |= htonl(ORB_EXV);
1376113584Ssimokawa		ocb->orb[5] = htonl(SBP_LOGIN_SIZE);
1377113584Ssimokawa		fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD);
1378103285Sikob		break;
1379110336Ssimokawa	case ORB_FUN_ATA:
1380111615Ssimokawa		ocb->orb[0] = htonl((0 << 16) | 0);
1381113584Ssimokawa		ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff);
1382110336Ssimokawa		/* fall through */
1383103285Sikob	case ORB_FUN_RCN:
1384103285Sikob	case ORB_FUN_LGO:
1385103285Sikob	case ORB_FUN_LUR:
1386103285Sikob	case ORB_FUN_RST:
1387103285Sikob	case ORB_FUN_ATS:
1388113584Ssimokawa		ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id);
1389103285Sikob		break;
1390103285Sikob	}
1391103285Sikob
1392111615Ssimokawa	if (target->mgm_ocb_cur != NULL) {
1393111615Ssimokawa		/* there is a standing ORB */
1394111615Ssimokawa		STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb);
1395111615Ssimokawa		return;
1396111615Ssimokawa	}
1397111615Ssimokawastart:
1398111615Ssimokawa	target->mgm_ocb_cur = ocb;
1399111615Ssimokawa
1400274819Ssmh	callout_reset(&target->mgm_ocb_timeout, 5 * hz,
1401114732Ssimokawa				sbp_mgm_timeout, (caddr_t)ocb);
1402103285Sikob	xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0);
1403272214Skan	if (xfer == NULL) {
1404103285Sikob		return;
1405103285Sikob	}
1406167632Ssimokawa	xfer->hand = sbp_mgm_callback;
1407103285Sikob
1408120660Ssimokawa	fp = &xfer->send.hdr;
1409113584Ssimokawa	fp->mode.wreqb.dest_hi = sdev->target->mgm_hi;
1410113584Ssimokawa	fp->mode.wreqb.dest_lo = sdev->target->mgm_lo;
1411113584Ssimokawa	fp->mode.wreqb.len = 8;
1412103285Sikob	fp->mode.wreqb.extcode = 0;
1413120660Ssimokawa	xfer->send.payload[0] = htonl(nid << 16);
1414120660Ssimokawa	xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff);
1415103285Sikob
1416103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
1417103285Sikob}
1418103285Sikob
1419103285Sikobstatic void
1420105792Ssimokawasbp_print_scsi_cmd(struct sbp_ocb *ocb)
1421103285Sikob{
1422103285Sikob	struct ccb_scsiio *csio;
1423103285Sikob
1424103285Sikob	csio = &ocb->ccb->csio;
1425257381Snwhitehorn	printf("%s:%d:%jx XPT_SCSI_IO: "
1426103285Sikob		"cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
1427103285Sikob		", flags: 0x%02x, "
1428103285Sikob		"%db cmd/%db data/%db sense\n",
1429103285Sikob		device_get_nameunit(ocb->sdev->target->sbp->fd.dev),
1430257381Snwhitehorn		ocb->ccb->ccb_h.target_id,
1431257381Snwhitehorn		(uintmax_t)ocb->ccb->ccb_h.target_lun,
1432103285Sikob		csio->cdb_io.cdb_bytes[0],
1433103285Sikob		csio->cdb_io.cdb_bytes[1],
1434103285Sikob		csio->cdb_io.cdb_bytes[2],
1435103285Sikob		csio->cdb_io.cdb_bytes[3],
1436103285Sikob		csio->cdb_io.cdb_bytes[4],
1437103285Sikob		csio->cdb_io.cdb_bytes[5],
1438103285Sikob		csio->cdb_io.cdb_bytes[6],
1439103285Sikob		csio->cdb_io.cdb_bytes[7],
1440103285Sikob		csio->cdb_io.cdb_bytes[8],
1441103285Sikob		csio->cdb_io.cdb_bytes[9],
1442103285Sikob		ocb->ccb->ccb_h.flags & CAM_DIR_MASK,
1443103285Sikob		csio->cdb_len, csio->dxfer_len,
1444103285Sikob		csio->sense_len);
1445105792Ssimokawa}
1446105792Ssimokawa
1447105792Ssimokawastatic void
1448105792Ssimokawasbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb)
1449105792Ssimokawa{
1450105792Ssimokawa	struct sbp_cmd_status *sbp_cmd_status;
1451225950Sken	struct scsi_sense_data_fixed *sense;
1452105792Ssimokawa
1453105792Ssimokawa	sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data;
1454225950Sken	sense = (struct scsi_sense_data_fixed *)&ocb->ccb->csio.sense_data;
1455105792Ssimokawa
1456105792SsimokawaSBP_DEBUG(0)
1457105792Ssimokawa	sbp_print_scsi_cmd(ocb);
1458103285Sikob	/* XXX need decode status */
1459188756Ssbruno	printf("%s: SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n",
1460188756Ssbruno		ocb->sdev->bustgtlun,
1461103285Sikob		sbp_cmd_status->status,
1462103285Sikob		sbp_cmd_status->sfmt,
1463103285Sikob		sbp_cmd_status->valid,
1464103285Sikob		sbp_cmd_status->s_key,
1465103285Sikob		sbp_cmd_status->s_code,
1466103285Sikob		sbp_cmd_status->s_qlfr,
1467188756Ssbruno		sbp_status->len);
1468103285SikobEND_DEBUG
1469103285Sikob
1470110071Ssimokawa	switch (sbp_cmd_status->status) {
1471110071Ssimokawa	case SCSI_STATUS_CHECK_COND:
1472110071Ssimokawa	case SCSI_STATUS_BUSY:
1473110071Ssimokawa	case SCSI_STATUS_CMD_TERMINATED:
1474272214Skan		if (sbp_cmd_status->sfmt == SBP_SFMT_CURR) {
1475103285Sikob			sense->error_code = SSD_CURRENT_ERROR;
1476272214Skan		} else {
1477103285Sikob			sense->error_code = SSD_DEFERRED_ERROR;
1478103285Sikob		}
1479272214Skan		if (sbp_cmd_status->valid)
1480103285Sikob			sense->error_code |= SSD_ERRCODE_VALID;
1481103285Sikob		sense->flags = sbp_cmd_status->s_key;
1482272214Skan		if (sbp_cmd_status->mark)
1483103285Sikob			sense->flags |= SSD_FILEMARK;
1484272214Skan		if (sbp_cmd_status->eom)
1485103285Sikob			sense->flags |= SSD_EOM;
1486272214Skan		if (sbp_cmd_status->ill_len)
1487103285Sikob			sense->flags |= SSD_ILI;
1488119556Ssimokawa
1489119556Ssimokawa		bcopy(&sbp_cmd_status->info, &sense->info[0], 4);
1490119556Ssimokawa
1491103285Sikob		if (sbp_status->len <= 1)
1492272214Skan			/* XXX not scsi status. shouldn't be happened */
1493103285Sikob			sense->extra_len = 0;
1494103285Sikob		else if (sbp_status->len <= 4)
1495103285Sikob			/* add_sense_code(_qual), info, cmd_spec_info */
1496103285Sikob			sense->extra_len = 6;
1497103285Sikob		else
1498103285Sikob			/* fru, sense_key_spec */
1499103285Sikob			sense->extra_len = 10;
1500119556Ssimokawa
1501119556Ssimokawa		bcopy(&sbp_cmd_status->cdb, &sense->cmd_spec_info[0], 4);
1502119556Ssimokawa
1503103285Sikob		sense->add_sense_code = sbp_cmd_status->s_code;
1504103285Sikob		sense->add_sense_code_qual = sbp_cmd_status->s_qlfr;
1505103285Sikob		sense->fru = sbp_cmd_status->fru;
1506103285Sikob
1507119556Ssimokawa		bcopy(&sbp_cmd_status->s_keydep[0],
1508119556Ssimokawa		    &sense->sense_key_spec[0], 3);
1509119556Ssimokawa
1510201758Smbr		ocb->ccb->csio.scsi_status = sbp_cmd_status->status;
1511103285Sikob		ocb->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
1512103285Sikob							| CAM_AUTOSNS_VALID;
1513103285Sikob/*
1514103285Sikob{
1515129585Sdfr		uint8_t j, *tmp;
1516103285Sikob		tmp = sense;
1517272214Skan		for (j = 0; j < 32; j += 8) {
1518272214Skan			printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n",
1519272214Skan				tmp[j], tmp[j + 1], tmp[j + 2], tmp[j + 3],
1520272214Skan				tmp[j + 4], tmp[j + 5], tmp[j + 6], tmp[j + 7]);
1521103285Sikob		}
1522103285Sikob
1523103285Sikob}
1524103285Sikob*/
1525110071Ssimokawa		break;
1526110071Ssimokawa	default:
1527188756Ssbruno		device_printf(ocb->sdev->target->sbp->fd.dev,
1528188756Ssbruno				"%s:%s unknown scsi status 0x%x\n",
1529188756Ssbruno				__func__, ocb->sdev->bustgtlun,
1530188756Ssbruno				sbp_cmd_status->status);
1531103285Sikob	}
1532103285Sikob}
1533103285Sikob
1534103285Sikobstatic void
1535103285Sikobsbp_fix_inq_data(struct sbp_ocb *ocb)
1536103285Sikob{
1537103285Sikob	union ccb *ccb;
1538103285Sikob	struct sbp_dev *sdev;
1539103285Sikob	struct scsi_inquiry_data *inq;
1540103285Sikob
1541103285Sikob	ccb = ocb->ccb;
1542103285Sikob	sdev = ocb->sdev;
1543103285Sikob
1544103285Sikob	if (ccb->csio.cdb_io.cdb_bytes[1] & SI_EVPD)
1545103285Sikob		return;
1546103285SikobSBP_DEBUG(1)
1547188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
1548188756Ssbruno		"%s:%s\n", __func__, sdev->bustgtlun);
1549103285SikobEND_DEBUG
1550103285Sikob	inq = (struct scsi_inquiry_data *) ccb->csio.data_ptr;
1551103285Sikob	switch (SID_TYPE(inq)) {
1552103285Sikob	case T_DIRECT:
1553118291Ssimokawa#if 0
1554272214Skan		/*
1555103285Sikob		 * XXX Convert Direct Access device to RBC.
1556108281Ssimokawa		 * I've never seen FireWire DA devices which support READ_6.
1557103285Sikob		 */
1558103285Sikob		if (SID_TYPE(inq) == T_DIRECT)
1559103285Sikob			inq->device |= T_RBC; /*  T_DIRECT == 0 */
1560103285Sikob#endif
1561103285Sikob		/* fall through */
1562103285Sikob	case T_RBC:
1563103285Sikob		/*
1564103285Sikob		 * Override vendor/product/revision information.
1565103285Sikob		 * Some devices sometimes return strange strings.
1566103285Sikob		 */
1567111615Ssimokawa#if 1
1568103285Sikob		bcopy(sdev->vendor, inq->vendor, sizeof(inq->vendor));
1569103285Sikob		bcopy(sdev->product, inq->product, sizeof(inq->product));
1570272214Skan		bcopy(sdev->revision + 2, inq->revision, sizeof(inq->revision));
1571111615Ssimokawa#endif
1572103285Sikob		break;
1573103285Sikob	}
1574127468Ssimokawa	/*
1575127468Ssimokawa	 * Force to enable/disable tagged queuing.
1576127468Ssimokawa	 * XXX CAM also checks SCP_QUEUE_DQUE flag in the control mode page.
1577127468Ssimokawa	 */
1578127468Ssimokawa	if (sbp_tags > 0)
1579127468Ssimokawa		inq->flags |= SID_CmdQue;
1580127468Ssimokawa	else if (sbp_tags < 0)
1581127468Ssimokawa		inq->flags &= ~SID_CmdQue;
1582127468Ssimokawa
1583103285Sikob}
1584103285Sikob
1585103285Sikobstatic void
1586113584Ssimokawasbp_recv1(struct fw_xfer *xfer)
1587113584Ssimokawa{
1588103285Sikob	struct fw_pkt *rfp;
1589103285Sikob#if NEED_RESPONSE
1590103285Sikob	struct fw_pkt *sfp;
1591103285Sikob#endif
1592103285Sikob	struct sbp_softc *sbp;
1593103285Sikob	struct sbp_dev *sdev;
1594103285Sikob	struct sbp_ocb *ocb;
1595103285Sikob	struct sbp_login_res *login_res = NULL;
1596103285Sikob	struct sbp_status *sbp_status;
1597103285Sikob	struct sbp_target *target;
1598111704Ssimokawa	int	orb_fun, status_valid0, status_valid, t, l, reset_agent = 0;
1599129585Sdfr	uint32_t addr;
1600103285Sikob/*
1601129585Sdfr	uint32_t *ld;
1602103285Sikob	ld = xfer->recv.buf;
1603103285Sikobprintf("sbp %x %d %d %08x %08x %08x %08x\n",
1604103285Sikob			xfer->resp, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3]));
1605103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
1606103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11]));
1607103285Sikob*/
1608113584Ssimokawa	sbp = (struct sbp_softc *)xfer->sc;
1609266772Sjhb	SBP_LOCK_ASSERT(sbp);
1610272214Skan	if (xfer->resp != 0) {
1611122529Ssimokawa		printf("sbp_recv: xfer->resp = %d\n", xfer->resp);
1612113584Ssimokawa		goto done0;
1613103285Sikob	}
1614272214Skan	if (xfer->recv.payload == NULL) {
1615120660Ssimokawa		printf("sbp_recv: xfer->recv.payload == NULL\n");
1616113584Ssimokawa		goto done0;
1617103285Sikob	}
1618120660Ssimokawa	rfp = &xfer->recv.hdr;
1619272214Skan	if (rfp->mode.wreqb.tcode != FWTCODE_WREQB) {
1620103285Sikob		printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode);
1621113584Ssimokawa		goto done0;
1622103285Sikob	}
1623120660Ssimokawa	sbp_status = (struct sbp_status *)xfer->recv.payload;
1624113584Ssimokawa	addr = rfp->mode.wreqb.dest_lo;
1625103285SikobSBP_DEBUG(2)
1626103285Sikob	printf("received address 0x%x\n", addr);
1627103285SikobEND_DEBUG
1628110189Ssimokawa	t = SBP_ADDR2TRG(addr);
1629110189Ssimokawa	if (t >= SBP_NUM_TARGETS) {
1630110189Ssimokawa		device_printf(sbp->fd.dev,
1631110189Ssimokawa			"sbp_recv1: invalid target %d\n", t);
1632113584Ssimokawa		goto done0;
1633110189Ssimokawa	}
1634110189Ssimokawa	target = &sbp->targets[t];
1635110189Ssimokawa	l = SBP_ADDR2LUN(addr);
1636121185Ssimokawa	if (l >= target->num_lun || target->luns[l] == NULL) {
1637110189Ssimokawa		device_printf(sbp->fd.dev,
1638110189Ssimokawa			"sbp_recv1: invalid lun %d (target=%d)\n", l, t);
1639113584Ssimokawa		goto done0;
1640110189Ssimokawa	}
1641121185Ssimokawa	sdev = target->luns[l];
1642103285Sikob
1643110189Ssimokawa	ocb = NULL;
1644110189Ssimokawa	switch (sbp_status->src) {
1645110189Ssimokawa	case 0:
1646110189Ssimokawa	case 1:
1647111615Ssimokawa		/* check mgm_ocb_cur first */
1648111615Ssimokawa		ocb  = target->mgm_ocb_cur;
1649111615Ssimokawa		if (ocb != NULL) {
1650111615Ssimokawa			if (OCB_MATCH(ocb, sbp_status)) {
1651111615Ssimokawa				callout_stop(&target->mgm_ocb_timeout);
1652111615Ssimokawa				target->mgm_ocb_cur = NULL;
1653111615Ssimokawa				break;
1654111615Ssimokawa			}
1655111615Ssimokawa		}
1656111615Ssimokawa		ocb = sbp_dequeue_ocb(sdev, sbp_status);
1657110189Ssimokawa		if (ocb == NULL) {
1658188756Ssbruno			device_printf(sdev->target->sbp->fd.dev,
1659188756Ssbruno				"%s:%s No ocb(%x) on the queue\n",
1660188756Ssbruno				__func__,sdev->bustgtlun,
1661188756Ssbruno				ntohl(sbp_status->orb_lo));
1662110189Ssimokawa		}
1663110189Ssimokawa		break;
1664110189Ssimokawa	case 2:
1665110189Ssimokawa		/* unsolicit */
1666188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1667188756Ssbruno			"%s:%s unsolicit status received\n",
1668188756Ssbruno			__func__, sdev->bustgtlun);
1669110189Ssimokawa		break;
1670110189Ssimokawa	default:
1671188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1672188756Ssbruno			"%s:%s unknown sbp_status->src\n",
1673188756Ssbruno			__func__, sdev->bustgtlun);
1674110189Ssimokawa	}
1675110189Ssimokawa
1676111615Ssimokawa	status_valid0 = (sbp_status->src < 2
1677110189Ssimokawa			&& sbp_status->resp == ORB_RES_CMPL
1678111615Ssimokawa			&& sbp_status->dead == 0);
1679111615Ssimokawa	status_valid = (status_valid0 && sbp_status->status == 0);
1680103285Sikob
1681272214Skan	if (!status_valid0 || debug > 2) {
1682103285Sikob		int status;
1683110129SsimokawaSBP_DEBUG(0)
1684188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1685188756Ssbruno			"%s:%s ORB status src:%x resp:%x dead:%x"
1686103285Sikob				" len:%x stat:%x orb:%x%08x\n",
1687188756Ssbruno			__func__, sdev->bustgtlun,
1688103285Sikob			sbp_status->src, sbp_status->resp, sbp_status->dead,
1689103285Sikob			sbp_status->len, sbp_status->status,
1690108280Ssimokawa			ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo));
1691110129SsimokawaEND_DEBUG
1692188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
1693188756Ssbruno				"%s\n", sdev->bustgtlun);
1694103285Sikob		status = sbp_status->status;
1695272214Skan		switch (sbp_status->resp) {
1696103285Sikob		case 0:
1697103285Sikob			if (status > MAX_ORB_STATUS0)
1698103285Sikob				printf("%s\n", orb_status0[MAX_ORB_STATUS0]);
1699110189Ssimokawa			else
1700110129Ssimokawa				printf("%s\n", orb_status0[status]);
1701103285Sikob			break;
1702103285Sikob		case 1:
1703110336Ssimokawa			printf("Obj: %s, Error: %s\n",
1704272214Skan				orb_status1_object[(status >> 6) & 3],
1705103285Sikob				orb_status1_serial_bus_error[status & 0xf]);
1706103285Sikob			break;
1707110129Ssimokawa		case 2:
1708110129Ssimokawa			printf("Illegal request\n");
1709110129Ssimokawa			break;
1710110129Ssimokawa		case 3:
1711110129Ssimokawa			printf("Vendor dependent\n");
1712110129Ssimokawa			break;
1713103285Sikob		default:
1714110129Ssimokawa			printf("unknown respose code %d\n", sbp_status->resp);
1715103285Sikob		}
1716103285Sikob	}
1717103285Sikob
1718103285Sikob	/* we have to reset the fetch agent if it's dead */
1719103285Sikob	if (sbp_status->dead) {
1720111615Ssimokawa		if (sdev->path) {
1721103285Sikob			xpt_freeze_devq(sdev->path, 1);
1722272214Skan			sdev->freeze++;
1723111615Ssimokawa		}
1724111704Ssimokawa		reset_agent = 1;
1725103285Sikob	}
1726103285Sikob
1727111704Ssimokawa	if (ocb == NULL)
1728111704Ssimokawa		goto done;
1729103285Sikob
1730272214Skan	switch (ntohl(ocb->orb[4]) & ORB_FMT_MSK) {
1731103285Sikob	case ORB_FMT_NOP:
1732103285Sikob		break;
1733103285Sikob	case ORB_FMT_VED:
1734103285Sikob		break;
1735103285Sikob	case ORB_FMT_STD:
1736272214Skan		switch (ocb->flags) {
1737103285Sikob		case OCB_ACT_MGM:
1738103285Sikob			orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK;
1739120842Ssimokawa			reset_agent = 0;
1740272214Skan			switch (orb_fun) {
1741103285Sikob			case ORB_FUN_LGI:
1742113584Ssimokawa				fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD);
1743113584Ssimokawa				login_res = sdev->login;
1744103285Sikob				login_res->len = ntohs(login_res->len);
1745103285Sikob				login_res->id = ntohs(login_res->id);
1746103285Sikob				login_res->cmd_hi = ntohs(login_res->cmd_hi);
1747103285Sikob				login_res->cmd_lo = ntohl(login_res->cmd_lo);
1748103285Sikob				if (status_valid) {
1749103285SikobSBP_DEBUG(0)
1750188756Ssbruno					device_printf(sdev->target->sbp->fd.dev,
1751188756Ssbruno						"%s:%s login: len %d, ID %d, cmd %08x%08x, recon_hold %d\n",
1752188756Ssbruno						__func__, sdev->bustgtlun,
1753188756Ssbruno						login_res->len, login_res->id,
1754188756Ssbruno						login_res->cmd_hi, login_res->cmd_lo,
1755188756Ssbruno						ntohs(login_res->recon_hold));
1756103285SikobEND_DEBUG
1757103285Sikob					sbp_busy_timeout(sdev);
1758103285Sikob				} else {
1759110336Ssimokawa					/* forgot logout? */
1760188756Ssbruno					device_printf(sdev->target->sbp->fd.dev,
1761188756Ssbruno						"%s:%s login failed\n",
1762188756Ssbruno						__func__, sdev->bustgtlun);
1763103285Sikob					sdev->status = SBP_DEV_RESET;
1764103285Sikob				}
1765103285Sikob				break;
1766103285Sikob			case ORB_FUN_RCN:
1767113584Ssimokawa				login_res = sdev->login;
1768103285Sikob				if (status_valid) {
1769103285SikobSBP_DEBUG(0)
1770188756Ssbruno					device_printf(sdev->target->sbp->fd.dev,
1771188756Ssbruno						"%s:%s reconnect: len %d, ID %d, cmd %08x%08x\n",
1772188756Ssbruno						__func__, sdev->bustgtlun,
1773188756Ssbruno						login_res->len, login_res->id,
1774188756Ssbruno						login_res->cmd_hi, login_res->cmd_lo);
1775103285SikobEND_DEBUG
1776111615Ssimokawa					if (sdev->status == SBP_DEV_ATTACHED)
1777111615Ssimokawa						sbp_scan_dev(sdev);
1778111615Ssimokawa					else
1779111615Ssimokawa						sbp_agent_reset(sdev);
1780103285Sikob				} else {
1781103285Sikob					/* reconnection hold time exceed? */
1782110336SsimokawaSBP_DEBUG(0)
1783188756Ssbruno					device_printf(sdev->target->sbp->fd.dev,
1784188756Ssbruno						"%s:%s reconnect failed\n",
1785188756Ssbruno						__func__, sdev->bustgtlun);
1786110336SsimokawaEND_DEBUG
1787111615Ssimokawa					sbp_login(sdev);
1788103285Sikob				}
1789103285Sikob				break;
1790103285Sikob			case ORB_FUN_LGO:
1791103285Sikob				sdev->status = SBP_DEV_RESET;
1792103285Sikob				break;
1793110336Ssimokawa			case ORB_FUN_RST:
1794110336Ssimokawa				sbp_busy_timeout(sdev);
1795110336Ssimokawa				break;
1796103285Sikob			case ORB_FUN_LUR:
1797103285Sikob			case ORB_FUN_ATA:
1798103285Sikob			case ORB_FUN_ATS:
1799110336Ssimokawa				sbp_agent_reset(sdev);
1800103285Sikob				break;
1801103285Sikob			default:
1802188756Ssbruno				device_printf(sdev->target->sbp->fd.dev,
1803188756Ssbruno					"%s:%s unknown function %d\n",
1804188756Ssbruno					__func__, sdev->bustgtlun, orb_fun);
1805103285Sikob				break;
1806103285Sikob			}
1807111615Ssimokawa			sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL);
1808103285Sikob			break;
1809103285Sikob		case OCB_ACT_CMD:
1810114732Ssimokawa			sdev->timeout = 0;
1811272214Skan			if (ocb->ccb != NULL) {
1812103285Sikob				union ccb *ccb;
1813188756Ssbruno
1814103285Sikob				ccb = ocb->ccb;
1815272214Skan				if (sbp_status->len > 1) {
1816103285Sikob					sbp_scsi_status(sbp_status, ocb);
1817272214Skan				} else {
1818272214Skan					if (sbp_status->resp != ORB_RES_CMPL) {
1819103285Sikob						ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1820272214Skan					} else {
1821103285Sikob						ccb->ccb_h.status = CAM_REQ_CMP;
1822103285Sikob					}
1823103285Sikob				}
1824103285Sikob				/* fix up inq data */
1825103285Sikob				if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY)
1826103285Sikob					sbp_fix_inq_data(ocb);
1827103285Sikob				xpt_done(ccb);
1828103285Sikob			}
1829103285Sikob			break;
1830103285Sikob		default:
1831103285Sikob			break;
1832103285Sikob		}
1833103285Sikob	}
1834103285Sikob
1835127468Ssimokawa	if (!use_doorbell)
1836127468Ssimokawa		sbp_free_ocb(sdev, ocb);
1837111704Ssimokawadone:
1838111704Ssimokawa	if (reset_agent)
1839111704Ssimokawa		sbp_agent_reset(sdev);
1840103285Sikob
1841113584Ssimokawadone0:
1842120660Ssimokawa	xfer->recv.pay_len = SBP_RECV_LEN;
1843103285Sikob/* The received packet is usually small enough to be stored within
1844103285Sikob * the buffer. In that case, the controller return ack_complete and
1845103285Sikob * no respose is necessary.
1846103285Sikob *
1847272214Skan * XXX fwohci.c and firewire.c should inform event_code such as
1848103285Sikob * ack_complete or ack_pending to upper driver.
1849103285Sikob */
1850103285Sikob#if NEED_RESPONSE
1851103285Sikob	xfer->send.off = 0;
1852103285Sikob	sfp = (struct fw_pkt *)xfer->send.buf;
1853103285Sikob	sfp->mode.wres.dst = rfp->mode.wreqb.src;
1854113584Ssimokawa	xfer->dst = sfp->mode.wres.dst;
1855103285Sikob	xfer->spd = min(sdev->target->fwdev->speed, max_speed);
1856167632Ssimokawa	xfer->hand = sbp_loginres_callback;
1857103285Sikob
1858103285Sikob	sfp->mode.wres.tlrt = rfp->mode.wreqb.tlrt;
1859103285Sikob	sfp->mode.wres.tcode = FWTCODE_WRES;
1860103285Sikob	sfp->mode.wres.rtcode = 0;
1861103285Sikob	sfp->mode.wres.pri = 0;
1862103285Sikob
1863103285Sikob	fw_asyreq(xfer->fc, -1, xfer);
1864103285Sikob#else
1865113584Ssimokawa	/* recycle */
1866113584Ssimokawa	STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
1867103285Sikob#endif
1868103285Sikob}
1869103285Sikob
1870103285Sikobstatic void
1871103285Sikobsbp_recv(struct fw_xfer *xfer)
1872103285Sikob{
1873266772Sjhb	struct sbp_softc *sbp;
1874103285Sikob
1875266772Sjhb	sbp = (struct sbp_softc *)xfer->sc;
1876266772Sjhb	SBP_LOCK(sbp);
1877103285Sikob	sbp_recv1(xfer);
1878266772Sjhb	SBP_UNLOCK(sbp);
1879103285Sikob}
1880103285Sikob/*
1881103285Sikob * sbp_attach()
1882103285Sikob */
1883103285Sikobstatic int
1884103285Sikobsbp_attach(device_t dev)
1885103285Sikob{
1886103285Sikob	struct sbp_softc *sbp;
1887103285Sikob	struct cam_devq *devq;
1888170374Ssimokawa	struct firewire_comm *fc;
1889266772Sjhb	int i, error;
1890103285Sikob
1891167624Ssimokawa	if (DFLTPHYS > SBP_MAXPHYS)
1892167624Ssimokawa		device_printf(dev, "Warning, DFLTPHYS(%dKB) is larger than "
1893167624Ssimokawa			"SBP_MAXPHYS(%dKB).\n", DFLTPHYS / 1024,
1894167624Ssimokawa			SBP_MAXPHYS / 1024);
1895167624Ssimokawa
1896170400Ssimokawa	if (!firewire_phydma_enable)
1897170400Ssimokawa		device_printf(dev, "Warning, hw.firewire.phydma_enable must be 1 "
1898170400Ssimokawa			"for SBP over FireWire.\n");
1899103285SikobSBP_DEBUG(0)
1900111199Ssimokawa	printf("sbp_attach (cold=%d)\n", cold);
1901103285SikobEND_DEBUG
1902103285Sikob
1903111199Ssimokawa	if (cold)
1904272214Skan		sbp_cold++;
1905266772Sjhb	sbp = device_get_softc(dev);
1906103285Sikob	sbp->fd.dev = dev;
1907170374Ssimokawa	sbp->fd.fc = fc = device_get_ivars(dev);
1908170374Ssimokawa	mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF);
1909124251Ssimokawa
1910124251Ssimokawa	if (max_speed < 0)
1911170374Ssimokawa		max_speed = fc->speed;
1912124251Ssimokawa
1913170374Ssimokawa	error = bus_dma_tag_create(/*parent*/fc->dmat,
1914113584Ssimokawa				/* XXX shoud be 4 for sane backend? */
1915113584Ssimokawa				/*alignment*/1,
1916103285Sikob				/*boundary*/0,
1917103285Sikob				/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
1918103285Sikob				/*highaddr*/BUS_SPACE_MAXADDR,
1919103285Sikob				/*filter*/NULL, /*filterarg*/NULL,
1920103285Sikob				/*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX,
1921113474Ssimokawa				/*maxsegsz*/SBP_SEG_MAX,
1922103285Sikob				/*flags*/BUS_DMA_ALLOCNOW,
1923117126Sscottl				/*lockfunc*/busdma_lock_mutex,
1924170374Ssimokawa				/*lockarg*/&sbp->mtx,
1925117228Ssimokawa				&sbp->dmat);
1926103285Sikob	if (error != 0) {
1927103285Sikob		printf("sbp_attach: Could not allocate DMA tag "
1928103285Sikob			"- error %d\n", error);
1929103285Sikob			return (ENOMEM);
1930103285Sikob	}
1931103285Sikob
1932103285Sikob	devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB);
1933103285Sikob	if (devq == NULL)
1934103285Sikob		return (ENXIO);
1935103285Sikob
1936272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++) {
1937103285Sikob		sbp->targets[i].fwdev = NULL;
1938103285Sikob		sbp->targets[i].luns = NULL;
1939267660Skan		sbp->targets[i].sbp = sbp;
1940103285Sikob	}
1941103285Sikob
1942103285Sikob	sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp,
1943103285Sikob				 device_get_unit(dev),
1944170374Ssimokawa				 &sbp->mtx,
1945111615Ssimokawa				 /*untagged*/ 1,
1946122528Ssimokawa				 /*tagged*/ SBP_QUEUE_LEN - 1,
1947111615Ssimokawa				 devq);
1948103285Sikob
1949103285Sikob	if (sbp->sim == NULL) {
1950103285Sikob		cam_simq_free(devq);
1951103285Sikob		return (ENXIO);
1952103285Sikob	}
1953103285Sikob
1954170374Ssimokawa	SBP_LOCK(sbp);
1955170872Sscottl	if (xpt_bus_register(sbp->sim, dev, /*bus*/0) != CAM_SUCCESS)
1956111615Ssimokawa		goto fail;
1957103285Sikob
1958249468Smav	if (xpt_create_path(&sbp->path, NULL, cam_sim_path(sbp->sim),
1959120660Ssimokawa	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1960120660Ssimokawa		xpt_bus_deregister(cam_sim_path(sbp->sim));
1961111615Ssimokawa		goto fail;
1962120660Ssimokawa	}
1963170374Ssimokawa	SBP_UNLOCK(sbp);
1964111615Ssimokawa
1965103285Sikob	/* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */
1966120660Ssimokawa	sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0);
1967120660Ssimokawa	sbp->fwb.end = sbp->fwb.start + 0xffff;
1968113584Ssimokawa	/* pre-allocate xfer */
1969113584Ssimokawa	STAILQ_INIT(&sbp->fwb.xferlist);
1970169130Ssimokawa	fw_xferlist_add(&sbp->fwb.xferlist, M_SBP,
1971169130Ssimokawa	    /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB/2,
1972170374Ssimokawa	    fc, (void *)sbp, sbp_recv);
1973103285Sikob
1974170374Ssimokawa	fw_bindadd(fc, &sbp->fwb);
1975170374Ssimokawa
1976113584Ssimokawa	sbp->fd.post_busreset = sbp_post_busreset;
1977103285Sikob	sbp->fd.post_explore = sbp_post_explore;
1978103285Sikob
1979170374Ssimokawa	if (fc->status != -1) {
1980122387Ssimokawa		sbp_post_busreset((void *)sbp);
1981111199Ssimokawa		sbp_post_explore((void *)sbp);
1982111199Ssimokawa	}
1983170374Ssimokawa	SBP_LOCK(sbp);
1984122387Ssimokawa	xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL);
1985170374Ssimokawa	SBP_UNLOCK(sbp);
1986111199Ssimokawa
1987103285Sikob	return (0);
1988111615Ssimokawafail:
1989170374Ssimokawa	SBP_UNLOCK(sbp);
1990111615Ssimokawa	cam_sim_free(sbp->sim, /*free_devq*/TRUE);
1991111615Ssimokawa	return (ENXIO);
1992103285Sikob}
1993103285Sikob
1994103285Sikobstatic int
1995110145Ssimokawasbp_logout_all(struct sbp_softc *sbp)
1996110145Ssimokawa{
1997110145Ssimokawa	struct sbp_target *target;
1998110145Ssimokawa	struct sbp_dev *sdev;
1999110145Ssimokawa	int i, j;
2000110145Ssimokawa
2001110145SsimokawaSBP_DEBUG(0)
2002110145Ssimokawa	printf("sbp_logout_all\n");
2003110145SsimokawaEND_DEBUG
2004266772Sjhb	SBP_LOCK_ASSERT(sbp);
2005272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++) {
2006110145Ssimokawa		target = &sbp->targets[i];
2007110145Ssimokawa		if (target->luns == NULL)
2008110145Ssimokawa			continue;
2009110145Ssimokawa		for (j = 0; j < target->num_lun; j++) {
2010121185Ssimokawa			sdev = target->luns[j];
2011121185Ssimokawa			if (sdev == NULL)
2012121185Ssimokawa				continue;
2013113584Ssimokawa			callout_stop(&sdev->login_callout);
2014110336Ssimokawa			if (sdev->status >= SBP_DEV_TOATTACH &&
2015110336Ssimokawa					sdev->status <= SBP_DEV_ATTACHED)
2016111615Ssimokawa				sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL);
2017110145Ssimokawa		}
2018110145Ssimokawa	}
2019113584Ssimokawa
2020110145Ssimokawa	return 0;
2021110145Ssimokawa}
2022110145Ssimokawa
2023110145Ssimokawastatic int
2024110145Ssimokawasbp_shutdown(device_t dev)
2025110145Ssimokawa{
2026110145Ssimokawa	struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev));
2027110145Ssimokawa
2028266772Sjhb	SBP_LOCK(sbp);
2029110145Ssimokawa	sbp_logout_all(sbp);
2030266772Sjhb	SBP_UNLOCK(sbp);
2031110145Ssimokawa	return (0);
2032110145Ssimokawa}
2033110145Ssimokawa
2034121185Ssimokawastatic void
2035121185Ssimokawasbp_free_sdev(struct sbp_dev *sdev)
2036121185Ssimokawa{
2037266772Sjhb	struct sbp_softc *sbp;
2038121185Ssimokawa	int i;
2039121185Ssimokawa
2040121185Ssimokawa	if (sdev == NULL)
2041121185Ssimokawa		return;
2042266772Sjhb	sbp = sdev->target->sbp;
2043266772Sjhb	SBP_UNLOCK(sbp);
2044266772Sjhb	callout_drain(&sdev->login_callout);
2045266772Sjhb	for (i = 0; i < SBP_QUEUE_LEN; i++) {
2046266772Sjhb		callout_drain(&sdev->ocb[i].timer);
2047266772Sjhb		bus_dmamap_destroy(sbp->dmat, sdev->ocb[i].dmamap);
2048266772Sjhb	}
2049266772Sjhb	fwdma_free(sbp->fd.fc, &sdev->dma);
2050121185Ssimokawa	free(sdev, M_SBP);
2051266772Sjhb	SBP_LOCK(sbp);
2052121185Ssimokawa}
2053121185Ssimokawa
2054121185Ssimokawastatic void
2055121185Ssimokawasbp_free_target(struct sbp_target *target)
2056121185Ssimokawa{
2057121185Ssimokawa	struct sbp_softc *sbp;
2058121185Ssimokawa	struct fw_xfer *xfer, *next;
2059121185Ssimokawa	int i;
2060121185Ssimokawa
2061121185Ssimokawa	if (target->luns == NULL)
2062121185Ssimokawa		return;
2063121185Ssimokawa	sbp = target->sbp;
2064266772Sjhb	SBP_LOCK_ASSERT(sbp);
2065266772Sjhb	SBP_UNLOCK(sbp);
2066266772Sjhb	callout_drain(&target->mgm_ocb_timeout);
2067266772Sjhb	callout_drain(&target->scan_callout);
2068266772Sjhb	SBP_LOCK(sbp);
2069121185Ssimokawa	for (i = 0; i < target->num_lun; i++)
2070121185Ssimokawa		sbp_free_sdev(target->luns[i]);
2071121185Ssimokawa
2072266772Sjhb	STAILQ_FOREACH_SAFE(xfer, &target->xferlist, link, next) {
2073121185Ssimokawa		fw_xfer_free_buf(xfer);
2074121185Ssimokawa	}
2075121185Ssimokawa	STAILQ_INIT(&target->xferlist);
2076121185Ssimokawa	free(target->luns, M_SBP);
2077201758Smbr	target->num_lun = 0;
2078121185Ssimokawa	target->luns = NULL;
2079121185Ssimokawa	target->fwdev = NULL;
2080121185Ssimokawa}
2081121185Ssimokawa
2082110145Ssimokawastatic int
2083103285Sikobsbp_detach(device_t dev)
2084103285Sikob{
2085103285Sikob	struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev));
2086103285Sikob	struct firewire_comm *fc = sbp->fd.fc;
2087121185Ssimokawa	int i;
2088103285Sikob
2089103285SikobSBP_DEBUG(0)
2090103285Sikob	printf("sbp_detach\n");
2091103285SikobEND_DEBUG
2092113584Ssimokawa
2093266772Sjhb	SBP_LOCK(sbp);
2094272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++)
2095110145Ssimokawa		sbp_cam_detach_target(&sbp->targets[i]);
2096170374Ssimokawa
2097120660Ssimokawa	xpt_async(AC_LOST_DEVICE, sbp->path, NULL);
2098111615Ssimokawa	xpt_free_path(sbp->path);
2099103285Sikob	xpt_bus_deregister(cam_sim_path(sbp->sim));
2100170378Sgallatin	cam_sim_free(sbp->sim, /*free_devq*/ TRUE);
2101110145Ssimokawa
2102110145Ssimokawa	sbp_logout_all(sbp);
2103266772Sjhb	SBP_UNLOCK(sbp);
2104113584Ssimokawa
2105110145Ssimokawa	/* XXX wait for logout completion */
2106167086Sjhb	pause("sbpdtc", hz/2);
2107110145Ssimokawa
2108266772Sjhb	SBP_LOCK(sbp);
2109272214Skan	for (i = 0; i < SBP_NUM_TARGETS; i++)
2110121185Ssimokawa		sbp_free_target(&sbp->targets[i]);
2111266772Sjhb	SBP_UNLOCK(sbp);
2112113584Ssimokawa
2113110145Ssimokawa	fw_bindremove(fc, &sbp->fwb);
2114169130Ssimokawa	fw_xferlist_remove(&sbp->fwb.xferlist);
2115113584Ssimokawa
2116103285Sikob	bus_dma_tag_destroy(sbp->dmat);
2117170374Ssimokawa	mtx_destroy(&sbp->mtx);
2118110145Ssimokawa
2119103285Sikob	return (0);
2120103285Sikob}
2121103285Sikob
2122103285Sikobstatic void
2123121185Ssimokawasbp_cam_detach_sdev(struct sbp_dev *sdev)
2124121185Ssimokawa{
2125121185Ssimokawa	if (sdev == NULL)
2126121185Ssimokawa		return;
2127121185Ssimokawa	if (sdev->status == SBP_DEV_DEAD)
2128121185Ssimokawa		return;
2129121185Ssimokawa	if (sdev->status == SBP_DEV_RESET)
2130121185Ssimokawa		return;
2131266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2132170374Ssimokawa	sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE);
2133121185Ssimokawa	if (sdev->path) {
2134121185Ssimokawa		xpt_release_devq(sdev->path,
2135121185Ssimokawa				 sdev->freeze, TRUE);
2136121185Ssimokawa		sdev->freeze = 0;
2137121185Ssimokawa		xpt_async(AC_LOST_DEVICE, sdev->path, NULL);
2138121185Ssimokawa		xpt_free_path(sdev->path);
2139121185Ssimokawa		sdev->path = NULL;
2140121185Ssimokawa	}
2141121185Ssimokawa}
2142121185Ssimokawa
2143121185Ssimokawastatic void
2144110145Ssimokawasbp_cam_detach_target(struct sbp_target *target)
2145103285Sikob{
2146103285Sikob	int i;
2147103285Sikob
2148266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
2149103285Sikob	if (target->luns != NULL) {
2150108529SsimokawaSBP_DEBUG(0)
2151103285Sikob		printf("sbp_detach_target %d\n", target->target_id);
2152108529SsimokawaEND_DEBUG
2153111615Ssimokawa		callout_stop(&target->scan_callout);
2154121185Ssimokawa		for (i = 0; i < target->num_lun; i++)
2155121185Ssimokawa			sbp_cam_detach_sdev(target->luns[i]);
2156103285Sikob	}
2157103285Sikob}
2158103285Sikob
2159103285Sikobstatic void
2160114732Ssimokawasbp_target_reset(struct sbp_dev *sdev, int method)
2161114732Ssimokawa{
2162114732Ssimokawa	int i;
2163114732Ssimokawa	struct sbp_target *target = sdev->target;
2164114732Ssimokawa	struct sbp_dev *tsdev;
2165114732Ssimokawa
2166266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
2167114732Ssimokawa	for (i = 0; i < target->num_lun; i++) {
2168121185Ssimokawa		tsdev = target->luns[i];
2169121185Ssimokawa		if (tsdev == NULL)
2170121185Ssimokawa			continue;
2171114732Ssimokawa		if (tsdev->status == SBP_DEV_DEAD)
2172114732Ssimokawa			continue;
2173114732Ssimokawa		if (tsdev->status == SBP_DEV_RESET)
2174114732Ssimokawa			continue;
2175114732Ssimokawa		xpt_freeze_devq(tsdev->path, 1);
2176272214Skan		tsdev->freeze++;
2177114732Ssimokawa		sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT);
2178114732Ssimokawa		if (method == 2)
2179114732Ssimokawa			tsdev->status = SBP_DEV_LOGIN;
2180114732Ssimokawa	}
2181272214Skan	switch (method) {
2182114732Ssimokawa	case 1:
2183114732Ssimokawa		printf("target reset\n");
2184114732Ssimokawa		sbp_mgm_orb(sdev, ORB_FUN_RST, NULL);
2185114732Ssimokawa		break;
2186114732Ssimokawa	case 2:
2187114732Ssimokawa		printf("reset start\n");
2188114732Ssimokawa		sbp_reset_start(sdev);
2189114732Ssimokawa		break;
2190114732Ssimokawa	}
2191272214Skan
2192114732Ssimokawa}
2193114732Ssimokawa
2194114732Ssimokawastatic void
2195114732Ssimokawasbp_mgm_timeout(void *arg)
2196114732Ssimokawa{
2197114732Ssimokawa	struct sbp_ocb *ocb = (struct sbp_ocb *)arg;
2198114732Ssimokawa	struct sbp_dev *sdev = ocb->sdev;
2199114732Ssimokawa	struct sbp_target *target = sdev->target;
2200114732Ssimokawa
2201266772Sjhb	SBP_LOCK_ASSERT(target->sbp);
2202188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2203188756Ssbruno		"%s:%s request timeout(mgm orb:0x%08x)\n",
2204188756Ssbruno		__func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr);
2205114732Ssimokawa	target->mgm_ocb_cur = NULL;
2206114732Ssimokawa	sbp_free_ocb(sdev, ocb);
2207114732Ssimokawa#if 0
2208114732Ssimokawa	/* XXX */
2209121185Ssimokawa	printf("run next request\n");
2210114732Ssimokawa	sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL);
2211114732Ssimokawa#endif
2212188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2213188756Ssbruno		"%s:%s reset start\n",
2214188756Ssbruno		__func__, sdev->bustgtlun);
2215114732Ssimokawa	sbp_reset_start(sdev);
2216114732Ssimokawa}
2217114732Ssimokawa
2218114732Ssimokawastatic void
2219103285Sikobsbp_timeout(void *arg)
2220103285Sikob{
2221103285Sikob	struct sbp_ocb *ocb = (struct sbp_ocb *)arg;
2222103285Sikob	struct sbp_dev *sdev = ocb->sdev;
2223103285Sikob
2224188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2225188756Ssbruno		"%s:%s request timeout(cmd orb:0x%08x) ... ",
2226188756Ssbruno		__func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr);
2227103285Sikob
2228266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2229272214Skan	sdev->timeout++;
2230272214Skan	switch (sdev->timeout) {
2231114732Ssimokawa	case 1:
2232110336Ssimokawa		printf("agent reset\n");
2233114732Ssimokawa		xpt_freeze_devq(sdev->path, 1);
2234272214Skan		sdev->freeze++;
2235114732Ssimokawa		sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT);
2236110336Ssimokawa		sbp_agent_reset(sdev);
2237114732Ssimokawa		break;
2238114732Ssimokawa	case 2:
2239114732Ssimokawa	case 3:
2240114732Ssimokawa		sbp_target_reset(sdev, sdev->timeout - 1);
2241114732Ssimokawa		break;
2242114732Ssimokawa#if 0
2243114732Ssimokawa	default:
2244114732Ssimokawa		/* XXX give up */
2245114732Ssimokawa		sbp_cam_detach_target(target);
2246114732Ssimokawa		if (target->luns != NULL)
2247114732Ssimokawa			free(target->luns, M_SBP);
2248201758Smbr		target->num_lun = 0;
2249114732Ssimokawa		target->luns = NULL;
2250114732Ssimokawa		target->fwdev = NULL;
2251114732Ssimokawa#endif
2252110336Ssimokawa	}
2253103285Sikob}
2254103285Sikob
2255103285Sikobstatic void
2256266772Sjhbsbp_action(struct cam_sim *sim, union ccb *ccb)
2257103285Sikob{
2258103285Sikob
2259103285Sikob	struct sbp_softc *sbp = (struct sbp_softc *)sim->softc;
2260103285Sikob	struct sbp_target *target = NULL;
2261103285Sikob	struct sbp_dev *sdev = NULL;
2262103285Sikob
2263266772Sjhb	if (sbp != NULL)
2264266772Sjhb		SBP_LOCK_ASSERT(sbp);
2265103285Sikob	/* target:lun -> sdev mapping */
2266103285Sikob	if (sbp != NULL
2267103285Sikob			&& ccb->ccb_h.target_id != CAM_TARGET_WILDCARD
2268103285Sikob			&& ccb->ccb_h.target_id < SBP_NUM_TARGETS) {
2269103285Sikob		target = &sbp->targets[ccb->ccb_h.target_id];
2270103285Sikob		if (target->fwdev != NULL
2271103285Sikob				&& ccb->ccb_h.target_lun != CAM_LUN_WILDCARD
2272103285Sikob				&& ccb->ccb_h.target_lun < target->num_lun) {
2273121185Ssimokawa			sdev = target->luns[ccb->ccb_h.target_lun];
2274121185Ssimokawa			if (sdev != NULL && sdev->status != SBP_DEV_ATTACHED &&
2275103285Sikob				sdev->status != SBP_DEV_PROBE)
2276103285Sikob				sdev = NULL;
2277103285Sikob		}
2278103285Sikob	}
2279103285Sikob
2280103285SikobSBP_DEBUG(1)
2281103285Sikob	if (sdev == NULL)
2282257381Snwhitehorn		printf("invalid target %d lun %jx\n",
2283257381Snwhitehorn			ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun);
2284103285SikobEND_DEBUG
2285103285Sikob
2286103285Sikob	switch (ccb->ccb_h.func_code) {
2287103285Sikob	case XPT_SCSI_IO:
2288103285Sikob	case XPT_RESET_DEV:
2289103285Sikob	case XPT_GET_TRAN_SETTINGS:
2290103285Sikob	case XPT_SET_TRAN_SETTINGS:
2291103285Sikob	case XPT_CALC_GEOMETRY:
2292103285Sikob		if (sdev == NULL) {
2293103285SikobSBP_DEBUG(1)
2294257381Snwhitehorn			printf("%s:%d:%jx:func_code 0x%04x: "
2295103285Sikob				"Invalid target (target needed)\n",
2296103285Sikob				device_get_nameunit(sbp->fd.dev),
2297257381Snwhitehorn				ccb->ccb_h.target_id,
2298257381Snwhitehorn				(uintmax_t)ccb->ccb_h.target_lun,
2299103285Sikob				ccb->ccb_h.func_code);
2300103285SikobEND_DEBUG
2301103285Sikob
2302108276Ssimokawa			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2303103285Sikob			xpt_done(ccb);
2304103285Sikob			return;
2305103285Sikob		}
2306103285Sikob		break;
2307103285Sikob	case XPT_PATH_INQ:
2308103285Sikob	case XPT_NOOP:
2309103285Sikob		/* The opcodes sometimes aimed at a target (sc is valid),
2310103285Sikob		 * sometimes aimed at the SIM (sc is invalid and target is
2311103285Sikob		 * CAM_TARGET_WILDCARD)
2312103285Sikob		 */
2313272214Skan		if (sbp == NULL &&
2314103285Sikob			ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
2315103285SikobSBP_DEBUG(0)
2316257381Snwhitehorn			printf("%s:%d:%jx func_code 0x%04x: "
2317103285Sikob				"Invalid target (no wildcard)\n",
2318103285Sikob				device_get_nameunit(sbp->fd.dev),
2319257381Snwhitehorn				ccb->ccb_h.target_id,
2320257381Snwhitehorn				(uintmax_t)ccb->ccb_h.target_lun,
2321103285Sikob				ccb->ccb_h.func_code);
2322103285SikobEND_DEBUG
2323108276Ssimokawa			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2324103285Sikob			xpt_done(ccb);
2325103285Sikob			return;
2326103285Sikob		}
2327103285Sikob		break;
2328103285Sikob	default:
2329103285Sikob		/* XXX Hm, we should check the input parameters */
2330103285Sikob		break;
2331103285Sikob	}
2332103285Sikob
2333103285Sikob	switch (ccb->ccb_h.func_code) {
2334103285Sikob	case XPT_SCSI_IO:
2335103285Sikob	{
2336103285Sikob		struct ccb_scsiio *csio;
2337103285Sikob		struct sbp_ocb *ocb;
2338113584Ssimokawa		int speed;
2339106506Ssimokawa		void *cdb;
2340103285Sikob
2341103285Sikob		csio = &ccb->csio;
2342170374Ssimokawa		mtx_assert(sim->mtx, MA_OWNED);
2343103285Sikob
2344121185SsimokawaSBP_DEBUG(2)
2345257381Snwhitehorn		printf("%s:%d:%jx XPT_SCSI_IO: "
2346103285Sikob			"cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
2347103285Sikob			", flags: 0x%02x, "
2348103285Sikob			"%db cmd/%db data/%db sense\n",
2349103285Sikob			device_get_nameunit(sbp->fd.dev),
2350257381Snwhitehorn			ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun,
2351103285Sikob			csio->cdb_io.cdb_bytes[0],
2352103285Sikob			csio->cdb_io.cdb_bytes[1],
2353103285Sikob			csio->cdb_io.cdb_bytes[2],
2354103285Sikob			csio->cdb_io.cdb_bytes[3],
2355103285Sikob			csio->cdb_io.cdb_bytes[4],
2356103285Sikob			csio->cdb_io.cdb_bytes[5],
2357103285Sikob			csio->cdb_io.cdb_bytes[6],
2358103285Sikob			csio->cdb_io.cdb_bytes[7],
2359103285Sikob			csio->cdb_io.cdb_bytes[8],
2360103285Sikob			csio->cdb_io.cdb_bytes[9],
2361103285Sikob			ccb->ccb_h.flags & CAM_DIR_MASK,
2362103285Sikob			csio->cdb_len, csio->dxfer_len,
2363103285Sikob			csio->sense_len);
2364103285SikobEND_DEBUG
2365272214Skan		if (sdev == NULL) {
2366103285Sikob			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2367103285Sikob			xpt_done(ccb);
2368103285Sikob			return;
2369103285Sikob		}
2370103285Sikob#if 0
2371103285Sikob		/* if we are in probe stage, pass only probe commands */
2372103285Sikob		if (sdev->status == SBP_DEV_PROBE) {
2373103285Sikob			char *name;
2374103285Sikob			name = xpt_path_periph(ccb->ccb_h.path)->periph_name;
2375103285Sikob			printf("probe stage, periph name: %s\n", name);
2376103285Sikob			if (strcmp(name, "probe") != 0) {
2377103285Sikob				ccb->ccb_h.status = CAM_REQUEUE_REQ;
2378103285Sikob				xpt_done(ccb);
2379103285Sikob				return;
2380103285Sikob			}
2381103285Sikob		}
2382103285Sikob#endif
2383122528Ssimokawa		if ((ocb = sbp_get_ocb(sdev)) == NULL) {
2384170807Ssimokawa			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2385127468Ssimokawa			if (sdev->freeze == 0) {
2386127468Ssimokawa				xpt_freeze_devq(sdev->path, 1);
2387272214Skan				sdev->freeze++;
2388127468Ssimokawa			}
2389122528Ssimokawa			xpt_done(ccb);
2390103285Sikob			return;
2391122528Ssimokawa		}
2392113584Ssimokawa
2393103285Sikob		ocb->flags = OCB_ACT_CMD;
2394103285Sikob		ocb->sdev = sdev;
2395103285Sikob		ocb->ccb = ccb;
2396103285Sikob		ccb->ccb_h.ccb_sdev_ptr = sdev;
2397258780Seadler		ocb->orb[0] = htonl(1U << 31);
2398103285Sikob		ocb->orb[1] = 0;
2399272214Skan		ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS) << 16));
2400113584Ssimokawa		ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET);
2401103285Sikob		speed = min(target->fwdev->speed, max_speed);
2402103285Sikob		ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed)
2403103285Sikob						| ORB_CMD_MAXP(speed + 7));
2404272214Skan		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2405103285Sikob			ocb->orb[4] |= htonl(ORB_CMD_IN);
2406103285Sikob		}
2407103285Sikob
2408106506Ssimokawa		if (csio->ccb_h.flags & CAM_CDB_POINTER)
2409106506Ssimokawa			cdb = (void *)csio->cdb_io.cdb_ptr;
2410106506Ssimokawa		else
2411106506Ssimokawa			cdb = (void *)&csio->cdb_io.cdb_bytes;
2412120660Ssimokawa		bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len);
2413103285Sikob/*
2414103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3]));
2415103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7]));
2416103285Sikob*/
2417103285Sikob		if (ccb->csio.dxfer_len > 0) {
2418247109Simp			int error;
2419103285Sikob
2420246713Skib			error = bus_dmamap_load_ccb(/*dma tag*/sbp->dmat,
2421103285Sikob					/*dma map*/ocb->dmamap,
2422246713Skib					ccb,
2423103285Sikob					sbp_execute_ocb,
2424103285Sikob					ocb,
2425103285Sikob					/*flags*/0);
2426113584Ssimokawa			if (error)
2427113584Ssimokawa				printf("sbp: bus_dmamap_load error %d\n", error);
2428103285Sikob		} else
2429103285Sikob			sbp_execute_ocb(ocb, NULL, 0, 0);
2430103285Sikob		break;
2431103285Sikob	}
2432103285Sikob	case XPT_CALC_GEOMETRY:
2433103285Sikob	{
2434103285Sikob		struct ccb_calc_geometry *ccg;
2435116351Snjl
2436103285Sikob		ccg = &ccb->ccg;
2437103285Sikob		if (ccg->block_size == 0) {
2438266772Sjhb			printf("sbp_action: block_size is 0.\n");
2439103285Sikob			ccb->ccb_h.status = CAM_REQ_INVALID;
2440103285Sikob			xpt_done(ccb);
2441103285Sikob			break;
2442103285Sikob		}
2443103285SikobSBP_DEBUG(1)
2444257381Snwhitehorn		printf("%s:%d:%d:%jx:XPT_CALC_GEOMETRY: "
2445114540Sjake			"Volume size = %jd\n",
2446114927Ssimokawa			device_get_nameunit(sbp->fd.dev),
2447114927Ssimokawa			cam_sim_path(sbp->sim),
2448257381Snwhitehorn			ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun,
2449271795Swill			(uintmax_t)ccg->volume_size);
2450103285SikobEND_DEBUG
2451103285Sikob
2452116351Snjl		cam_calc_geometry(ccg, /*extended*/1);
2453103285Sikob		xpt_done(ccb);
2454103285Sikob		break;
2455103285Sikob	}
2456103285Sikob	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
2457103285Sikob	{
2458103285Sikob
2459103285SikobSBP_DEBUG(1)
2460103285Sikob		printf("%s:%d:XPT_RESET_BUS: \n",
2461103285Sikob			device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim));
2462103285SikobEND_DEBUG
2463103285Sikob
2464103285Sikob		ccb->ccb_h.status = CAM_REQ_INVALID;
2465103285Sikob		xpt_done(ccb);
2466103285Sikob		break;
2467103285Sikob	}
2468103285Sikob	case XPT_PATH_INQ:		/* Path routing inquiry */
2469103285Sikob	{
2470103285Sikob		struct ccb_pathinq *cpi = &ccb->cpi;
2471272214Skan
2472103285SikobSBP_DEBUG(1)
2473257381Snwhitehorn		printf("%s:%d:%jx XPT_PATH_INQ:.\n",
2474103285Sikob			device_get_nameunit(sbp->fd.dev),
2475257381Snwhitehorn			ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun);
2476103285SikobEND_DEBUG
2477103285Sikob		cpi->version_num = 1; /* XXX??? */
2478111615Ssimokawa		cpi->hba_inquiry = PI_TAG_ABLE;
2479103285Sikob		cpi->target_sprt = 0;
2480118105Snjl		cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE;
2481103285Sikob		cpi->hba_eng_cnt = 0;
2482103285Sikob		cpi->max_target = SBP_NUM_TARGETS - 1;
2483103285Sikob		cpi->max_lun = SBP_NUM_LUNS - 1;
2484103285Sikob		cpi->initiator_id = SBP_INITIATOR;
2485103285Sikob		cpi->bus_id = sim->bus_id;
2486103285Sikob		cpi->base_transfer_speed = 400 * 1000 / 8;
2487103285Sikob		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2488103285Sikob		strncpy(cpi->hba_vid, "SBP", HBA_IDLEN);
2489103285Sikob		strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
2490103285Sikob		cpi->unit_number = sim->unit_number;
2491163816Smjacob                cpi->transport = XPORT_SPI;	/* XX should have a FireWire */
2492163816Smjacob                cpi->transport_version = 2;
2493163816Smjacob                cpi->protocol = PROTO_SCSI;
2494163816Smjacob                cpi->protocol_version = SCSI_REV_2;
2495103285Sikob
2496103285Sikob		cpi->ccb_h.status = CAM_REQ_CMP;
2497103285Sikob		xpt_done(ccb);
2498103285Sikob		break;
2499103285Sikob	}
2500103285Sikob	case XPT_GET_TRAN_SETTINGS:
2501103285Sikob	{
2502103285Sikob		struct ccb_trans_settings *cts = &ccb->cts;
2503163816Smjacob		struct ccb_trans_settings_scsi *scsi =
2504163816Smjacob		    &cts->proto_specific.scsi;
2505163816Smjacob		struct ccb_trans_settings_spi *spi =
2506163816Smjacob		    &cts->xport_specific.spi;
2507163816Smjacob
2508163816Smjacob		cts->protocol = PROTO_SCSI;
2509163816Smjacob		cts->protocol_version = SCSI_REV_2;
2510163816Smjacob		cts->transport = XPORT_SPI;	/* should have a FireWire */
2511163816Smjacob		cts->transport_version = 2;
2512163816Smjacob		spi->valid = CTS_SPI_VALID_DISC;
2513163816Smjacob		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
2514163816Smjacob		scsi->valid = CTS_SCSI_VALID_TQ;
2515163816Smjacob		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2516103285SikobSBP_DEBUG(1)
2517257381Snwhitehorn		printf("%s:%d:%jx XPT_GET_TRAN_SETTINGS:.\n",
2518103285Sikob			device_get_nameunit(sbp->fd.dev),
2519257381Snwhitehorn			ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun);
2520103285SikobEND_DEBUG
2521103285Sikob		cts->ccb_h.status = CAM_REQ_CMP;
2522103285Sikob		xpt_done(ccb);
2523103285Sikob		break;
2524103285Sikob	}
2525103285Sikob	case XPT_ABORT:
2526103285Sikob		ccb->ccb_h.status = CAM_UA_ABORT;
2527103285Sikob		xpt_done(ccb);
2528103285Sikob		break;
2529111615Ssimokawa	case XPT_SET_TRAN_SETTINGS:
2530111615Ssimokawa		/* XXX */
2531103285Sikob	default:
2532103285Sikob		ccb->ccb_h.status = CAM_REQ_INVALID;
2533103285Sikob		xpt_done(ccb);
2534103285Sikob		break;
2535103285Sikob	}
2536103285Sikob	return;
2537103285Sikob}
2538103285Sikob
2539103285Sikobstatic void
2540272214Skansbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error)
2541103285Sikob{
2542103285Sikob	int i;
2543103285Sikob	struct sbp_ocb *ocb;
2544103285Sikob	struct sbp_ocb *prev;
2545105633Ssimokawa	bus_dma_segment_t *s;
2546103285Sikob
2547103285Sikob	if (error)
2548103285Sikob		printf("sbp_execute_ocb: error=%d\n", error);
2549103285Sikob
2550103285Sikob	ocb = (struct sbp_ocb *)arg;
2551113584Ssimokawa
2552121185SsimokawaSBP_DEBUG(2)
2553113584Ssimokawa	printf("sbp_execute_ocb: seg %d", seg);
2554113584Ssimokawa	for (i = 0; i < seg; i++)
2555113972Ssimokawa		printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr,
2556113972Ssimokawa					(uintmax_t)segments[i].ds_len);
2557113584Ssimokawa	printf("\n");
2558113584SsimokawaEND_DEBUG
2559113584Ssimokawa
2560103285Sikob	if (seg == 1) {
2561103285Sikob		/* direct pointer */
2562113474Ssimokawa		s = &segments[0];
2563113474Ssimokawa		if (s->ds_len > SBP_SEG_MAX)
2564113474Ssimokawa			panic("ds_len > SBP_SEG_MAX, fix busdma code");
2565113474Ssimokawa		ocb->orb[3] = htonl(s->ds_addr);
2566113474Ssimokawa		ocb->orb[4] |= htonl(s->ds_len);
2567272214Skan	} else if (seg > 1) {
2568103285Sikob		/* page table */
2569103285Sikob		for (i = 0; i < seg; i++) {
2570105633Ssimokawa			s = &segments[i];
2571108877SsimokawaSBP_DEBUG(0)
2572108877Ssimokawa			/* XXX LSI Logic "< 16 byte" bug might be hit */
2573105633Ssimokawa			if (s->ds_len < 16)
2574105633Ssimokawa				printf("sbp_execute_ocb: warning, "
2575106543Ssimokawa					"segment length(%zd) is less than 16."
2576272214Skan					"(seg=%d/%d)\n", (size_t)s->ds_len, i + 1, seg);
2577108877SsimokawaEND_DEBUG
2578113474Ssimokawa			if (s->ds_len > SBP_SEG_MAX)
2579113474Ssimokawa				panic("ds_len > SBP_SEG_MAX, fix busdma code");
2580105633Ssimokawa			ocb->ind_ptr[i].hi = htonl(s->ds_len << 16);
2581105633Ssimokawa			ocb->ind_ptr[i].lo = htonl(s->ds_addr);
2582103285Sikob		}
2583103285Sikob		ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg);
2584103285Sikob	}
2585272214Skan
2586113584Ssimokawa	if (seg > 0)
2587113584Ssimokawa		bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap,
2588113584Ssimokawa			(ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
2589113584Ssimokawa			BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
2590103285Sikob	prev = sbp_enqueue_ocb(ocb->sdev, ocb);
2591113584Ssimokawa	fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE);
2592127468Ssimokawa	if (use_doorbell) {
2593127468Ssimokawa		if (prev == NULL) {
2594127468Ssimokawa			if (ocb->sdev->last_ocb != NULL)
2595127468Ssimokawa				sbp_doorbell(ocb->sdev);
2596127468Ssimokawa			else
2597272214Skan				sbp_orb_pointer(ocb->sdev, ocb);
2598127468Ssimokawa		}
2599127468Ssimokawa	} else {
2600127468Ssimokawa		if (prev == NULL || (ocb->sdev->flags & ORB_LINK_DEAD) != 0) {
2601127468Ssimokawa			ocb->sdev->flags &= ~ORB_LINK_DEAD;
2602272214Skan			sbp_orb_pointer(ocb->sdev, ocb);
2603127468Ssimokawa		}
2604120842Ssimokawa	}
2605103285Sikob}
2606103285Sikob
2607103285Sikobstatic void
2608103285Sikobsbp_poll(struct cam_sim *sim)
2609272214Skan{
2610120847Ssimokawa	struct sbp_softc *sbp;
2611120847Ssimokawa	struct firewire_comm *fc;
2612120847Ssimokawa
2613120847Ssimokawa	sbp = (struct sbp_softc *)sim->softc;
2614120847Ssimokawa	fc = sbp->fd.fc;
2615120847Ssimokawa
2616120847Ssimokawa	fc->poll(fc, 0, -1);
2617120847Ssimokawa
2618103285Sikob	return;
2619103285Sikob}
2620120847Ssimokawa
2621103285Sikobstatic struct sbp_ocb *
2622111615Ssimokawasbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status)
2623103285Sikob{
2624103285Sikob	struct sbp_ocb *ocb;
2625103285Sikob	struct sbp_ocb *next;
2626266772Sjhb	int order = 0;
2627103285Sikob
2628103285SikobSBP_DEBUG(1)
2629188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2630188756Ssbruno	"%s:%s 0x%08x src %d\n",
2631188756Ssbruno	    __func__, sdev->bustgtlun, ntohl(sbp_status->orb_lo), sbp_status->src);
2632103285SikobEND_DEBUG
2633266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2634266772Sjhb	STAILQ_FOREACH_SAFE(ocb, &sdev->ocbs, ocb, next) {
2635111615Ssimokawa		if (OCB_MATCH(ocb, sbp_status)) {
2636103285Sikob			/* found */
2637111819Ssimokawa			STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb);
2638103285Sikob			if (ocb->ccb != NULL)
2639266772Sjhb				callout_stop(&ocb->timer);
2640113584Ssimokawa			if (ntohl(ocb->orb[4]) & 0xffff) {
2641113584Ssimokawa				bus_dmamap_sync(sdev->target->sbp->dmat,
2642113584Ssimokawa					ocb->dmamap,
2643113584Ssimokawa					(ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
2644113584Ssimokawa					BUS_DMASYNC_POSTREAD :
2645113584Ssimokawa					BUS_DMASYNC_POSTWRITE);
2646113584Ssimokawa				bus_dmamap_unload(sdev->target->sbp->dmat,
2647113584Ssimokawa					ocb->dmamap);
2648103285Sikob			}
2649127468Ssimokawa			if (!use_doorbell) {
2650127468Ssimokawa				if (sbp_status->src == SRC_NO_NEXT) {
2651127468Ssimokawa					if (next != NULL)
2652272214Skan						sbp_orb_pointer(sdev, next);
2653127468Ssimokawa					else if (order > 0) {
2654127468Ssimokawa						/*
2655127468Ssimokawa						 * Unordered execution
2656127468Ssimokawa						 * We need to send pointer for
2657127468Ssimokawa						 * next ORB
2658127468Ssimokawa						 */
2659127468Ssimokawa						sdev->flags |= ORB_LINK_DEAD;
2660127468Ssimokawa					}
2661120842Ssimokawa				}
2662127468Ssimokawa			} else {
2663127468Ssimokawa				/*
2664127468Ssimokawa				 * XXX this is not correct for unordered
2665272214Skan				 * execution.
2666127468Ssimokawa				 */
2667170807Ssimokawa				if (sdev->last_ocb != NULL) {
2668127468Ssimokawa					sbp_free_ocb(sdev, sdev->last_ocb);
2669170807Ssimokawa				}
2670127468Ssimokawa				sdev->last_ocb = ocb;
2671127468Ssimokawa				if (next != NULL &&
2672127468Ssimokawa				    sbp_status->src == SRC_NO_NEXT)
2673127468Ssimokawa					sbp_doorbell(sdev);
2674120842Ssimokawa			}
2675103285Sikob			break;
2676111819Ssimokawa		} else
2677272214Skan			order++;
2678103285Sikob	}
2679103285SikobSBP_DEBUG(0)
2680103285Sikob	if (ocb && order > 0) {
2681188756Ssbruno		device_printf(sdev->target->sbp->fd.dev,
2682188756Ssbruno			"%s:%s unordered execution order:%d\n",
2683188756Ssbruno			__func__, sdev->bustgtlun, order);
2684103285Sikob	}
2685103285SikobEND_DEBUG
2686103285Sikob	return (ocb);
2687103285Sikob}
2688103285Sikob
2689103285Sikobstatic struct sbp_ocb *
2690103285Sikobsbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
2691103285Sikob{
2692127468Ssimokawa	struct sbp_ocb *prev, *prev2;
2693103285Sikob
2694266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2695121185SsimokawaSBP_DEBUG(1)
2696188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2697188756Ssbruno	"%s:%s 0x%08jx\n", __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr);
2698103285SikobEND_DEBUG
2699127468Ssimokawa	prev2 = prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb);
2700103285Sikob	STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb);
2701103285Sikob
2702274819Ssmh	if (ocb->ccb != NULL) {
2703274819Ssmh		callout_reset_sbt(&ocb->timer,
2704274819Ssmh		    SBT_1MS * ocb->ccb->ccb_h.timeout, 0, sbp_timeout,
2705274819Ssmh		    ocb, 0);
2706274819Ssmh	}
2707103285Sikob
2708127468Ssimokawa	if (use_doorbell && prev == NULL)
2709127468Ssimokawa		prev2 = sdev->last_ocb;
2710127468Ssimokawa
2711170807Ssimokawa	if (prev2 != NULL && (ocb->sdev->flags & ORB_LINK_DEAD) == 0) {
2712170807SsimokawaSBP_DEBUG(1)
2713120842Ssimokawa		printf("linking chain 0x%jx -> 0x%jx\n",
2714127468Ssimokawa		    (uintmax_t)prev2->bus_addr, (uintmax_t)ocb->bus_addr);
2715103285SikobEND_DEBUG
2716170724Ssimokawa		/*
2717170724Ssimokawa		 * Suppress compiler optimization so that orb[1] must be written first.
2718170724Ssimokawa		 * XXX We may need an explicit memory barrier for other architectures
2719170724Ssimokawa		 * other than i386/amd64.
2720170724Ssimokawa		 */
2721170724Ssimokawa		*(volatile uint32_t *)&prev2->orb[1] = htonl(ocb->bus_addr);
2722170724Ssimokawa		*(volatile uint32_t *)&prev2->orb[0] = 0;
2723103285Sikob	}
2724103285Sikob
2725103285Sikob	return prev;
2726103285Sikob}
2727103285Sikob
2728103285Sikobstatic struct sbp_ocb *
2729113584Ssimokawasbp_get_ocb(struct sbp_dev *sdev)
2730103285Sikob{
2731103285Sikob	struct sbp_ocb *ocb;
2732170374Ssimokawa
2733266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2734113584Ssimokawa	ocb = STAILQ_FIRST(&sdev->free_ocbs);
2735103285Sikob	if (ocb == NULL) {
2736127468Ssimokawa		sdev->flags |= ORB_SHORTAGE;
2737103285Sikob		printf("ocb shortage!!!\n");
2738103285Sikob		return NULL;
2739103285Sikob	}
2740113584Ssimokawa	STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb);
2741103285Sikob	ocb->ccb = NULL;
2742103285Sikob	return (ocb);
2743103285Sikob}
2744103285Sikob
2745103285Sikobstatic void
2746113584Ssimokawasbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
2747103285Sikob{
2748103285Sikob	ocb->flags = 0;
2749103285Sikob	ocb->ccb = NULL;
2750170374Ssimokawa
2751266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2752113584Ssimokawa	STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb);
2753127468Ssimokawa	if ((sdev->flags & ORB_SHORTAGE) != 0) {
2754127468Ssimokawa		int count;
2755127468Ssimokawa
2756127468Ssimokawa		sdev->flags &= ~ORB_SHORTAGE;
2757127468Ssimokawa		count = sdev->freeze;
2758127468Ssimokawa		sdev->freeze = 0;
2759127468Ssimokawa		xpt_release_devq(sdev->path, count, TRUE);
2760127468Ssimokawa	}
2761103285Sikob}
2762103285Sikob
2763103285Sikobstatic void
2764103285Sikobsbp_abort_ocb(struct sbp_ocb *ocb, int status)
2765103285Sikob{
2766103285Sikob	struct sbp_dev *sdev;
2767103285Sikob
2768103285Sikob	sdev = ocb->sdev;
2769266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2770113584SsimokawaSBP_DEBUG(0)
2771188756Ssbruno	device_printf(sdev->target->sbp->fd.dev,
2772188756Ssbruno	"%s:%s 0x%jx\n", __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr);
2773113584SsimokawaEND_DEBUG
2774113584SsimokawaSBP_DEBUG(1)
2775105792Ssimokawa	if (ocb->ccb != NULL)
2776105792Ssimokawa		sbp_print_scsi_cmd(ocb);
2777103285SikobEND_DEBUG
2778113584Ssimokawa	if (ntohl(ocb->orb[4]) & 0xffff) {
2779113584Ssimokawa		bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap,
2780113584Ssimokawa			(ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
2781113584Ssimokawa			BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
2782113584Ssimokawa		bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap);
2783113584Ssimokawa	}
2784111819Ssimokawa	if (ocb->ccb != NULL) {
2785266772Sjhb		callout_stop(&ocb->timer);
2786103285Sikob		ocb->ccb->ccb_h.status = status;
2787103285Sikob		xpt_done(ocb->ccb);
2788103285Sikob	}
2789113584Ssimokawa	sbp_free_ocb(sdev, ocb);
2790103285Sikob}
2791103285Sikob
2792103285Sikobstatic void
2793103285Sikobsbp_abort_all_ocbs(struct sbp_dev *sdev, int status)
2794103285Sikob{
2795105792Ssimokawa	struct sbp_ocb *ocb, *next;
2796105792Ssimokawa	STAILQ_HEAD(, sbp_ocb) temp;
2797103285Sikob
2798170807Ssimokawa	STAILQ_INIT(&temp);
2799266772Sjhb	SBP_LOCK_ASSERT(sdev->target->sbp);
2800170807Ssimokawa	STAILQ_CONCAT(&temp, &sdev->ocbs);
2801105792Ssimokawa	STAILQ_INIT(&sdev->ocbs);
2802170807Ssimokawa
2803266772Sjhb	STAILQ_FOREACH_SAFE(ocb, &temp, ocb, next) {
2804103285Sikob		sbp_abort_ocb(ocb, status);
2805103285Sikob	}
2806127468Ssimokawa	if (sdev->last_ocb != NULL) {
2807127468Ssimokawa		sbp_free_ocb(sdev, sdev->last_ocb);
2808127468Ssimokawa		sdev->last_ocb = NULL;
2809127468Ssimokawa	}
2810103285Sikob}
2811103285Sikob
2812103285Sikobstatic devclass_t sbp_devclass;
2813103285Sikob
2814103285Sikobstatic device_method_t sbp_methods[] = {
2815103285Sikob	/* device interface */
2816103285Sikob	DEVMETHOD(device_identify,	sbp_identify),
2817103285Sikob	DEVMETHOD(device_probe,		sbp_probe),
2818103285Sikob	DEVMETHOD(device_attach,	sbp_attach),
2819103285Sikob	DEVMETHOD(device_detach,	sbp_detach),
2820110145Ssimokawa	DEVMETHOD(device_shutdown,	sbp_shutdown),
2821103285Sikob
2822103285Sikob	{ 0, 0 }
2823103285Sikob};
2824103285Sikob
2825103285Sikobstatic driver_t sbp_driver = {
2826103285Sikob	"sbp",
2827103285Sikob	sbp_methods,
2828103285Sikob	sizeof(struct sbp_softc),
2829103285Sikob};
2830103285SikobDRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0);
2831103285SikobMODULE_VERSION(sbp, 1);
2832103285SikobMODULE_DEPEND(sbp, firewire, 1, 1, 1);
2833103285SikobMODULE_DEPEND(sbp, cam, 1, 1, 1);
2834