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$ 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 66 #define SBP_TARG_RECV_LEN 8 67 #define MAX_INITIATORS 8 68 #define MAX_LUN 63 69 #define MAX_LOGINS 63 70 #define MAX_NODES 63 71 /* 72 * management/command block agent registers 73 * 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 77 * 78 */ 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) | \ 83 SBP_TARG_BIND_LO(-1)) 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) 87 88 #define FETCH_MGM 0 89 #define FETCH_CMD 1 90 #define FETCH_POINTER 2 91 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) 97 98 static MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode"); 99 100 static int debug = 0; 101 102 SYSCTL_INT(_debug, OID_AUTO, sbp_targ_debug, CTLFLAG_RW, &debug, 0, 103 "SBP target mode debug flag"); 104 105 struct sbp_targ_login { 106 struct sbp_targ_lstate *lstate; 107 struct fw_device *fwdev; 108 struct sbp_login_res loginres; 109 uint16_t fifo_hi; 110 uint16_t last_hi; 111 uint32_t fifo_lo; 112 uint32_t last_lo; 113 STAILQ_HEAD(, orb_info) orbs; 114 STAILQ_ENTRY(sbp_targ_login) link; 115 uint16_t hold_sec; 116 uint16_t id; 117 uint8_t flags; 118 uint8_t spd; 119 struct callout hold_callout; 120 }; 121 122 struct sbp_targ_lstate { 123 uint16_t lun; 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; 129 uint32_t flags; 130 STAILQ_HEAD(, sbp_targ_login) logins; 131 }; 132 133 struct sbp_targ_softc { 134 struct firewire_dev_comm fd; 135 struct cam_sim *sim; 136 struct cam_path *path; 137 struct fw_bind fwb; 138 int ndevs; 139 int flags; 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]; 144 struct mtx mtx; 145 }; 146 #define SBP_LOCK(sc) mtx_lock(&(sc)->mtx) 147 #define SBP_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 148 149 struct corb4 { 150 #if BYTE_ORDER == BIG_ENDIAN 151 uint32_t n:1, 152 rq_fmt:2, 153 :1, 154 dir:1, 155 spd:3, 156 max_payload:4, 157 page_table_present:1, 158 page_size:3, 159 data_size:16; 160 #else 161 uint32_t data_size:16, 162 page_size:3, 163 page_table_present:1, 164 max_payload:4, 165 spd:3, 166 dir:1, 167 :1, 168 rq_fmt:2, 169 n:1; 170 #endif 171 }; 172 173 struct morb4 { 174 #if BYTE_ORDER == BIG_ENDIAN 175 uint32_t n:1, 176 rq_fmt:2, 177 :9, 178 fun:4, 179 id:16; 180 #else 181 uint32_t id:16, 182 fun:4, 183 :9, 184 rq_fmt:2, 185 n:1; 186 #endif 187 }; 188 189 struct orb_info { 190 struct sbp_targ_softc *sc; 191 struct fw_device *fwdev; 192 struct sbp_targ_login *login; 193 union ccb *ccb; 194 struct ccb_accept_tio *atio; 195 uint8_t state; 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 203 uint8_t refcount; 204 uint16_t orb_hi; 205 uint32_t orb_lo; 206 uint32_t data_hi; 207 uint32_t data_lo; 208 struct corb4 orb4; 209 STAILQ_ENTRY(orb_info) link; 210 uint32_t orb[8]; 211 uint32_t *page_table; 212 struct sbp_status status; 213 }; 214 215 static char *orb_fun_name[] = { 216 ORB_FUN_NAMES 217 }; 218 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 *); 223 224 static void 225 sbp_targ_identify(driver_t *driver, device_t parent) 226 { 227 BUS_ADD_CHILD(parent, 0, "sbp_targ", device_get_unit(parent)); 228 } 229 230 static int 231 sbp_targ_probe(device_t dev) 232 { 233 device_t pa; 234 235 pa = device_get_parent(dev); 236 if(device_get_unit(dev) != device_get_unit(pa)){ 237 return(ENXIO); 238 } 239 240 device_set_desc(dev, "SBP-2/SCSI over FireWire target mode"); 241 return (0); 242 } 243 244 static void 245 sbp_targ_dealloc_login(struct sbp_targ_login *login) 246 { 247 struct orb_info *orbi, *next; 248 249 if (login == NULL) { 250 printf("%s: login = NULL\n", __func__); 251 return; 252 } 253 for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) { 254 next = STAILQ_NEXT(orbi, link); 255 free(orbi, M_SBP_TARG); 256 } 257 callout_stop(&login->hold_callout); 258 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); 262 } 263 264 static void 265 sbp_targ_hold_expire(void *arg) 266 { 267 struct sbp_targ_login *login; 268 269 login = (struct sbp_targ_login *)arg; 270 271 if (login->flags & F_HOLD) { 272 printf("%s: login_id=%d expired\n", __func__, login->id); 273 sbp_targ_dealloc_login(login); 274 } else { 275 printf("%s: login_id=%d not hold\n", __func__, login->id); 276 } 277 } 278 279 static void 280 sbp_targ_post_busreset(void *arg) 281 { 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; 288 int i; 289 290 sc = (struct sbp_targ_softc *)arg; 291 src = sc->fd.fc->crom_src; 292 root = sc->fd.fc->crom_root; 293 294 unit = &sc->unit; 295 296 if ((sc->flags & F_FREEZED) == 0) { 297 SBP_LOCK(sc); 298 sc->flags |= F_FREEZED; 299 xpt_freeze_simq(sc->sim, /*count*/1); 300 SBP_UNLOCK(sc); 301 } else { 302 printf("%s: already freezed\n", __func__); 303 } 304 305 bzero(unit, sizeof(struct crom_chunk)); 306 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); 312 313 crom_add_entry(unit, CROM_MGM, SBP_TARG_MGM >> 2); 314 crom_add_entry(unit, CSRKEY_UNIT_CH, (10<<8) | 8); 315 316 for (i = 0; i < MAX_LUN; i ++) { 317 lstate = sc->lstate[i]; 318 if (lstate == NULL) 319 continue; 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"); 324 } 325 326 /* Process for reconnection hold time */ 327 for (i = 0; i < MAX_LOGINS; i ++) { 328 login = sc->logins[i]; 329 if (login == NULL) 330 continue; 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); 337 } 338 } 339 } 340 341 static void 342 sbp_targ_post_explore(void *arg) 343 { 344 struct sbp_targ_softc *sc; 345 346 sc = (struct sbp_targ_softc *)arg; 347 SBP_LOCK(sc); 348 sc->flags &= ~F_FREEZED; 349 xpt_release_simq(sc->sim, /*run queue*/TRUE); 350 SBP_UNLOCK(sc); 351 return; 352 } 353 354 static cam_status 355 sbp_targ_find_devs(struct sbp_targ_softc *sc, union ccb *ccb, 356 struct sbp_targ_lstate **lstate, int notfound_failure) 357 { 358 u_int lun; 359 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); 365 } 366 367 if (ccb->ccb_h.target_id != 0) 368 return (CAM_TID_INVALID); 369 370 lun = ccb->ccb_h.target_lun; 371 if (lun >= MAX_LUN) 372 return (CAM_LUN_INVALID); 373 374 *lstate = sc->lstate[lun]; 375 376 if (notfound_failure != 0 && *lstate == NULL) 377 return (CAM_PATH_INVALID); 378 379 return (CAM_REQ_CMP); 380 } 381 382 static void 383 sbp_targ_en_lun(struct sbp_targ_softc *sc, union ccb *ccb) 384 { 385 struct ccb_en_lun *cel = &ccb->cel; 386 struct sbp_targ_lstate *lstate; 387 cam_status status; 388 389 status = sbp_targ_find_devs(sc, ccb, &lstate, 0); 390 if (status != CAM_REQ_CMP) { 391 ccb->ccb_h.status = status; 392 return; 393 } 394 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; 400 return; 401 } 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"); 405 return; 406 } 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; 413 return; 414 } 415 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) 416 sc->black_hole = lstate; 417 else 418 sc->lstate[ccb->ccb_h.target_lun] = lstate; 419 memset(lstate, 0, sizeof(*lstate)); 420 lstate->sc = sc; 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; 430 return; 431 } 432 SLIST_INIT(&lstate->accept_tios); 433 SLIST_INIT(&lstate->immed_notifies); 434 STAILQ_INIT(&lstate->logins); 435 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"); 439 /* bus reset */ 440 sc->fd.fc->ibr(sc->fd.fc); 441 } else { 442 struct sbp_targ_login *login, *next; 443 444 if (lstate == NULL) { 445 ccb->ccb_h.status = CAM_LUN_INVALID; 446 return; 447 } 448 ccb->ccb_h.status = CAM_REQ_CMP; 449 450 if (SLIST_FIRST(&lstate->accept_tios) != NULL) { 451 printf("ATIOs pending\n"); 452 ccb->ccb_h.status = CAM_REQ_INVALID; 453 } 454 455 if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { 456 printf("INOTs pending\n"); 457 ccb->ccb_h.status = CAM_REQ_INVALID; 458 } 459 460 if (ccb->ccb_h.status != CAM_REQ_CMP) { 461 return; 462 } 463 464 xpt_print_path(ccb->ccb_h.path); 465 printf("Target mode disabled\n"); 466 xpt_free_path(lstate->path); 467 468 for (login = STAILQ_FIRST(&lstate->logins); login != NULL; 469 login = next) { 470 next = STAILQ_NEXT(login, link); 471 sbp_targ_dealloc_login(login); 472 } 473 474 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) 475 sc->black_hole = NULL; 476 else 477 sc->lstate[ccb->ccb_h.target_lun] = NULL; 478 free(lstate, M_SBP_TARG); 479 480 /* bus reset */ 481 sc->fd.fc->ibr(sc->fd.fc); 482 } 483 } 484 485 static void 486 sbp_targ_send_lstate_events(struct sbp_targ_softc *sc, 487 struct sbp_targ_lstate *lstate) 488 { 489 #if 0 490 struct ccb_hdr *ccbh; 491 struct ccb_immed_notify *inot; 492 493 printf("%s: not implemented yet\n", __func__); 494 #endif 495 } 496 497 498 static __inline void 499 sbp_targ_remove_orb_info_locked(struct sbp_targ_login *login, struct orb_info *orbi) 500 { 501 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link); 502 } 503 504 static __inline void 505 sbp_targ_remove_orb_info(struct sbp_targ_login *login, struct orb_info *orbi) 506 { 507 SBP_LOCK(orbi->sc); 508 STAILQ_REMOVE(&login->orbs, orbi, orb_info, link); 509 SBP_UNLOCK(orbi->sc); 510 } 511 512 /* 513 * tag_id/init_id encoding 514 * 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 518 * variables. 519 * 520 * tag_id represents lower 32bit of ORB address. 521 * init_id represents login_id. 522 * 523 */ 524 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) 528 { 529 struct sbp_targ_login *login; 530 struct orb_info *orbi; 531 532 login = lstate->sc->logins[init_id]; 533 if (login == NULL) { 534 printf("%s: no such login\n", __func__); 535 return (NULL); 536 } 537 STAILQ_FOREACH(orbi, &login->orbs, link) 538 if (orbi->orb_lo == tag_id) 539 goto found; 540 printf("%s: orb not found tag_id=0x%08x init_id=%d\n", 541 __func__, tag_id, init_id); 542 return (NULL); 543 found: 544 return (orbi); 545 } 546 547 static void 548 sbp_targ_abort(struct sbp_targ_softc *sc, struct orb_info *orbi) 549 { 550 struct orb_info *norbi; 551 552 SBP_LOCK(sc); 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; 559 xpt_done(orbi->ccb); 560 orbi->ccb = NULL; 561 } 562 #if 0 563 if (orbi->state <= ORBI_STATUS_ATIO) { 564 sbp_targ_remove_orb_info_locked(orbi->login, orbi); 565 free(orbi, M_SBP_TARG); 566 } else 567 #endif 568 orbi->state = ORBI_STATUS_ABORTED; 569 } 570 } 571 SBP_UNLOCK(sc); 572 } 573 574 static void 575 sbp_targ_free_orbi(struct fw_xfer *xfer) 576 { 577 struct orb_info *orbi; 578 579 orbi = (struct orb_info *)xfer->sc; 580 if (xfer->resp != 0) { 581 /* XXX */ 582 printf("%s: xfer->resp = %d\n", __func__, xfer->resp); 583 } 584 free(orbi, M_SBP_TARG); 585 fw_xfer_free(xfer); 586 } 587 588 static void 589 sbp_targ_status_FIFO(struct orb_info *orbi, 590 uint32_t fifo_hi, uint32_t fifo_lo, int dequeue) 591 { 592 struct fw_xfer *xfer; 593 594 if (dequeue) 595 sbp_targ_remove_orb_info(orbi->login, orbi); 596 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, 600 sbp_targ_free_orbi); 601 602 if (xfer == NULL) { 603 /* XXX */ 604 printf("%s: xfer == NULL\n", __func__); 605 } 606 } 607 608 static void 609 sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb) 610 { 611 struct sbp_status *sbp_status; 612 #if 0 613 struct orb_info *norbi; 614 #endif 615 616 sbp_status = &orbi->status; 617 618 orbi->state = ORBI_STATUS_STATUS; 619 620 sbp_status->resp = 0; /* XXX */ 621 sbp_status->status = 0; /* XXX */ 622 sbp_status->dead = 0; /* XXX */ 623 624 switch (ccb->csio.scsi_status) { 625 case SCSI_STATUS_OK: 626 if (debug) 627 printf("%s: STATUS_OK\n", __func__); 628 sbp_status->len = 1; 629 break; 630 case SCSI_STATUS_CHECK_COND: 631 case SCSI_STATUS_BUSY: 632 case SCSI_STATUS_CMD_TERMINATED: 633 { 634 struct sbp_cmd_status *sbp_cmd_status; 635 struct scsi_sense_data *sense; 636 int error_code, sense_key, asc, ascq; 637 uint8_t stream_bits; 638 uint8_t sks[3]; 639 uint64_t info; 640 int64_t sinfo; 641 int sense_len; 642 643 if (debug) 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; 649 650 #if 0 /* XXX What we should do? */ 651 #if 0 652 sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link)); 653 #else 654 norbi = STAILQ_NEXT(orbi, link); 655 while (norbi) { 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); 660 norbi->ccb = NULL; 661 } 662 sbp_targ_remove_orb_info_locked(orbi->login, norbi); 663 norbi = STAILQ_NEXT(norbi, link); 664 free(norbi, M_SBP_TARG); 665 } 666 #endif 667 #endif 668 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); 672 673 switch (error_code) { 674 case SSD_CURRENT_ERROR: 675 case SSD_DESC_CURRENT_ERROR: 676 sbp_cmd_status->sfmt = SBP_SFMT_CURR; 677 break; 678 default: 679 sbp_cmd_status->sfmt = SBP_SFMT_DEFER; 680 break; 681 } 682 683 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, 684 &sinfo) == 0) { 685 uint32_t info_trunc; 686 sbp_cmd_status->valid = 1; 687 info_trunc = info; 688 689 sbp_cmd_status->info = htobe32(info_trunc); 690 } else { 691 sbp_cmd_status->valid = 0; 692 } 693 694 sbp_cmd_status->s_key = sense_key; 695 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; 704 } else { 705 sbp_cmd_status->mark = 0; 706 sbp_cmd_status->eom = 0; 707 sbp_cmd_status->ill_len = 0; 708 } 709 710 711 /* add_sense_code(_qual), info, cmd_spec_info */ 712 sbp_status->len = 4; 713 714 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND, 715 &info, &sinfo) == 0) { 716 uint32_t cmdspec_trunc; 717 718 cmdspec_trunc = info; 719 720 sbp_cmd_status->cdb = htobe32(cmdspec_trunc); 721 } 722 723 sbp_cmd_status->s_code = asc; 724 sbp_cmd_status->s_qlfr = ascq; 725 726 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU, &info, 727 &sinfo) == 0) { 728 sbp_cmd_status->fru = (uint8_t)info; 729 sbp_status->len = 5; 730 } else { 731 sbp_cmd_status->fru = 0; 732 } 733 734 if (scsi_get_sks(sense, sense_len, sks) == 0) { 735 bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks)); 736 sbp_status->len = 5; 737 } 738 739 break; 740 } 741 default: 742 printf("%s: unknown scsi status 0x%x\n", __func__, 743 sbp_status->status); 744 } 745 746 if (orbi->page_table != NULL) 747 free(orbi->page_table, M_SBP_TARG); 748 749 sbp_targ_status_FIFO(orbi, 750 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); 751 } 752 753 static void 754 sbp_targ_cam_done(struct fw_xfer *xfer) 755 { 756 struct orb_info *orbi; 757 union ccb *ccb; 758 759 orbi = (struct orb_info *)xfer->sc; 760 761 if (debug > 1) 762 printf("%s: resp=%d refcount=%d\n", __func__, 763 xfer->resp, orbi->refcount); 764 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)); 771 } 772 773 orbi->refcount --; 774 775 ccb = orbi->ccb; 776 if (orbi->refcount == 0) { 777 orbi->ccb = NULL; 778 if (orbi->state == ORBI_STATUS_ABORTED) { 779 if (debug) 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; 789 SBP_LOCK(orbi->sc); 790 xpt_done(ccb); 791 SBP_UNLOCK(orbi->sc); 792 } else { 793 orbi->status.len = 1; 794 sbp_targ_status_FIFO(orbi, 795 orbi->login->fifo_hi, orbi->login->fifo_lo, 796 /*dequeue*/1); 797 ccb->ccb_h.status = CAM_REQ_ABORTED; 798 SBP_LOCK(orbi->sc); 799 xpt_done(ccb); 800 SBP_UNLOCK(orbi->sc); 801 } 802 } 803 804 fw_xfer_free(xfer); 805 } 806 807 static cam_status 808 sbp_targ_abort_ccb(struct sbp_targ_softc *sc, union ccb *ccb) 809 { 810 union ccb *accb; 811 struct sbp_targ_lstate *lstate; 812 struct ccb_hdr_slist *list; 813 struct ccb_hdr *curelm; 814 int found; 815 cam_status status; 816 817 status = sbp_targ_find_devs(sc, ccb, &lstate, 0); 818 if (status != CAM_REQ_CMP) 819 return (status); 820 821 accb = ccb->cab.abort_ccb; 822 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; 827 else 828 return (CAM_UA_ABORT); 829 830 curelm = SLIST_FIRST(list); 831 found = 0; 832 if (curelm == &accb->ccb_h) { 833 found = 1; 834 SLIST_REMOVE_HEAD(list, sim_links.sle); 835 } else { 836 while(curelm != NULL) { 837 struct ccb_hdr *nextelm; 838 839 nextelm = SLIST_NEXT(curelm, sim_links.sle); 840 if (nextelm == &accb->ccb_h) { 841 found = 1; 842 SLIST_NEXT(curelm, sim_links.sle) = 843 SLIST_NEXT(nextelm, sim_links.sle); 844 break; 845 } 846 curelm = nextelm; 847 } 848 } 849 if (found) { 850 accb->ccb_h.status = CAM_REQ_ABORTED; 851 xpt_done(accb); 852 return (CAM_REQ_CMP); 853 } 854 printf("%s: not found\n", __func__); 855 return (CAM_PATH_INVALID); 856 } 857 858 static void 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 *)) 862 { 863 struct fw_xfer *xfer; 864 u_int len, ccb_dir, off = 0; 865 char *ptr; 866 867 if (debug > 1) 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; 871 872 while (size > 0) { 873 /* XXX assume dst_lo + off doesn't overflow */ 874 len = MIN(size, 2048 /* XXX */); 875 size -= len; 876 orbi->refcount ++; 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, 881 ptr + off, hand); 882 else 883 xfer = fwmem_write_block(orbi->fwdev, 884 (void *)orbi, /*spd*/2, 885 dst_hi, dst_lo + off, len, 886 ptr + off, hand); 887 if (xfer == NULL) { 888 printf("%s: xfer == NULL", __func__); 889 /* XXX what should we do?? */ 890 orbi->refcount --; 891 } 892 off += len; 893 } 894 } 895 896 static void 897 sbp_targ_pt_done(struct fw_xfer *xfer) 898 { 899 struct orb_info *orbi; 900 union ccb *ccb; 901 u_int i, offset, res, len; 902 uint32_t t1, t2, *p; 903 904 orbi = (struct orb_info *)xfer->sc; 905 ccb = orbi->ccb; 906 if (orbi->state == ORBI_STATUS_ABORTED) { 907 if (debug) 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); 912 fw_xfer_free(xfer); 913 return; 914 } 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)); 922 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); 926 fw_xfer_free(xfer); 927 return; 928 } 929 res = ccb->csio.dxfer_len; 930 offset = 0; 931 if (debug) 932 printf("%s: dxfer_len=%d\n", __func__, res); 933 orbi->refcount ++; 934 for (p = orbi->page_table, i = orbi->orb4.data_size; i > 0; i --) { 935 t1 = ntohl(*p++); 936 t2 = ntohl(*p++); 937 if (debug > 1) 938 printf("page_table: %04x:%08x %d\n", 939 t1 & 0xffff, t2, t1>>16); 940 len = MIN(t1 >> 16, res); 941 res -= len; 942 sbp_targ_xfer_buf(orbi, offset, t1 & 0xffff, t2, len, 943 sbp_targ_cam_done); 944 offset += len; 945 if (res == 0) 946 break; 947 } 948 orbi->refcount --; 949 if (orbi->refcount == 0) 950 printf("%s: refcount == 0\n", __func__); 951 if (res !=0) 952 /* XXX handle res != 0 case */ 953 printf("%s: page table is too small(%d)\n", __func__, res); 954 955 fw_xfer_free(xfer); 956 return; 957 } 958 959 static void 960 sbp_targ_fetch_pt(struct orb_info *orbi) 961 { 962 struct fw_xfer *xfer; 963 964 if (debug) 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) 969 goto error; 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); 973 if (xfer != NULL) 974 return; 975 error: 976 orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 977 xpt_done(orbi->ccb); 978 return; 979 } 980 981 static void 982 sbp_targ_action1(struct cam_sim *sim, union ccb *ccb) 983 { 984 struct sbp_targ_softc *sc; 985 struct sbp_targ_lstate *lstate; 986 cam_status status; 987 u_int ccb_dir; 988 989 sc = (struct sbp_targ_softc *)cam_sim_softc(sim); 990 991 status = sbp_targ_find_devs(sc, ccb, &lstate, TRUE); 992 993 switch (ccb->ccb_h.func_code) { 994 case XPT_CONT_TARGET_IO: 995 { 996 struct orb_info *orbi; 997 998 if (debug) 999 printf("%s: XPT_CONT_TARGET_IO (0x%08x)\n", 1000 __func__, ccb->csio.tag_id); 1001 1002 if (status != CAM_REQ_CMP) { 1003 ccb->ccb_h.status = status; 1004 xpt_done(ccb); 1005 break; 1006 } 1007 /* XXX transfer from/to initiator */ 1008 orbi = sbp_targ_get_orb_info(lstate, 1009 ccb->csio.tag_id, ccb->csio.init_id); 1010 if (orbi == NULL) { 1011 ccb->ccb_h.status = CAM_REQ_ABORTED; /* XXX */ 1012 xpt_done(ccb); 1013 break; 1014 } 1015 if (orbi->state == ORBI_STATUS_ABORTED) { 1016 if (debug) 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; 1021 xpt_done(ccb); 1022 break; 1023 } 1024 orbi->state = ORBI_STATUS_CTIO; 1025 1026 orbi->ccb = ccb; 1027 ccb_dir = ccb->ccb_h.flags & CAM_DIR_MASK; 1028 1029 /* XXX */ 1030 if (ccb->csio.dxfer_len == 0) 1031 ccb_dir = CAM_DIR_NONE; 1032 1033 /* Sanity check */ 1034 if (ccb_dir == CAM_DIR_IN && orbi->orb4.dir == 0) 1035 printf("%s: direction mismatch\n", __func__); 1036 1037 /* check page table */ 1038 if (ccb_dir != CAM_DIR_NONE && orbi->orb4.page_table_present) { 1039 if (debug) 1040 printf("%s: page_table_present\n", 1041 __func__); 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; 1046 xpt_done(ccb); 1047 break; 1048 } 1049 sbp_targ_fetch_pt(orbi); 1050 break; 1051 } 1052 1053 /* Sanity check */ 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); 1059 1060 if (ccb_dir != CAM_DIR_NONE) 1061 sbp_targ_xfer_buf(orbi, 0, orbi->data_hi, 1062 orbi->data_lo, 1063 MIN(orbi->orb4.data_size, ccb->csio.dxfer_len), 1064 sbp_targ_cam_done); 1065 1066 if (ccb_dir == CAM_DIR_NONE) { 1067 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 1068 /* XXX */ 1069 SBP_UNLOCK(sc); 1070 sbp_targ_send_status(orbi, ccb); 1071 SBP_LOCK(sc); 1072 } 1073 ccb->ccb_h.status = CAM_REQ_CMP; 1074 xpt_done(ccb); 1075 } 1076 break; 1077 } 1078 case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */ 1079 if (status != CAM_REQ_CMP) { 1080 ccb->ccb_h.status = status; 1081 xpt_done(ccb); 1082 break; 1083 } 1084 SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 1085 sim_links.sle); 1086 ccb->ccb_h.status = CAM_REQ_INPROG; 1087 if ((lstate->flags & F_ATIO_STARVED) != 0) { 1088 struct sbp_targ_login *login; 1089 1090 if (debug) 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, 1097 login->fwdev, 1098 login->last_hi, login->last_lo, 1099 login, FETCH_CMD); 1100 } 1101 } 1102 break; 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; 1107 xpt_done(ccb); 1108 break; 1109 } 1110 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 1111 sim_links.sle); 1112 ccb->ccb_h.status = CAM_REQ_INPROG; 1113 sbp_targ_send_lstate_events(sc, lstate); 1114 break; 1115 case XPT_EN_LUN: 1116 sbp_targ_en_lun(sc, ccb); 1117 xpt_done(ccb); 1118 break; 1119 case XPT_PATH_INQ: 1120 { 1121 struct ccb_pathinq *cpi = &ccb->cpi; 1122 1123 cpi->version_num = 1; /* XXX??? */ 1124 cpi->hba_inquiry = PI_TAG_ABLE; 1125 cpi->target_sprt = PIT_PROCESSOR 1126 | PIT_DISCONNECT 1127 | PIT_TERM_IO; 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; 1139 1140 cpi->ccb_h.status = CAM_REQ_CMP; 1141 xpt_done(ccb); 1142 break; 1143 } 1144 case XPT_ABORT: 1145 { 1146 union ccb *accb = ccb->cab.abort_ccb; 1147 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); 1152 break; 1153 case XPT_CONT_TARGET_IO: 1154 /* XXX */ 1155 ccb->ccb_h.status = CAM_UA_ABORT; 1156 break; 1157 default: 1158 printf("%s: aborting unknown function %d\n", 1159 __func__, accb->ccb_h.func_code); 1160 ccb->ccb_h.status = CAM_REQ_INVALID; 1161 break; 1162 } 1163 xpt_done(ccb); 1164 break; 1165 } 1166 default: 1167 printf("%s: unknown function %d\n", 1168 __func__, ccb->ccb_h.func_code); 1169 ccb->ccb_h.status = CAM_REQ_INVALID; 1170 xpt_done(ccb); 1171 break; 1172 } 1173 return; 1174 } 1175 1176 static void 1177 sbp_targ_action(struct cam_sim *sim, union ccb *ccb) 1178 { 1179 int s; 1180 1181 s = splfw(); 1182 sbp_targ_action1(sim, ccb); 1183 splx(s); 1184 } 1185 1186 static void 1187 sbp_targ_poll(struct cam_sim *sim) 1188 { 1189 /* XXX */ 1190 return; 1191 } 1192 1193 static void 1194 sbp_targ_cmd_handler(struct fw_xfer *xfer) 1195 { 1196 struct fw_pkt *fp; 1197 uint32_t *orb; 1198 struct corb4 *orb4; 1199 struct orb_info *orbi; 1200 struct ccb_accept_tio *atio; 1201 u_char *bytes; 1202 int i; 1203 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)); 1212 1213 sbp_targ_status_FIFO(orbi, 1214 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1); 1215 fw_xfer_free(xfer); 1216 return; 1217 } 1218 fp = &xfer->recv.hdr; 1219 1220 atio = orbi->atio; 1221 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; 1227 SBP_LOCK(orbi->sc); 1228 xpt_done((union ccb*)atio); 1229 SBP_UNLOCK(orbi->sc); 1230 goto done0; 1231 } 1232 orbi->state = ORBI_STATUS_ATIO; 1233 1234 orb = orbi->orb; 1235 /* swap payload except SCSI command */ 1236 for (i = 0; i < 5; i ++) 1237 orb[i] = ntohl(orb[i]); 1238 1239 orb4 = (struct corb4 *)&orb[4]; 1240 if (orb4->rq_fmt != 0) { 1241 /* XXX */ 1242 printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt); 1243 } 1244 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; 1251 1252 atio->ccb_h.flags = CAM_TAG_ACTION_VALID; 1253 bytes = (u_char *)&orb[5]; 1254 if (debug) 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) { 1260 case 0: 1261 atio->cdb_len = 6; 1262 break; 1263 case 1: 1264 case 2: 1265 atio->cdb_len = 10; 1266 break; 1267 case 4: 1268 atio->cdb_len = 16; 1269 break; 1270 case 5: 1271 atio->cdb_len = 12; 1272 break; 1273 case 3: 1274 default: 1275 /* Only copy the opcode. */ 1276 atio->cdb_len = 1; 1277 printf("Reserved or VU command code type encountered\n"); 1278 break; 1279 } 1280 1281 memcpy(atio->cdb_io.cdb_bytes, bytes, atio->cdb_len); 1282 1283 atio->ccb_h.status |= CAM_CDB_RECVD; 1284 1285 /* next ORB */ 1286 if ((orb[0] & (1<<31)) == 0) { 1287 if (debug) 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); 1292 } else { 1293 orbi->status.src = SRC_NO_NEXT; 1294 orbi->login->flags &= ~F_LINK_ACTIVE; 1295 } 1296 1297 orbi->data_hi = orb[2]; 1298 orbi->data_lo = orb[3]; 1299 orbi->orb4 = *orb4; 1300 1301 SBP_LOCK(orbi->sc); 1302 xpt_done((union ccb*)atio); 1303 SBP_UNLOCK(orbi->sc); 1304 done0: 1305 fw_xfer_free(xfer); 1306 return; 1307 } 1308 1309 static struct sbp_targ_login * 1310 sbp_targ_get_login(struct sbp_targ_softc *sc, struct fw_device *fwdev, int lun) 1311 { 1312 struct sbp_targ_lstate *lstate; 1313 struct sbp_targ_login *login; 1314 int i; 1315 1316 lstate = sc->lstate[lun]; 1317 1318 STAILQ_FOREACH(login, &lstate->logins, link) 1319 if (login->fwdev == fwdev) 1320 return (login); 1321 1322 for (i = 0; i < MAX_LOGINS; i ++) 1323 if (sc->logins[i] == NULL) 1324 goto found; 1325 1326 printf("%s: increase MAX_LOGIN\n", __func__); 1327 return (NULL); 1328 1329 found: 1330 login = (struct sbp_targ_login *)malloc( 1331 sizeof(struct sbp_targ_login), M_SBP_TARG, M_NOWAIT | M_ZERO); 1332 1333 if (login == NULL) { 1334 printf("%s: malloc failed\n", __func__); 1335 return (NULL); 1336 } 1337 1338 login->id = i; 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; 1347 return (login); 1348 } 1349 1350 static void 1351 sbp_targ_mgm_handler(struct fw_xfer *xfer) 1352 { 1353 struct sbp_targ_lstate *lstate; 1354 struct sbp_targ_login *login; 1355 struct fw_pkt *fp; 1356 uint32_t *orb; 1357 struct morb4 *orb4; 1358 struct orb_info *orbi; 1359 int i; 1360 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)); 1369 1370 sbp_targ_status_FIFO(orbi, 1371 orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/0); 1372 fw_xfer_free(xfer); 1373 return; 1374 } 1375 fp = &xfer->recv.hdr; 1376 1377 orb = orbi->orb; 1378 /* swap payload */ 1379 for (i = 0; i < 8; i ++) { 1380 orb[i] = ntohl(orb[i]); 1381 } 1382 orb4 = (struct morb4 *)&orb[4]; 1383 if (debug) 1384 printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]); 1385 1386 orbi->status.src = SRC_NO_NEXT; 1387 1388 switch (orb4->fun << 16) { 1389 case ORB_FUN_LGI: 1390 { 1391 int exclusive = 0, lun; 1392 1393 if (orb[4] & ORB_EXV) 1394 exclusive = 1; 1395 1396 lun = orb4->id; 1397 lstate = orbi->sc->lstate[lun]; 1398 1399 if (lun >= MAX_LUN || lstate == NULL || 1400 (exclusive && 1401 STAILQ_FIRST(&lstate->logins) != NULL && 1402 STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev) 1403 ) { 1404 /* error */ 1405 orbi->status.dead = 1; 1406 orbi->status.status = STATUS_ACCESS_DENY; 1407 orbi->status.len = 1; 1408 break; 1409 } 1410 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", 1415 __func__); 1416 orbi->status.dead = 1; 1417 orbi->status.status = STATUS_RES_UNAVAIL; 1418 orbi->status.len = 1; 1419 break; 1420 } 1421 printf("%s: login id=%d\n", __func__, login->id); 1422 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); 1430 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 */ 1436 break; 1437 } 1438 case ORB_FUN_RCN: 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); 1445 } else { 1446 orbi->status.dead = 1; 1447 orbi->status.status = STATUS_ACCESS_DENY; 1448 printf("%s: reconnection faild id=%d\n", 1449 __func__, orb4->id); 1450 } 1451 break; 1452 case ORB_FUN_LGO: 1453 login = orbi->sc->logins[orb4->id]; 1454 if (login->fwdev != orbi->fwdev) { 1455 printf("%s: wrong initiator\n", __func__); 1456 break; 1457 } 1458 sbp_targ_dealloc_login(login); 1459 break; 1460 default: 1461 printf("%s: %s not implemented yet\n", 1462 __func__, orb_fun_name[orb4->fun]); 1463 break; 1464 } 1465 orbi->status.len = 1; 1466 sbp_targ_status_FIFO(orbi, orb[6], orb[7], /*dequeue*/0); 1467 fw_xfer_free(xfer); 1468 return; 1469 } 1470 1471 static void 1472 sbp_targ_pointer_handler(struct fw_xfer *xfer) 1473 { 1474 struct orb_info *orbi; 1475 uint32_t orb0, orb1; 1476 1477 orbi = (struct orb_info *)xfer->sc; 1478 if (xfer->resp != 0) { 1479 printf("%s: xfer->resp = %d\n", __func__, xfer->resp); 1480 goto done; 1481 } 1482 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__); 1487 goto done; 1488 } 1489 sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev, 1490 (uint16_t)orb0, orb1, orbi->login, FETCH_CMD); 1491 done: 1492 free(orbi, M_SBP_TARG); 1493 fw_xfer_free(xfer); 1494 return; 1495 } 1496 1497 static void 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, 1500 int mode) 1501 { 1502 struct orb_info *orbi; 1503 1504 if (debug) 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); 1507 if (orbi == NULL) { 1508 printf("%s: malloc failed\n", __func__); 1509 return; 1510 } 1511 orbi->sc = sc; 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); 1518 1519 switch (mode) { 1520 case FETCH_MGM: 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); 1524 break; 1525 case FETCH_CMD: 1526 orbi->state = ORBI_STATUS_FETCH; 1527 login->last_hi = orb_hi; 1528 login->last_lo = orb_lo; 1529 login->flags |= F_LINK_ACTIVE; 1530 /* dequeue */ 1531 SBP_LOCK(sc); 1532 orbi->atio = (struct ccb_accept_tio *) 1533 SLIST_FIRST(&login->lstate->accept_tios); 1534 if (orbi->atio == NULL) { 1535 SBP_UNLOCK(sc); 1536 printf("%s: no free atio\n", __func__); 1537 login->lstate->flags |= F_ATIO_STARVED; 1538 login->flags |= F_ATIO_STARVED; 1539 #if 0 1540 /* XXX ?? */ 1541 login->fwdev = fwdev; 1542 #endif 1543 break; 1544 } 1545 SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle); 1546 STAILQ_INSERT_TAIL(&login->orbs, orbi, link); 1547 SBP_UNLOCK(sc); 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); 1551 break; 1552 case FETCH_POINTER: 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); 1558 break; 1559 default: 1560 printf("%s: invalid mode %d\n", __func__, mode); 1561 } 1562 } 1563 1564 static void 1565 sbp_targ_resp_callback(struct fw_xfer *xfer) 1566 { 1567 struct sbp_targ_softc *sc; 1568 int s; 1569 1570 if (debug) 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; 1576 s = splfw(); 1577 STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link); 1578 splx(s); 1579 } 1580 1581 static int 1582 sbp_targ_cmd(struct fw_xfer *xfer, struct fw_device *fwdev, int login_id, 1583 int reg) 1584 { 1585 struct sbp_targ_login *login; 1586 struct sbp_targ_softc *sc; 1587 int rtcode = 0; 1588 1589 if (login_id < 0 || login_id >= MAX_LOGINS) 1590 return(RESP_ADDRESS_ERROR); 1591 1592 sc = (struct sbp_targ_softc *)xfer->sc; 1593 login = sc->logins[login_id]; 1594 if (login == NULL) 1595 return(RESP_ADDRESS_ERROR); 1596 1597 if (login->fwdev != fwdev) { 1598 /* XXX */ 1599 return(RESP_ADDRESS_ERROR); 1600 } 1601 1602 switch (reg) { 1603 case 0x08: /* ORB_POINTER */ 1604 if (debug) 1605 printf("%s: ORB_POINTER(%d)\n", __func__, login_id); 1606 if ((login->flags & F_LINK_ACTIVE) != 0) { 1607 if (debug) 1608 printf("link active (ORB_POINTER)\n"); 1609 break; 1610 } 1611 sbp_targ_fetch_orb(sc, fwdev, 1612 ntohl(xfer->recv.payload[0]), 1613 ntohl(xfer->recv.payload[1]), 1614 login, FETCH_CMD); 1615 break; 1616 case 0x04: /* AGENT_RESET */ 1617 if (debug) 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)); 1622 break; 1623 case 0x10: /* DOORBELL */ 1624 if (debug) 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", 1629 __func__); 1630 break; 1631 } 1632 if ((login->flags & F_LINK_ACTIVE) != 0) { 1633 if (debug) 1634 printf("link active (DOORBELL)\n"); 1635 break; 1636 } 1637 sbp_targ_fetch_orb(sc, fwdev, 1638 login->last_hi, login->last_lo, 1639 login, FETCH_POINTER); 1640 break; 1641 case 0x00: /* AGENT_STATE */ 1642 printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id); 1643 break; 1644 case 0x14: /* UNSOLICITED_STATE_ENABLE */ 1645 printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n", 1646 __func__, login_id); 1647 break; 1648 default: 1649 printf("%s: invalid register %d(%d)\n", 1650 __func__, reg, login_id); 1651 rtcode = RESP_ADDRESS_ERROR; 1652 } 1653 1654 return (rtcode); 1655 } 1656 1657 static int 1658 sbp_targ_mgm(struct fw_xfer *xfer, struct fw_device *fwdev) 1659 { 1660 struct sbp_targ_softc *sc; 1661 struct fw_pkt *fp; 1662 1663 sc = (struct sbp_targ_softc *)xfer->sc; 1664 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); 1669 } 1670 1671 sbp_targ_fetch_orb(sc, fwdev, 1672 ntohl(xfer->recv.payload[0]), 1673 ntohl(xfer->recv.payload[1]), 1674 NULL, FETCH_MGM); 1675 1676 return(0); 1677 } 1678 1679 static void 1680 sbp_targ_recv(struct fw_xfer *xfer) 1681 { 1682 struct fw_pkt *fp, *sfp; 1683 struct fw_device *fwdev; 1684 uint32_t lo; 1685 int s, rtcode; 1686 struct sbp_targ_softc *sc; 1687 1688 s = splfw(); 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 */ 1696 goto done; 1697 } 1698 lo = fp->mode.wreqb.dest_lo; 1699 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), 1704 lo % 0x20); 1705 else 1706 rtcode = RESP_ADDRESS_ERROR; 1707 1708 done: 1709 if (rtcode != 0) 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; 1719 1720 fw_asyreq(xfer->fc, -1, xfer); 1721 splx(s); 1722 } 1723 1724 static int 1725 sbp_targ_attach(device_t dev) 1726 { 1727 struct sbp_targ_softc *sc; 1728 struct cam_devq *devq; 1729 struct firewire_comm *fc; 1730 1731 sc = (struct sbp_targ_softc *) device_get_softc(dev); 1732 bzero((void *)sc, sizeof(struct sbp_targ_softc)); 1733 1734 mtx_init(&sc->mtx, "sbp_targ", NULL, MTX_DEF); 1735 sc->fd.fc = fc = device_get_ivars(dev); 1736 sc->fd.dev = dev; 1737 sc->fd.post_explore = (void *) sbp_targ_post_explore; 1738 sc->fd.post_busreset = (void *) sbp_targ_post_busreset; 1739 1740 devq = cam_simq_alloc(/*maxopenings*/MAX_LUN*MAX_INITIATORS); 1741 if (devq == NULL) 1742 return (ENXIO); 1743 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); 1749 return (ENXIO); 1750 } 1751 1752 SBP_LOCK(sc); 1753 if (xpt_bus_register(sc->sim, dev, /*bus*/0) != CAM_SUCCESS) 1754 goto fail; 1755 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)); 1759 goto fail; 1760 } 1761 SBP_UNLOCK(sc); 1762 1763 sc->fwb.start = SBP_TARG_BIND_START; 1764 sc->fwb.end = SBP_TARG_BIND_END; 1765 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); 1772 return 0; 1773 1774 fail: 1775 SBP_UNLOCK(sc); 1776 cam_sim_free(sc->sim, /*free_devq*/TRUE); 1777 return (ENXIO); 1778 } 1779 1780 static int 1781 sbp_targ_detach(device_t dev) 1782 { 1783 struct sbp_targ_softc *sc; 1784 struct sbp_targ_lstate *lstate; 1785 int i; 1786 1787 sc = (struct sbp_targ_softc *)device_get_softc(dev); 1788 sc->fd.post_busreset = NULL; 1789 1790 SBP_LOCK(sc); 1791 xpt_free_path(sc->path); 1792 xpt_bus_deregister(cam_sim_path(sc->sim)); 1793 SBP_UNLOCK(sc); 1794 cam_sim_free(sc->sim, /*free_devq*/TRUE); 1795 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); 1801 } 1802 } 1803 if (sc->black_hole != NULL) { 1804 xpt_free_path(sc->black_hole->path); 1805 free(sc->black_hole, M_SBP_TARG); 1806 } 1807 1808 fw_bindremove(sc->fd.fc, &sc->fwb); 1809 fw_xferlist_remove(&sc->fwb.xferlist); 1810 1811 mtx_destroy(&sc->mtx); 1812 1813 return 0; 1814 } 1815 1816 static devclass_t sbp_targ_devclass; 1817 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), 1824 { 0, 0 } 1825 }; 1826 1827 static driver_t sbp_targ_driver = { 1828 "sbp_targ", 1829 sbp_targ_methods, 1830 sizeof(struct sbp_targ_softc), 1831 }; 1832 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); 1837