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