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