3 * Hidetoshi Shimokawa. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
16 * This product includes software developed by Hidetoshi Shimokawa.
18 * 4. Neither the name of the author nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
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>
43 #include <sys/malloc.h>
44 #include <sys/endian.h>
45 #if __FreeBSD_version < 500000
46 #include <sys/devicestat.h>
50 #include <machine/bus.h>
52 #include <dev/firewire/firewire.h>
53 #include <dev/firewire/firewirereg.h>
54 #include <dev/firewire/iec13213.h>
55 #include <dev/firewire/sbp.h>
56 #include <dev/firewire/fwmem.h>
59 #include <cam/cam_ccb.h>
60 #include <cam/cam_sim.h>
61 #include <cam/cam_xpt_sim.h>
62 #include <cam/cam_debug.h>
63 #include <cam/cam_periph.h>
64 #include <cam/scsi/scsi_all.h>
66 #define SBP_TARG_RECV_LEN 8
67 #define MAX_INITIATORS 8
72 * management/command block agent registers
74 * BASE 0xffff f001 0000 management port
75 * BASE 0xffff f001 0020 command port for login id 0
76 * BASE 0xffff f001 0040 command port for login id 1
79 #define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 000 */
80 #define SBP_TARG_BIND_HI 0xffff
81 #define SBP_TARG_BIND_LO(l) (0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1))
82 #define SBP_TARG_BIND_START (((u_int64_t)SBP_TARG_BIND_HI << 32) | \
84 #define SBP_TARG_BIND_END (((u_int64_t)SBP_TARG_BIND_HI << 32) | \
85 SBP_TARG_BIND_LO(MAX_LOGINS))
86 #define SBP_TARG_LOGIN_ID(lo) (((lo) - SBP_TARG_BIND_LO(0))/0x20)
90 #define FETCH_POINTER 2
92 #define F_LINK_ACTIVE (1 << 0)
93 #define F_ATIO_STARVED (1 << 1)
94 #define F_LOGIN (1 << 2)
95 #define F_HOLD (1 << 3)
96 #define F_FREEZED (1 << 4)
98 MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode");
100 static int debug = 0;
102 SYSCTL_INT(_debug, OID_AUTO, sbp_targ_debug, CTLFLAG_RW, &debug, 0,
103 "SBP target mode debug flag");
105 struct sbp_targ_login {
106 struct sbp_targ_lstate *lstate;
107 struct fw_device *fwdev;
108 struct sbp_login_res loginres;
113 STAILQ_HEAD(, orb_info) orbs;
114 STAILQ_ENTRY(sbp_targ_login) link;
119 struct callout hold_callout;
122 struct sbp_targ_lstate {
124 struct sbp_targ_softc *sc;
125 struct cam_path *path;
126 struct ccb_hdr_slist accept_tios;
127 struct ccb_hdr_slist immed_notifies;
128 struct crom_chunk model;
130 STAILQ_HEAD(, sbp_targ_login) logins;
133 struct sbp_targ_softc {
134 struct firewire_dev_comm fd;
136 struct cam_path *path;
140 struct crom_chunk unit;
141 struct sbp_targ_lstate *lstate[MAX_LUN];
142 struct sbp_targ_lstate *black_hole;
143 struct sbp_targ_login *logins[MAX_LOGINS];
146 #define SBP_LOCK(sc) mtx_lock(&(sc)->mtx)
147 #define SBP_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
150 #if BYTE_ORDER == BIG_ENDIAN
157 page_table_present:1,
161 uint32_t data_size:16,
163 page_table_present:1,
174 #if BYTE_ORDER == BIG_ENDIAN
190 struct sbp_targ_softc *sc;
191 struct fw_device *fwdev;
192 struct sbp_targ_login *login;
194 struct ccb_accept_tio *atio;
196 #define ORBI_STATUS_NONE 0
197 #define ORBI_STATUS_FETCH 1
198 #define ORBI_STATUS_ATIO 2
199 #define ORBI_STATUS_CTIO 3
200 #define ORBI_STATUS_STATUS 4
201 #define ORBI_STATUS_POINTER 5
202 #define ORBI_STATUS_ABORTED 7
209 STAILQ_ENTRY(orb_info) link;
211 uint32_t *page_table;
212 struct sbp_status status;
215 static char *orb_fun_name[] = {
219 static void sbp_targ_recv(struct fw_xfer *);
220 static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *,
221 uint16_t, uint32_t, struct sbp_targ_login *, int);
222 static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *);
225 sbp_targ_identify(driver_t *driver, device_t parent)
227 BUS_ADD_CHILD(parent, 0, "sbp_targ", device_get_unit(parent));
231 sbp_targ_probe(device_t dev)
235 pa = device_get_parent(dev);
236 if(device_get_unit(dev) != device_get_unit(pa)){
240 device_set_desc(dev, "SBP-2/SCSI over FireWire target mode");
245 sbp_targ_dealloc_login(struct sbp_targ_login *login)
247 struct orb_info *orbi, *next;
250 printf("%s: login = NULL\n", __func__);
253 for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) {
254 next = STAILQ_NEXT(orbi, link);
255 free(orbi, M_SBP_TARG);
257 callout_stop(&login->hold_callout);
259 STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link);
260 login->lstate->sc->logins[login->id] = NULL;
261 free((void *)login, M_SBP_TARG);
265 sbp_targ_hold_expire(void *arg)
267 struct sbp_targ_login *login;
269 login = (struct sbp_targ_login *)arg;
271 if (login->flags & F_HOLD) {
272 printf("%s: login_id=%d expired\n", __func__, login->id);
273 sbp_targ_dealloc_login(login);
275 printf("%s: login_id=%d not hold\n", __func__, login->id);
280 sbp_targ_post_busreset(void *arg)
282 struct sbp_targ_softc *sc;
283 struct crom_src *src;
284 struct crom_chunk *root;
285 struct crom_chunk *unit;
286 struct sbp_targ_lstate *lstate;
287 struct sbp_targ_login *login;
290 sc = (struct sbp_targ_softc *)arg;
291 src = sc->fd.fc->crom_src;
292 root = sc->fd.fc->crom_root;
296 if ((sc->flags & F_FREEZED) == 0) {
298 sc->flags |= F_FREEZED;
299 xpt_freeze_simq(sc->sim, /*count*/1);
302 printf("%s: already freezed\n", __func__);
305 bzero(unit, sizeof(struct crom_chunk));
307 crom_add_chunk(src, root, unit, CROM_UDIR);
308 crom_add_entry(unit, CSRKEY_SPEC, CSRVAL_ANSIT10);
309 crom_add_entry(unit, CSRKEY_VER, CSRVAL_T10SBP2);
310 crom_add_entry(unit, CSRKEY_COM_SPEC, CSRVAL_ANSIT10);
311 crom_add_entry(unit, CSRKEY_COM_SET, CSRVAL_SCSI);
313 crom_add_entry(unit, CROM_MGM, SBP_TARG_MGM >> 2);
314 crom_add_entry(unit, CSRKEY_UNIT_CH, (10<<8) | 8);
316 for (i = 0; i < MAX_LUN; i ++) {
317 lstate = sc->lstate[i];
320 crom_add_entry(unit, CSRKEY_FIRM_VER, 1);
321 crom_add_entry(unit, CROM_LUN, i);
322 crom_add_entry(unit, CSRKEY_MODEL, 1);
323 crom_add_simple_text(src, unit, &lstate->model, "TargetMode");
326 /* Process for reconnection hold time */
327 for (i = 0; i < MAX_LOGINS; i ++) {
328 login = sc->logins[i];
331 sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
332 if (login->flags & F_LOGIN) {
333 login->flags |= F_HOLD;
334 callout_reset(&login->hold_callout,
335 hz * login->hold_sec,
336 sbp_targ_hold_expire, (void *)login);
342 sbp_targ_post_explore(void *arg)
344 struct sbp_targ_softc *sc;
346 sc = (struct sbp_targ_softc *)arg;
348 sc->flags &= ~F_FREEZED;
349 xpt_release_simq(sc->sim, /*run queue*/TRUE);
355 sbp_targ_find_devs(struct sbp_targ_softc *sc, union ccb *ccb,
356 struct sbp_targ_lstate **lstate, int notfound_failure)
360 /* XXX 0 is the only vaild target_id */
361 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD &&
362 ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
363 *lstate = sc->black_hole;
364 return (CAM_REQ_CMP);
367 if (ccb->ccb_h.target_id != 0)
368 return (CAM_TID_INVALID);
370 lun = ccb->ccb_h.target_lun;
372 return (CAM_LUN_INVALID);
374 *lstate = sc->lstate[lun];
376 if (notfound_failure != 0 && *lstate == NULL)
377 return (CAM_PATH_INVALID);
379 return (CAM_REQ_CMP);
383 sbp_targ_en_lun(struct sbp_targ_softc *sc, union ccb *ccb)
385 struct ccb_en_lun *cel = &ccb->cel;
386 struct sbp_targ_lstate *lstate;
389 status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
390 if (status != CAM_REQ_CMP) {
391 ccb->ccb_h.status = status;
395 if (cel->enable != 0) {
396 if (lstate != NULL) {
397 xpt_print_path(ccb->ccb_h.path);
398 printf("Lun already enabled\n");
399 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
402 if (cel->grp6_len != 0 || cel->grp7_len != 0) {
403 ccb->ccb_h.status = CAM_REQ_INVALID;
404 printf("Non-zero Group Codes\n");
407 lstate = (struct sbp_targ_lstate *)
408 malloc(sizeof(*lstate), M_SBP_TARG, M_NOWAIT | M_ZERO);
409 if (lstate == NULL) {
410 xpt_print_path(ccb->ccb_h.path);
411 printf("Couldn't allocate lstate\n");
412 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
415 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
416 sc->black_hole = lstate;
418 sc->lstate[ccb->ccb_h.target_lun] = lstate;
419 memset(lstate, 0, sizeof(*lstate));
421 status = xpt_create_path(&lstate->path, /*periph*/NULL,
422 xpt_path_path_id(ccb->ccb_h.path),
423 xpt_path_target_id(ccb->ccb_h.path),
424 xpt_path_lun_id(ccb->ccb_h.path));
425 if (status != CAM_REQ_CMP) {
426 free(lstate, M_SBP_TARG);
427 xpt_print_path(ccb->ccb_h.path);
428 printf("Couldn't allocate path\n");
429 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
432 SLIST_INIT(&lstate->accept_tios);
433 SLIST_INIT(&lstate->immed_notifies);
434 STAILQ_INIT(&lstate->logins);
436 ccb->ccb_h.status = CAM_REQ_CMP;
437 xpt_print_path(ccb->ccb_h.path);
438 printf("Lun now enabled for target mode\n");
440 sc->fd.fc->ibr(sc->fd.fc);
442 struct sbp_targ_login *login, *next;
444 if (lstate == NULL) {
445 ccb->ccb_h.status = CAM_LUN_INVALID;
448 ccb->ccb_h.status = CAM_REQ_CMP;
450 if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
451 printf("ATIOs pending\n");
452 ccb->ccb_h.status = CAM_REQ_INVALID;
455 if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
456 printf("INOTs pending\n");
457 ccb->ccb_h.status = CAM_REQ_INVALID;
460 if (ccb->ccb_h.status != CAM_REQ_CMP) {
464 xpt_print_path(ccb->ccb_h.path);
465 printf("Target mode disabled\n");
466 xpt_free_path(lstate->path);
468 for (login = STAILQ_FIRST(&lstate->logins); login != NULL;
470 next = STAILQ_NEXT(login, link);
471 sbp_targ_dealloc_login(login);
474 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
475 sc->black_hole = NULL;
477 sc->lstate[ccb->ccb_h.target_lun] = NULL;
478 free(lstate, M_SBP_TARG);
481 sc->fd.fc->ibr(sc->fd.fc);
486 sbp_targ_send_lstate_events(struct sbp_targ_softc *sc,
487 struct sbp_targ_lstate *lstate)
490 struct ccb_hdr *ccbh;
491 struct ccb_immed_notify *inot;
493 printf("%s: not implemented yet\n", __func__);
499 sbp_targ_remove_orb_info_locked(struct sbp_targ_login *login, struct orb_info *orbi)
501 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
505 sbp_targ_remove_orb_info(struct sbp_targ_login *login, struct orb_info *orbi)
508 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link);
509 SBP_UNLOCK(orbi->sc);
513 * tag_id/init_id encoding
515 * tag_id and init_id has only 32bit for each.
516 * scsi_target can handle very limited number(up to 15) of init_id.
517 * we have to encode 48bit orb and 64bit EUI64 into these
520 * tag_id represents lower 32bit of ORB address.
521 * init_id represents login_id.
525 static struct orb_info *
526 sbp_targ_get_orb_info(struct sbp_targ_lstate *lstate,
527 u_int tag_id, u_int init_id)
529 struct sbp_targ_login *login;
530 struct orb_info *orbi;
532 login = lstate->sc->logins[init_id];
534 printf("%s: no such login\n", __func__);
537 STAILQ_FOREACH(orbi, &login->orbs, link)
538 if (orbi->orb_lo == tag_id)
540 printf("%s: orb not found tag_id=0x%08x init_id=%d\n",
541 __func__, tag_id, init_id);
548 sbp_targ_abort(struct sbp_targ_softc *sc, struct orb_info *orbi)
550 struct orb_info *norbi;
553 for (; orbi != NULL; orbi = norbi) {
554 printf("%s: status=%d ccb=%p\n", __func__, orbi->state, orbi->ccb);
555 norbi = STAILQ_NEXT(orbi, link);
556 if (orbi->state != ORBI_STATUS_ABORTED) {
557 if (orbi->ccb != NULL) {
558 orbi->ccb->ccb_h.status = CAM_REQ_ABORTED;
563 if (orbi->state <= ORBI_STATUS_ATIO) {
564 sbp_targ_remove_orb_info_locked(orbi->login, orbi);
565 free(orbi, M_SBP_TARG);
568 orbi->state = ORBI_STATUS_ABORTED;
575 sbp_targ_free_orbi(struct fw_xfer *xfer)
577 struct orb_info *orbi;
579 orbi = (struct orb_info *)xfer->sc;
580 if (xfer->resp != 0) {
582 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
584 free(orbi, M_SBP_TARG);
589 sbp_targ_status_FIFO(struct orb_info *orbi,
590 uint32_t fifo_hi, uint32_t fifo_lo, int dequeue)
592 struct fw_xfer *xfer;
595 sbp_targ_remove_orb_info(orbi->login, orbi);
597 xfer = fwmem_write_block(orbi->fwdev, (void *)orbi,
598 /*spd*/2, fifo_hi, fifo_lo,
599 sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status,
604 printf("%s: xfer == NULL\n", __func__);
609 sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb)
611 struct sbp_status *sbp_status;
613 struct orb_info *norbi;
616 sbp_status = &orbi->status;
618 orbi->state = ORBI_STATUS_STATUS;
620 sbp_status->resp = 0; /* XXX */
621 sbp_status->status = 0; /* XXX */
622 sbp_status->dead = 0; /* XXX */
624 switch (ccb->csio.scsi_status) {
627 printf("%s: STATUS_OK\n", __func__);
630 case SCSI_STATUS_CHECK_COND:
631 case SCSI_STATUS_BUSY:
632 case SCSI_STATUS_CMD_TERMINATED:
634 struct sbp_cmd_status *sbp_cmd_status;
635 struct scsi_sense_data *sense;
636 int error_code, sense_key, asc, ascq;
644 printf("%s: STATUS %d\n", __func__,
645 ccb->csio.scsi_status);
646 sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0];
647 sbp_cmd_status->status = ccb->csio.scsi_status;
648 sense = &ccb->csio.sense_data;
650 #if 0 /* XXX What we should do? */
652 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
654 norbi = STAILQ_NEXT(orbi, link);
656 printf("%s: status=%d\n", __func__, norbi->state);
657 if (norbi->ccb != NULL) {
658 norbi->ccb->ccb_h.status = CAM_REQ_ABORTED;
659 xpt_done(norbi->ccb);
662 sbp_targ_remove_orb_info_locked(orbi->login, norbi);
663 norbi = STAILQ_NEXT(norbi, link);
664 free(norbi, M_SBP_TARG);
669 sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
670 scsi_extract_sense_len(sense, sense_len, &error_code,
671 &sense_key, &asc, &ascq, /*show_errors*/ 0);
673 switch (error_code) {
674 case SSD_CURRENT_ERROR:
675 case SSD_DESC_CURRENT_ERROR:
676 sbp_cmd_status->sfmt = SBP_SFMT_CURR;
679 sbp_cmd_status->sfmt = SBP_SFMT_DEFER;
683 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info,
686 sbp_cmd_status->valid = 1;
689 sbp_cmd_status->info = htobe32(info_trunc);
691 sbp_cmd_status->valid = 0;
694 sbp_cmd_status->s_key = sense_key;
696 if (scsi_get_stream_info(sense, sense_len, NULL,
697 &stream_bits) == 0) {
698 sbp_cmd_status->mark =
699 (stream_bits & SSD_FILEMARK) ? 1 : 0;
700 sbp_cmd_status->eom =
701 (stream_bits & SSD_EOM) ? 1 : 0;
702 sbp_cmd_status->ill_len =
703 (stream_bits & SSD_ILI) ? 1 : 0;
705 sbp_cmd_status->mark = 0;
706 sbp_cmd_status->eom = 0;
707 sbp_cmd_status->ill_len = 0;
711 /* add_sense_code(_qual), info, cmd_spec_info */
714 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND,
715 &info, &sinfo) == 0) {
716 uint32_t cmdspec_trunc;
718 cmdspec_trunc = info;
720 sbp_cmd_status->cdb = htobe32(cmdspec_trunc);
723 sbp_cmd_status->s_code = asc;
724 sbp_cmd_status->s_qlfr = ascq;
726 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU, &info,
728 sbp_cmd_status->fru = (uint8_t)info;
731 sbp_cmd_status->fru = 0;
734 if (scsi_get_sks(sense, sense_len, sks) == 0) {
735 bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks));
742 printf("%s: unknown scsi status 0x%x\n", __func__,
746 if (orbi->page_table != NULL)
747 free(orbi->page_table, M_SBP_TARG);
749 sbp_targ_status_FIFO(orbi,
750 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
754 sbp_targ_cam_done(struct fw_xfer *xfer)
756 struct orb_info *orbi;
759 orbi = (struct orb_info *)xfer->sc;
762 printf("%s: resp=%d refcount=%d\n", __func__,
763 xfer->resp, orbi->refcount);
765 if (xfer->resp != 0) {
766 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
767 orbi->status.resp = SBP_TRANS_FAIL;
768 orbi->status.status = OBJ_DATA | SBE_TIMEOUT/*XXX*/;
769 orbi->status.dead = 1;
770 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
776 if (orbi->refcount == 0) {
778 if (orbi->state == ORBI_STATUS_ABORTED) {
780 printf("%s: orbi aborted\n", __func__);
781 sbp_targ_remove_orb_info(orbi->login, orbi);
782 if (orbi->page_table != NULL)
783 free(orbi->page_table, M_SBP_TARG);
784 free(orbi, M_SBP_TARG);
785 } else if (orbi->status.resp == 0) {
786 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0)
787 sbp_targ_send_status(orbi, ccb);
788 ccb->ccb_h.status = CAM_REQ_CMP;
791 SBP_UNLOCK(orbi->sc);
793 orbi->status.len = 1;
794 sbp_targ_status_FIFO(orbi,
795 orbi->login->fifo_hi, orbi->login->fifo_lo,
797 ccb->ccb_h.status = CAM_REQ_ABORTED;
800 SBP_UNLOCK(orbi->sc);
808 sbp_targ_abort_ccb(struct sbp_targ_softc *sc, union ccb *ccb)
811 struct sbp_targ_lstate *lstate;
812 struct ccb_hdr_slist *list;
813 struct ccb_hdr *curelm;
817 status = sbp_targ_find_devs(sc, ccb, &lstate, 0);
818 if (status != CAM_REQ_CMP)
821 accb = ccb->cab.abort_ccb;
823 if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
824 list = &lstate->accept_tios;
825 else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY)
826 list = &lstate->immed_notifies;
828 return (CAM_UA_ABORT);
830 curelm = SLIST_FIRST(list);
832 if (curelm == &accb->ccb_h) {
834 SLIST_REMOVE_HEAD(list, sim_links.sle);
836 while(curelm != NULL) {
837 struct ccb_hdr *nextelm;
839 nextelm = SLIST_NEXT(curelm, sim_links.sle);
840 if (nextelm == &accb->ccb_h) {
842 SLIST_NEXT(curelm, sim_links.sle) =
843 SLIST_NEXT(nextelm, sim_links.sle);
850 accb->ccb_h.status = CAM_REQ_ABORTED;
852 return (CAM_REQ_CMP);
854 printf("%s: not found\n", __func__);
855 return (CAM_PATH_INVALID);
859 sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset,
860 uint16_t dst_hi, uint32_t dst_lo, u_int size,
861 void (*hand)(struct fw_xfer *))
863 struct fw_xfer *xfer;
864 u_int len, ccb_dir, off = 0;
868 printf("%s: offset=%d size=%d\n", __func__, offset, size);
869 ccb_dir = orbi->ccb->ccb_h.flags & CAM_DIR_MASK;
870 ptr = (char *)orbi->ccb->csio.data_ptr + offset;
873 /* XXX assume dst_lo + off doesn't overflow */
874 len = MIN(size, 2048 /* XXX */);
877 if (ccb_dir == CAM_DIR_OUT)
878 xfer = fwmem_read_block(orbi->fwdev,
879 (void *)orbi, /*spd*/2,
880 dst_hi, dst_lo + off, len,
883 xfer = fwmem_write_block(orbi->fwdev,
884 (void *)orbi, /*spd*/2,
885 dst_hi, dst_lo + off, len,
888 printf("%s: xfer == NULL", __func__);
889 /* XXX what should we do?? */
897 sbp_targ_pt_done(struct fw_xfer *xfer)
899 struct orb_info *orbi;
901 u_int i, offset, res, len;
904 orbi = (struct orb_info *)xfer->sc;
906 if (orbi->state == ORBI_STATUS_ABORTED) {
908 printf("%s: orbi aborted\n", __func__);
909 sbp_targ_remove_orb_info(orbi->login, orbi);
910 free(orbi->page_table, M_SBP_TARG);
911 free(orbi, M_SBP_TARG);
915 if (xfer->resp != 0) {
916 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
917 orbi->status.resp = SBP_TRANS_FAIL;
918 orbi->status.status = OBJ_PT | SBE_TIMEOUT/*XXX*/;
919 orbi->status.dead = 1;
920 orbi->status.len = 1;
921 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
923 sbp_targ_status_FIFO(orbi,
924 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
925 free(orbi->page_table, M_SBP_TARG);
929 res = ccb->csio.dxfer_len;
932 printf("%s: dxfer_len=%d\n", __func__, res);
934 for (p = orbi->page_table, i = orbi->orb4.data_size; i > 0; i --) {
938 printf("page_table: %04x:%08x %d\n",
939 t1 & 0xffff, t2, t1>>16);
940 len = MIN(t1 >> 16, res);
942 sbp_targ_xfer_buf(orbi, offset, t1 & 0xffff, t2, len,
949 if (orbi->refcount == 0)
950 printf("%s: refcount == 0\n", __func__);
952 /* XXX handle res != 0 case */
953 printf("%s: page table is too small(%d)\n", __func__, res);
960 sbp_targ_fetch_pt(struct orb_info *orbi)
962 struct fw_xfer *xfer;
965 printf("%s: page_table_size=%d\n",
966 __func__, orbi->orb4.data_size);
967 orbi->page_table = malloc(orbi->orb4.data_size*8, M_SBP_TARG, M_NOWAIT);
968 if (orbi->page_table == NULL)
970 xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/2,
971 orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*8,
972 (void *)orbi->page_table, sbp_targ_pt_done);
976 orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
982 sbp_targ_action1(struct cam_sim *sim, union ccb *ccb)
984 struct sbp_targ_softc *sc;
985 struct sbp_targ_lstate *lstate;
989 sc = (struct sbp_targ_softc *)cam_sim_softc(sim);
991 status = sbp_targ_find_devs(sc, ccb, &lstate, TRUE);
993 switch (ccb->ccb_h.func_code) {
994 case XPT_CONT_TARGET_IO:
996 struct orb_info *orbi;
999 printf("%s: XPT_CONT_TARGET_IO (0x%08x)\n",
1000 __func__, ccb->csio.tag_id);
1002 if (status != CAM_REQ_CMP) {
1003 ccb->ccb_h.status = status;
1007 /* XXX transfer from/to initiator */
1008 orbi = sbp_targ_get_orb_info(lstate,
1009 ccb->csio.tag_id, ccb->csio.init_id);
1011 ccb->ccb_h.status = CAM_REQ_ABORTED; /* XXX */
1015 if (orbi->state == ORBI_STATUS_ABORTED) {
1017 printf("%s: ctio aborted\n", __func__);
1018 sbp_targ_remove_orb_info_locked(orbi->login, orbi);
1019 free(orbi, M_SBP_TARG);
1020 ccb->ccb_h.status = CAM_REQ_ABORTED;
1024 orbi->state = ORBI_STATUS_CTIO;
1027 ccb_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1030 if (ccb->csio.dxfer_len == 0)
1031 ccb_dir = CAM_DIR_NONE;
1034 if (ccb_dir == CAM_DIR_IN && orbi->orb4.dir == 0)
1035 printf("%s: direction mismatch\n", __func__);
1037 /* check page table */
1038 if (ccb_dir != CAM_DIR_NONE && orbi->orb4.page_table_present) {
1040 printf("%s: page_table_present\n",
1042 if (orbi->orb4.page_size != 0) {
1043 printf("%s: unsupported pagesize %d != 0\n",
1044 __func__, orbi->orb4.page_size);
1045 ccb->ccb_h.status = CAM_REQ_INVALID;
1049 sbp_targ_fetch_pt(orbi);
1054 if (ccb_dir != CAM_DIR_NONE &&
1055 orbi->orb4.data_size != ccb->csio.dxfer_len)
1056 printf("%s: data_size(%d) != dxfer_len(%d)\n",
1057 __func__, orbi->orb4.data_size,
1058 ccb->csio.dxfer_len);
1060 if (ccb_dir != CAM_DIR_NONE)
1061 sbp_targ_xfer_buf(orbi, 0, orbi->data_hi,
1063 MIN(orbi->orb4.data_size, ccb->csio.dxfer_len),
1066 if (ccb_dir == CAM_DIR_NONE) {
1067 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1070 sbp_targ_send_status(orbi, ccb);
1073 ccb->ccb_h.status = CAM_REQ_CMP;
1078 case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */
1079 if (status != CAM_REQ_CMP) {
1080 ccb->ccb_h.status = status;
1084 SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
1086 ccb->ccb_h.status = CAM_REQ_INPROG;
1087 if ((lstate->flags & F_ATIO_STARVED) != 0) {
1088 struct sbp_targ_login *login;
1091 printf("%s: new atio arrived\n", __func__);
1092 lstate->flags &= ~F_ATIO_STARVED;
1093 STAILQ_FOREACH(login, &lstate->logins, link)
1094 if ((login->flags & F_ATIO_STARVED) != 0) {
1095 login->flags &= ~F_ATIO_STARVED;
1096 sbp_targ_fetch_orb(lstate->sc,
1098 login->last_hi, login->last_lo,
1103 case XPT_NOTIFY_ACK: /* recycle notify ack */
1104 case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */
1105 if (status != CAM_REQ_CMP) {
1106 ccb->ccb_h.status = status;
1110 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
1112 ccb->ccb_h.status = CAM_REQ_INPROG;
1113 sbp_targ_send_lstate_events(sc, lstate);
1116 sbp_targ_en_lun(sc, ccb);
1121 struct ccb_pathinq *cpi = &ccb->cpi;
1123 cpi->version_num = 1; /* XXX??? */
1124 cpi->hba_inquiry = PI_TAG_ABLE;
1125 cpi->target_sprt = PIT_PROCESSOR
1128 cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE;
1129 cpi->hba_eng_cnt = 0;
1130 cpi->max_target = 7; /* XXX */
1131 cpi->max_lun = MAX_LUN - 1;
1132 cpi->initiator_id = 7; /* XXX */
1133 cpi->bus_id = sim->bus_id;
1134 cpi->base_transfer_speed = 400 * 1000 / 8;
1135 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1136 strncpy(cpi->hba_vid, "SBP_TARG", HBA_IDLEN);
1137 strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
1138 cpi->unit_number = sim->unit_number;
1140 cpi->ccb_h.status = CAM_REQ_CMP;
1146 union ccb *accb = ccb->cab.abort_ccb;
1148 switch (accb->ccb_h.func_code) {
1149 case XPT_ACCEPT_TARGET_IO:
1150 case XPT_IMMED_NOTIFY:
1151 ccb->ccb_h.status = sbp_targ_abort_ccb(sc, ccb);
1153 case XPT_CONT_TARGET_IO:
1155 ccb->ccb_h.status = CAM_UA_ABORT;
1158 printf("%s: aborting unknown function %d\n",
1159 __func__, accb->ccb_h.func_code);
1160 ccb->ccb_h.status = CAM_REQ_INVALID;
1167 printf("%s: unknown function %d\n",
1168 __func__, ccb->ccb_h.func_code);
1169 ccb->ccb_h.status = CAM_REQ_INVALID;
1177 sbp_targ_action(struct cam_sim *sim, union ccb *ccb)
1182 sbp_targ_action1(sim, ccb);
1187 sbp_targ_poll(struct cam_sim *sim)
1194 sbp_targ_cmd_handler(struct fw_xfer *xfer)
1199 struct orb_info *orbi;
1200 struct ccb_accept_tio *atio;
1204 orbi = (struct orb_info *)xfer->sc;
1205 if (xfer->resp != 0) {
1206 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1207 orbi->status.resp = SBP_TRANS_FAIL;
1208 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1209 orbi->status.dead = 1;
1210 orbi->status.len = 1;
1211 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1213 sbp_targ_status_FIFO(orbi,
1214 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
1218 fp = &xfer->recv.hdr;
1222 if (orbi->state == ORBI_STATUS_ABORTED) {
1223 printf("%s: aborted\n", __func__);
1224 sbp_targ_remove_orb_info(orbi->login, orbi);
1225 free(orbi, M_SBP_TARG);
1226 atio->ccb_h.status = CAM_REQ_ABORTED;
1228 xpt_done((union ccb*)atio);
1229 SBP_UNLOCK(orbi->sc);
1232 orbi->state = ORBI_STATUS_ATIO;
1235 /* swap payload except SCSI command */
1236 for (i = 0; i < 5; i ++)
1237 orb[i] = ntohl(orb[i]);
1239 orb4 = (struct corb4 *)&orb[4];
1240 if (orb4->rq_fmt != 0) {
1242 printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt);
1245 atio->ccb_h.target_id = 0; /* XXX */
1246 atio->ccb_h.target_lun = orbi->login->lstate->lun;
1247 atio->sense_len = 0;
1248 atio->tag_action = 1; /* XXX */
1249 atio->tag_id = orbi->orb_lo;
1250 atio->init_id = orbi->login->id;
1252 atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
1253 bytes = (u_char *)&orb[5];
1255 printf("%s: %p %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
1256 __func__, (void *)atio,
1257 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
1258 bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
1259 switch (bytes[0] >> 5) {
1275 /* Only copy the opcode. */
1277 printf("Reserved or VU command code type encountered\n");
1281 memcpy(atio->cdb_io.cdb_bytes, bytes, atio->cdb_len);
1283 atio->ccb_h.status |= CAM_CDB_RECVD;
1286 if ((orb[0] & (1<<31)) == 0) {
1288 printf("%s: fetch next orb\n", __func__);
1289 orbi->status.src = SRC_NEXT_EXISTS;
1290 sbp_targ_fetch_orb(orbi->sc, orbi->fwdev,
1291 orb[0], orb[1], orbi->login, FETCH_CMD);
1293 orbi->status.src = SRC_NO_NEXT;
1294 orbi->login->flags &= ~F_LINK_ACTIVE;
1297 orbi->data_hi = orb[2];
1298 orbi->data_lo = orb[3];
1302 xpt_done((union ccb*)atio);
1303 SBP_UNLOCK(orbi->sc);
1309 static struct sbp_targ_login *
1310 sbp_targ_get_login(struct sbp_targ_softc *sc, struct fw_device *fwdev, int lun)
1312 struct sbp_targ_lstate *lstate;
1313 struct sbp_targ_login *login;
1316 lstate = sc->lstate[lun];
1318 STAILQ_FOREACH(login, &lstate->logins, link)
1319 if (login->fwdev == fwdev)
1322 for (i = 0; i < MAX_LOGINS; i ++)
1323 if (sc->logins[i] == NULL)
1326 printf("%s: increase MAX_LOGIN\n", __func__);
1330 login = (struct sbp_targ_login *)malloc(
1331 sizeof(struct sbp_targ_login), M_SBP_TARG, M_NOWAIT | M_ZERO);
1333 if (login == NULL) {
1334 printf("%s: malloc failed\n", __func__);
1339 login->fwdev = fwdev;
1340 login->lstate = lstate;
1341 login->last_hi = 0xffff;
1342 login->last_lo = 0xffffffff;
1343 login->hold_sec = 1;
1344 STAILQ_INIT(&login->orbs);
1345 CALLOUT_INIT(&login->hold_callout);
1346 sc->logins[i] = login;
1351 sbp_targ_mgm_handler(struct fw_xfer *xfer)
1353 struct sbp_targ_lstate *lstate;
1354 struct sbp_targ_login *login;
1358 struct orb_info *orbi;
1361 orbi = (struct orb_info *)xfer->sc;
1362 if (xfer->resp != 0) {
1363 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1364 orbi->status.resp = SBP_TRANS_FAIL;
1365 orbi->status.status = OBJ_ORB | SBE_TIMEOUT/*XXX*/;
1366 orbi->status.dead = 1;
1367 orbi->status.len = 1;
1368 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
1370 sbp_targ_status_FIFO(orbi,
1371 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/0);
1375 fp = &xfer->recv.hdr;
1379 for (i = 0; i < 8; i ++) {
1380 orb[i] = ntohl(orb[i]);
1382 orb4 = (struct morb4 *)&orb[4];
1384 printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]);
1386 orbi->status.src = SRC_NO_NEXT;
1388 switch (orb4->fun << 16) {
1391 int exclusive = 0, lun;
1393 if (orb[4] & ORB_EXV)
1397 lstate = orbi->sc->lstate[lun];
1399 if (lun >= MAX_LUN || lstate == NULL ||
1401 STAILQ_FIRST(&lstate->logins) != NULL &&
1402 STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)
1405 orbi->status.dead = 1;
1406 orbi->status.status = STATUS_ACCESS_DENY;
1407 orbi->status.len = 1;
1411 /* allocate login */
1412 login = sbp_targ_get_login(orbi->sc, orbi->fwdev, lun);
1413 if (login == NULL) {
1414 printf("%s: sbp_targ_get_login failed\n",
1416 orbi->status.dead = 1;
1417 orbi->status.status = STATUS_RES_UNAVAIL;
1418 orbi->status.len = 1;
1421 printf("%s: login id=%d\n", __func__, login->id);
1423 login->fifo_hi = orb[6];
1424 login->fifo_lo = orb[7];
1425 login->loginres.len = htons(sizeof(uint32_t) * 4);
1426 login->loginres.id = htons(login->id);
1427 login->loginres.cmd_hi = htons(SBP_TARG_BIND_HI);
1428 login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id));
1429 login->loginres.recon_hold = htons(login->hold_sec);
1431 STAILQ_INSERT_TAIL(&lstate->logins, login, link);
1432 fwmem_write_block(orbi->fwdev, NULL, /*spd*/2, orb[2], orb[3],
1433 sizeof(struct sbp_login_res), (void *)&login->loginres,
1434 fw_asy_callback_free);
1435 /* XXX return status after loginres is successfully written */
1439 login = orbi->sc->logins[orb4->id];
1440 if (login != NULL && login->fwdev == orbi->fwdev) {
1441 login->flags &= ~F_HOLD;
1442 callout_stop(&login->hold_callout);
1443 printf("%s: reconnected id=%d\n",
1444 __func__, login->id);
1446 orbi->status.dead = 1;
1447 orbi->status.status = STATUS_ACCESS_DENY;
1448 printf("%s: reconnection faild id=%d\n",
1449 __func__, orb4->id);
1453 login = orbi->sc->logins[orb4->id];
1454 if (login->fwdev != orbi->fwdev) {
1455 printf("%s: wrong initiator\n", __func__);
1458 sbp_targ_dealloc_login(login);
1461 printf("%s: %s not implemented yet\n",
1462 __func__, orb_fun_name[orb4->fun]);
1465 orbi->status.len = 1;
1466 sbp_targ_status_FIFO(orbi, orb[6], orb[7], /*dequeue*/0);
1472 sbp_targ_pointer_handler(struct fw_xfer *xfer)
1474 struct orb_info *orbi;
1475 uint32_t orb0, orb1;
1477 orbi = (struct orb_info *)xfer->sc;
1478 if (xfer->resp != 0) {
1479 printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
1483 orb0 = ntohl(orbi->orb[0]);
1484 orb1 = ntohl(orbi->orb[1]);
1485 if ((orb0 & (1 << 31)) != 0) {
1486 printf("%s: invalid pointer\n", __func__);
1489 sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev,
1490 (uint16_t)orb0, orb1, orbi->login, FETCH_CMD);
1492 free(orbi, M_SBP_TARG);
1498 sbp_targ_fetch_orb(struct sbp_targ_softc *sc, struct fw_device *fwdev,
1499 uint16_t orb_hi, uint32_t orb_lo, struct sbp_targ_login *login,
1502 struct orb_info *orbi;
1505 printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo);
1506 orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO);
1508 printf("%s: malloc failed\n", __func__);
1512 orbi->fwdev = fwdev;
1513 orbi->login = login;
1514 orbi->orb_hi = orb_hi;
1515 orbi->orb_lo = orb_lo;
1516 orbi->status.orb_hi = htons(orb_hi);
1517 orbi->status.orb_lo = htonl(orb_lo);
1521 fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
1522 sizeof(uint32_t) * 8, &orbi->orb[0],
1523 sbp_targ_mgm_handler);
1526 orbi->state = ORBI_STATUS_FETCH;
1527 login->last_hi = orb_hi;
1528 login->last_lo = orb_lo;
1529 login->flags |= F_LINK_ACTIVE;
1532 orbi->atio = (struct ccb_accept_tio *)
1533 SLIST_FIRST(&login->lstate->accept_tios);
1534 if (orbi->atio == NULL) {
1536 printf("%s: no free atio\n", __func__);
1537 login->lstate->flags |= F_ATIO_STARVED;
1538 login->flags |= F_ATIO_STARVED;
1541 login->fwdev = fwdev;
1545 SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
1546 STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
1548 fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
1549 sizeof(uint32_t) * 8, &orbi->orb[0],
1550 sbp_targ_cmd_handler);
1553 orbi->state = ORBI_STATUS_POINTER;
1554 login->flags |= F_LINK_ACTIVE;
1555 fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
1556 sizeof(uint32_t) * 2, &orbi->orb[0],
1557 sbp_targ_pointer_handler);
1560 printf("%s: invalid mode %d\n", __func__, mode);
1565 sbp_targ_resp_callback(struct fw_xfer *xfer)
1567 struct sbp_targ_softc *sc;
1571 printf("%s: xfer=%p\n", __func__, xfer);
1572 sc = (struct sbp_targ_softc *)xfer->sc;
1573 fw_xfer_unload(xfer);
1574 xfer->recv.pay_len = SBP_TARG_RECV_LEN;
1575 xfer->hand = sbp_targ_recv;
1577 STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link);
1582 sbp_targ_cmd(struct fw_xfer *xfer, struct fw_device *fwdev, int login_id,
1585 struct sbp_targ_login *login;
1586 struct sbp_targ_softc *sc;
1589 if (login_id < 0 || login_id >= MAX_LOGINS)
1590 return(RESP_ADDRESS_ERROR);
1592 sc = (struct sbp_targ_softc *)xfer->sc;
1593 login = sc->logins[login_id];
1595 return(RESP_ADDRESS_ERROR);
1597 if (login->fwdev != fwdev) {
1599 return(RESP_ADDRESS_ERROR);
1603 case 0x08: /* ORB_POINTER */
1605 printf("%s: ORB_POINTER(%d)\n", __func__, login_id);
1606 if ((login->flags & F_LINK_ACTIVE) != 0) {
1608 printf("link active (ORB_POINTER)\n");
1611 sbp_targ_fetch_orb(sc, fwdev,
1612 ntohl(xfer->recv.payload[0]),
1613 ntohl(xfer->recv.payload[1]),
1616 case 0x04: /* AGENT_RESET */
1618 printf("%s: AGENT RESET(%d)\n", __func__, login_id);
1619 login->last_hi = 0xffff;
1620 login->last_lo = 0xffffffff;
1621 sbp_targ_abort(sc, STAILQ_FIRST(&login->orbs));
1623 case 0x10: /* DOORBELL */
1625 printf("%s: DOORBELL(%d)\n", __func__, login_id);
1626 if (login->last_hi == 0xffff &&
1627 login->last_lo == 0xffffffff) {
1628 printf("%s: no previous pointer(DOORBELL)\n",
1632 if ((login->flags & F_LINK_ACTIVE) != 0) {
1634 printf("link active (DOORBELL)\n");
1637 sbp_targ_fetch_orb(sc, fwdev,
1638 login->last_hi, login->last_lo,
1639 login, FETCH_POINTER);
1641 case 0x00: /* AGENT_STATE */
1642 printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id);
1644 case 0x14: /* UNSOLICITED_STATE_ENABLE */
1645 printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n",
1646 __func__, login_id);
1649 printf("%s: invalid register %d(%d)\n",
1650 __func__, reg, login_id);
1651 rtcode = RESP_ADDRESS_ERROR;
1658 sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev)
1660 struct sbp_targ_softc *sc;
1663 sc = (struct sbp_targ_softc *)xfer->sc;
1665 fp = &xfer->recv.hdr;
1666 if (fp->mode.wreqb.tcode != FWTCODE_WREQB){
1667 printf("%s: tcode = %d\n", __func__, fp->mode.wreqb.tcode);
1668 return(RESP_TYPE_ERROR);
1671 sbp_targ_fetch_orb(sc, fwdev,
1672 ntohl(xfer->recv.payload[0]),
1673 ntohl(xfer->recv.payload[1]),
1680 sbp_targ_recv(struct fw_xfer *xfer)
1682 struct fw_pkt *fp, *sfp;
1683 struct fw_device *fwdev;
1686 struct sbp_targ_softc *sc;
1689 sc = (struct sbp_targ_softc *)xfer->sc;
1690 fp = &xfer->recv.hdr;
1691 fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
1692 if (fwdev == NULL) {
1693 printf("%s: cannot resolve nodeid=%d\n",
1694 __func__, fp->mode.wreqb.src & 0x3f);
1695 rtcode = RESP_TYPE_ERROR; /* XXX */
1698 lo = fp->mode.wreqb.dest_lo;
1700 if (lo == SBP_TARG_BIND_LO(-1))
1701 rtcode = sbp_targ_mgm(xfer, fwdev);
1702 else if (lo >= SBP_TARG_BIND_LO(0))
1703 rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
1706 rtcode = RESP_ADDRESS_ERROR;
1710 printf("%s: rtcode = %d\n", __func__, rtcode);
1711 sfp = &xfer->send.hdr;
1712 xfer->send.spd = 2; /* XXX */
1713 xfer->hand = sbp_targ_resp_callback;
1714 sfp->mode.wres.dst = fp->mode.wreqb.src;
1715 sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
1716 sfp->mode.wres.tcode = FWTCODE_WRES;
1717 sfp->mode.wres.rtcode = rtcode;
1718 sfp->mode.wres.pri = 0;
1720 fw_asyreq(xfer->fc, -1, xfer);
1725 sbp_targ_attach(device_t dev)
1727 struct sbp_targ_softc *sc;
1728 struct cam_devq *devq;
1729 struct firewire_comm *fc;
1731 sc = (struct sbp_targ_softc *) device_get_softc(dev);
1732 bzero((void *)sc, sizeof(struct sbp_targ_softc));
1734 mtx_init(&sc->mtx, "sbp_targ", NULL, MTX_DEF);
1735 sc->fd.fc = fc = device_get_ivars(dev);
1737 sc->fd.post_explore = (void *) sbp_targ_post_explore;
1738 sc->fd.post_busreset = (void *) sbp_targ_post_busreset;
1740 devq = cam_simq_alloc(/*maxopenings*/MAX_LUN*MAX_INITIATORS);
1744 sc->sim = cam_sim_alloc(sbp_targ_action, sbp_targ_poll,
1745 "sbp_targ", sc, device_get_unit(dev), &sc->mtx,
1746 /*untagged*/ 1, /*tagged*/ 1, devq);
1747 if (sc->sim == NULL) {
1748 cam_simq_free(devq);
1753 if (xpt_bus_register(sc->sim, dev, /*bus*/0) != CAM_SUCCESS)
1756 if (xpt_create_path(&sc->path, /*periph*/ NULL, cam_sim_path(sc->sim),
1757 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1758 xpt_bus_deregister(cam_sim_path(sc->sim));
1763 sc->fwb.start = SBP_TARG_BIND_START;
1764 sc->fwb.end = SBP_TARG_BIND_END;
1766 /* pre-allocate xfer */
1767 STAILQ_INIT(&sc->fwb.xferlist);
1768 fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
1769 /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
1770 fc, (void *)sc, sbp_targ_recv);
1771 fw_bindadd(fc, &sc->fwb);
1776 cam_sim_free(sc->sim, /*free_devq*/TRUE);
1781 sbp_targ_detach(device_t dev)
1783 struct sbp_targ_softc *sc;
1784 struct sbp_targ_lstate *lstate;
1787 sc = (struct sbp_targ_softc *)device_get_softc(dev);
1788 sc->fd.post_busreset = NULL;
1791 xpt_free_path(sc->path);
1792 xpt_bus_deregister(cam_sim_path(sc->sim));
1794 cam_sim_free(sc->sim, /*free_devq*/TRUE);
1796 for (i = 0; i < MAX_LUN; i ++) {
1797 lstate = sc->lstate[i];
1798 if (lstate != NULL) {
1799 xpt_free_path(lstate->path);
1800 free(lstate, M_SBP_TARG);
1803 if (sc->black_hole != NULL) {
1804 xpt_free_path(sc->black_hole->path);
1805 free(sc->black_hole, M_SBP_TARG);
1808 fw_bindremove(sc->fd.fc, &sc->fwb);
1809 fw_xferlist_remove(&sc->fwb.xferlist);
1811 mtx_destroy(&sc->mtx);
1816 static devclass_t sbp_targ_devclass;
1818 static device_method_t sbp_targ_methods[] = {
1819 /* device interface */
1820 DEVMETHOD(device_identify, sbp_targ_identify),
1821 DEVMETHOD(device_probe, sbp_targ_probe),
1822 DEVMETHOD(device_attach, sbp_targ_attach),
1823 DEVMETHOD(device_detach, sbp_targ_detach),
1827 static driver_t sbp_targ_driver = {
1830 sizeof(struct sbp_targ_softc),
1833 DRIVER_MODULE(sbp_targ, firewire, sbp_targ_driver, sbp_targ_devclass, 0, 0);
1834 MODULE_VERSION(sbp_targ, 1);
1835 MODULE_DEPEND(sbp_targ, firewire, 1, 1, 1);
1836 MODULE_DEPEND(sbp_targ, cam, 1, 1, 1);