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