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