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