1139749Simp/*- 2122526Ssimokawa * Copyright (c) 2003 Hidetoshi Shimokawa 3122526Ssimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 4103285Sikob * All rights reserved. 5103285Sikob * 6103285Sikob * Redistribution and use in source and binary forms, with or without 7103285Sikob * modification, are permitted provided that the following conditions 8103285Sikob * are met: 9103285Sikob * 1. Redistributions of source code must retain the above copyright 10103285Sikob * notice, this list of conditions and the following disclaimer. 11103285Sikob * 2. Redistributions in binary form must reproduce the above copyright 12103285Sikob * notice, this list of conditions and the following disclaimer in the 13103285Sikob * documentation and/or other materials provided with the distribution. 14103285Sikob * 3. All advertising materials mentioning features or use of this software 15103285Sikob * must display the acknowledgement as bellow: 16103285Sikob * 17103285Sikob * This product includes software developed by K. Kobayashi and H. Shimokawa 18103285Sikob * 19103285Sikob * 4. The name of the author may not be used to endorse or promote products 20103285Sikob * derived from this software without specific prior written permission. 21103285Sikob * 22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23103285Sikob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24103285Sikob * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25103285Sikob * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26103285Sikob * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27103285Sikob * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28103285Sikob * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30103285Sikob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31103285Sikob * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32103285Sikob * POSSIBILITY OF SUCH DAMAGE. 33272214Skan * 34103285Sikob * $FreeBSD: releng/11.0/sys/dev/firewire/sbp.c 274819 2014-11-21 21:01:24Z smh $ 35103285Sikob * 36103285Sikob */ 37103285Sikob 38103285Sikob#include <sys/param.h> 39103285Sikob#include <sys/systm.h> 40103285Sikob#include <sys/module.h> 41103285Sikob#include <sys/bus.h> 42127468Ssimokawa#include <sys/kernel.h> 43103285Sikob#include <sys/sysctl.h> 44103285Sikob#include <machine/bus.h> 45103285Sikob#include <sys/malloc.h> 46117126Sscottl#include <sys/lock.h> 47117126Sscottl#include <sys/mutex.h> 48103285Sikob 49103285Sikob#include <cam/cam.h> 50103285Sikob#include <cam/cam_ccb.h> 51103285Sikob#include <cam/cam_sim.h> 52103285Sikob#include <cam/cam_xpt_sim.h> 53103285Sikob#include <cam/cam_debug.h> 54103285Sikob#include <cam/cam_periph.h> 55103285Sikob#include <cam/scsi/scsi_all.h> 56103285Sikob 57103285Sikob#include <dev/firewire/firewire.h> 58103285Sikob#include <dev/firewire/firewirereg.h> 59113584Ssimokawa#include <dev/firewire/fwdma.h> 60103285Sikob#include <dev/firewire/iec13213.h> 61120660Ssimokawa#include <dev/firewire/sbp.h> 62103285Sikob 63103285Sikob#define ccb_sdev_ptr spriv_ptr0 64103285Sikob#define ccb_sbp_ptr spriv_ptr1 65103285Sikob 66111615Ssimokawa#define SBP_NUM_TARGETS 8 /* MAX 64 */ 67121185Ssimokawa/* 68121185Ssimokawa * Scan_bus doesn't work for more than 8 LUNs 69121185Ssimokawa * because of CAM_SCSI2_MAXLUN in cam_xpt.c 70121185Ssimokawa */ 71121185Ssimokawa#define SBP_NUM_LUNS 64 72167622Ssimokawa#define SBP_MAXPHYS MIN(MAXPHYS, (512*1024) /* 512KB */) 73113584Ssimokawa#define SBP_DMA_SIZE PAGE_SIZE 74113584Ssimokawa#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res) 75113584Ssimokawa#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb)) 76103285Sikob#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) 77113584Ssimokawa 78272214Skan/* 79111615Ssimokawa * STATUS FIFO addressing 80111615Ssimokawa * bit 81272214Skan *----------------------- 82130532Sdfr * 0- 1( 2): 0 (alignment) 83111615Ssimokawa * 2- 7( 6): target 84111615Ssimokawa * 8-15( 8): lun 85120660Ssimokawa * 16-31( 8): reserved 86272214Skan * 32-47(16): SBP_BIND_HI 87272214Skan * 48-64(16): bus_id, node_id 88111615Ssimokawa */ 89103285Sikob#define SBP_BIND_HI 0x1 90120660Ssimokawa#define SBP_DEV2ADDR(t, l) \ 91120660Ssimokawa (((u_int64_t)SBP_BIND_HI << 32) \ 92120660Ssimokawa | (((l) & 0xff) << 8) \ 93120660Ssimokawa | (((t) & 0x3f) << 2)) 94103285Sikob#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f) 95103285Sikob#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff) 96120660Ssimokawa#define SBP_INITIATOR 7 97103285Sikob 98103285Sikobstatic char *orb_fun_name[] = { 99120660Ssimokawa ORB_FUN_NAMES 100103285Sikob}; 101103285Sikob 102111203Ssimokawastatic int debug = 0; 103103285Sikobstatic int auto_login = 1; 104124251Ssimokawastatic int max_speed = -1; 105111199Ssimokawastatic int sbp_cold = 1; 106122387Ssimokawastatic int ex_login = 1; 107122387Ssimokawastatic int login_delay = 1000; /* msec */ 108122387Ssimokawastatic int scan_delay = 500; /* msec */ 109127468Ssimokawastatic int use_doorbell = 0; 110127468Ssimokawastatic int sbp_tags = 0; 111103285Sikob 112103285SikobSYSCTL_DECL(_hw_firewire); 113227309Sedstatic SYSCTL_NODE(_hw_firewire, OID_AUTO, sbp, CTLFLAG_RD, 0, 114227309Sed "SBP-II Subsystem"); 115267992ShselaskySYSCTL_INT(_debug, OID_AUTO, sbp_debug, CTLFLAG_RWTUN, &debug, 0, 116103285Sikob "SBP debug flag"); 117267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RWTUN, &auto_login, 0, 118103285Sikob "SBP perform login automatically"); 119267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RWTUN, &max_speed, 0, 120103285Sikob "SBP transfer max speed"); 121267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, exclusive_login, CTLFLAG_RWTUN, 122130677Ssimokawa &ex_login, 0, "SBP enable exclusive login"); 123267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, login_delay, CTLFLAG_RWTUN, 124122387Ssimokawa &login_delay, 0, "SBP login delay in msec"); 125267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, scan_delay, CTLFLAG_RWTUN, 126122387Ssimokawa &scan_delay, 0, "SBP scan delay in msec"); 127267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, use_doorbell, CTLFLAG_RWTUN, 128127468Ssimokawa &use_doorbell, 0, "SBP use doorbell request"); 129267992ShselaskySYSCTL_INT(_hw_firewire_sbp, OID_AUTO, tags, CTLFLAG_RWTUN, &sbp_tags, 0, 130127468Ssimokawa "SBP tagged queuing support"); 131103285Sikob 132103285Sikob#define NEED_RESPONSE 0 133103285Sikob 134113584Ssimokawa#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE) 135113584Ssimokawa#ifdef __sparc64__ /* iommu */ 136167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, SBP_SEG_MAX) 137113584Ssimokawa#else 138167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, PAGE_SIZE) 139113584Ssimokawa#endif 140103285Sikobstruct sbp_ocb { 141103285Sikob STAILQ_ENTRY(sbp_ocb) ocb; 142103285Sikob union ccb *ccb; 143113584Ssimokawa bus_addr_t bus_addr; 144129585Sdfr uint32_t orb[8]; 145129585Sdfr#define IND_PTR_OFFSET (8*sizeof(uint32_t)) 146120660Ssimokawa struct ind_ptr ind_ptr[SBP_IND_MAX]; 147103285Sikob struct sbp_dev *sdev; 148113584Ssimokawa int flags; /* XXX should be removed */ 149103285Sikob bus_dmamap_t dmamap; 150266772Sjhb struct callout timer; 151103285Sikob}; 152113584Ssimokawa 153103285Sikob#define OCB_ACT_MGM 0 154103285Sikob#define OCB_ACT_CMD 1 155113584Ssimokawa#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo)) 156103285Sikob 157272214Skanstruct sbp_dev { 158103285Sikob#define SBP_DEV_RESET 0 /* accept login */ 159114732Ssimokawa#define SBP_DEV_LOGIN 1 /* to login */ 160110336Ssimokawa#if 0 161103285Sikob#define SBP_DEV_RECONN 2 /* to reconnect */ 162110336Ssimokawa#endif 163103285Sikob#define SBP_DEV_TOATTACH 3 /* to attach */ 164103285Sikob#define SBP_DEV_PROBE 4 /* scan lun */ 165103285Sikob#define SBP_DEV_ATTACHED 5 /* in operation */ 166103285Sikob#define SBP_DEV_DEAD 6 /* unavailable unit */ 167103285Sikob#define SBP_DEV_RETRY 7 /* unavailable unit */ 168129585Sdfr uint8_t status:4, 169114732Ssimokawa timeout:4; 170129585Sdfr uint8_t type; 171129585Sdfr uint16_t lun_id; 172129585Sdfr uint16_t freeze; 173121185Ssimokawa#define ORB_LINK_DEAD (1 << 0) 174121185Ssimokawa#define VALID_LUN (1 << 1) 175121185Ssimokawa#define ORB_POINTER_ACTIVE (1 << 2) 176121185Ssimokawa#define ORB_POINTER_NEED (1 << 3) 177127468Ssimokawa#define ORB_DOORBELL_ACTIVE (1 << 4) 178127468Ssimokawa#define ORB_DOORBELL_NEED (1 << 5) 179127468Ssimokawa#define ORB_SHORTAGE (1 << 6) 180129585Sdfr uint16_t flags; 181103285Sikob struct cam_path *path; 182103285Sikob struct sbp_target *target; 183113584Ssimokawa struct fwdma_alloc dma; 184113584Ssimokawa struct sbp_login_res *login; 185111615Ssimokawa struct callout login_callout; 186113584Ssimokawa struct sbp_ocb *ocb; 187103285Sikob STAILQ_HEAD(, sbp_ocb) ocbs; 188113584Ssimokawa STAILQ_HEAD(, sbp_ocb) free_ocbs; 189127468Ssimokawa struct sbp_ocb *last_ocb; 190103285Sikob char vendor[32]; 191103285Sikob char product[32]; 192103285Sikob char revision[10]; 193188756Ssbruno char bustgtlun[32]; 194103285Sikob}; 195103285Sikob 196103285Sikobstruct sbp_target { 197103285Sikob int target_id; 198103285Sikob int num_lun; 199121185Ssimokawa struct sbp_dev **luns; 200103285Sikob struct sbp_softc *sbp; 201103285Sikob struct fw_device *fwdev; 202129585Sdfr uint32_t mgm_hi, mgm_lo; 203111615Ssimokawa struct sbp_ocb *mgm_ocb_cur; 204111615Ssimokawa STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; 205111615Ssimokawa struct callout mgm_ocb_timeout; 206111615Ssimokawa struct callout scan_callout; 207113584Ssimokawa STAILQ_HEAD(, fw_xfer) xferlist; 208113584Ssimokawa int n_xfer; 209103285Sikob}; 210103285Sikob 211103285Sikobstruct sbp_softc { 212103285Sikob struct firewire_dev_comm fd; 213103285Sikob struct cam_sim *sim; 214111615Ssimokawa struct cam_path *path; 215103285Sikob struct sbp_target targets[SBP_NUM_TARGETS]; 216103285Sikob struct fw_bind fwb; 217103285Sikob bus_dma_tag_t dmat; 218122387Ssimokawa struct timeval last_busreset; 219124145Ssimokawa#define SIMQ_FREEZED 1 220124145Ssimokawa int flags; 221170374Ssimokawa struct mtx mtx; 222103285Sikob}; 223266772Sjhb#define SBP_LOCK(sbp) mtx_lock(&(sbp)->mtx) 224266772Sjhb#define SBP_UNLOCK(sbp) mtx_unlock(&(sbp)->mtx) 225266772Sjhb#define SBP_LOCK_ASSERT(sbp) mtx_assert(&(sbp)->mtx, MA_OWNED) 226122387Ssimokawa 227124169Ssimokawastatic void sbp_post_explore (void *); 228124169Ssimokawastatic void sbp_recv (struct fw_xfer *); 229124169Ssimokawastatic void sbp_mgm_callback (struct fw_xfer *); 230121185Ssimokawa#if 0 231124169Ssimokawastatic void sbp_cmd_callback (struct fw_xfer *); 232121185Ssimokawa#endif 233124169Ssimokawastatic void sbp_orb_pointer (struct sbp_dev *, struct sbp_ocb *); 234127468Ssimokawastatic void sbp_doorbell(struct sbp_dev *); 235272214Skanstatic void sbp_execute_ocb (void *, bus_dma_segment_t *, int, int); 236124169Ssimokawastatic void sbp_free_ocb (struct sbp_dev *, struct sbp_ocb *); 237124169Ssimokawastatic void sbp_abort_ocb (struct sbp_ocb *, int); 238124169Ssimokawastatic void sbp_abort_all_ocbs (struct sbp_dev *, int); 239124169Ssimokawastatic struct fw_xfer * sbp_write_cmd (struct sbp_dev *, int, int); 240124169Ssimokawastatic struct sbp_ocb * sbp_get_ocb (struct sbp_dev *); 241124169Ssimokawastatic struct sbp_ocb * sbp_enqueue_ocb (struct sbp_dev *, struct sbp_ocb *); 242124169Ssimokawastatic struct sbp_ocb * sbp_dequeue_ocb (struct sbp_dev *, struct sbp_status *); 243121185Ssimokawastatic void sbp_cam_detach_sdev(struct sbp_dev *); 244121185Ssimokawastatic void sbp_free_sdev(struct sbp_dev *); 245124169Ssimokawastatic void sbp_cam_detach_target (struct sbp_target *); 246124169Ssimokawastatic void sbp_free_target (struct sbp_target *); 247124169Ssimokawastatic void sbp_mgm_timeout (void *arg); 248124169Ssimokawastatic void sbp_timeout (void *arg); 249124169Ssimokawastatic void sbp_mgm_orb (struct sbp_dev *, int, struct sbp_ocb *); 250103285Sikob 251227293Sedstatic MALLOC_DEFINE(M_SBP, "sbp", "SBP-II/FireWire"); 252103285Sikob 253103285Sikob/* cam related functions */ 254103285Sikobstatic void sbp_action(struct cam_sim *sim, union ccb *ccb); 255103285Sikobstatic void sbp_poll(struct cam_sim *sim); 256111615Ssimokawastatic void sbp_cam_scan_lun(struct cam_periph *, union ccb *); 257111615Ssimokawastatic void sbp_cam_scan_target(void *arg); 258103285Sikob 259103285Sikobstatic char *orb_status0[] = { 260103285Sikob /* 0 */ "No additional information to report", 261103285Sikob /* 1 */ "Request type not supported", 262103285Sikob /* 2 */ "Speed not supported", 263103285Sikob /* 3 */ "Page size not supported", 264103285Sikob /* 4 */ "Access denied", 265103285Sikob /* 5 */ "Logical unit not supported", 266103285Sikob /* 6 */ "Maximum payload too small", 267103285Sikob /* 7 */ "Reserved for future standardization", 268103285Sikob /* 8 */ "Resources unavailable", 269103285Sikob /* 9 */ "Function rejected", 270103285Sikob /* A */ "Login ID not recognized", 271103285Sikob /* B */ "Dummy ORB completed", 272103285Sikob /* C */ "Request aborted", 273103285Sikob /* FF */ "Unspecified error" 274103285Sikob#define MAX_ORB_STATUS0 0xd 275103285Sikob}; 276103285Sikob 277103285Sikobstatic char *orb_status1_object[] = { 278103285Sikob /* 0 */ "Operation request block (ORB)", 279103285Sikob /* 1 */ "Data buffer", 280103285Sikob /* 2 */ "Page table", 281103285Sikob /* 3 */ "Unable to specify" 282103285Sikob}; 283103285Sikob 284103285Sikobstatic char *orb_status1_serial_bus_error[] = { 285103285Sikob /* 0 */ "Missing acknowledge", 286103285Sikob /* 1 */ "Reserved; not to be used", 287103285Sikob /* 2 */ "Time-out error", 288103285Sikob /* 3 */ "Reserved; not to be used", 289103285Sikob /* 4 */ "Busy retry limit exceeded(X)", 290103285Sikob /* 5 */ "Busy retry limit exceeded(A)", 291103285Sikob /* 6 */ "Busy retry limit exceeded(B)", 292103285Sikob /* 7 */ "Reserved for future standardization", 293103285Sikob /* 8 */ "Reserved for future standardization", 294103285Sikob /* 9 */ "Reserved for future standardization", 295103285Sikob /* A */ "Reserved for future standardization", 296103285Sikob /* B */ "Tardy retry limit exceeded", 297103285Sikob /* C */ "Conflict error", 298103285Sikob /* D */ "Data error", 299103285Sikob /* E */ "Type error", 300103285Sikob /* F */ "Address error" 301103285Sikob}; 302103285Sikob 303103285Sikobstatic void 304103285Sikobsbp_identify(driver_t *driver, device_t parent) 305103285Sikob{ 306103285SikobSBP_DEBUG(0) 307103285Sikob printf("sbp_identify\n"); 308103285SikobEND_DEBUG 309103285Sikob 310266772Sjhb if (device_find_child(parent, "sbp", -1) == NULL) 311266772Sjhb BUS_ADD_CHILD(parent, 0, "sbp", -1); 312103285Sikob} 313103285Sikob 314103285Sikob/* 315103285Sikob * sbp_probe() 316103285Sikob */ 317103285Sikobstatic int 318103285Sikobsbp_probe(device_t dev) 319103285Sikob{ 320103285Sikob 321103285SikobSBP_DEBUG(0) 322103285Sikob printf("sbp_probe\n"); 323103285SikobEND_DEBUG 324103285Sikob 325120660Ssimokawa device_set_desc(dev, "SBP-2/SCSI over FireWire"); 326111615Ssimokawa 327132432Ssimokawa#if 0 328111615Ssimokawa if (bootverbose) 329111615Ssimokawa debug = bootverbose; 330132432Ssimokawa#endif 331132432Ssimokawa 332103285Sikob return (0); 333103285Sikob} 334103285Sikob 335188756Ssbruno/* 336188756Ssbruno * Display device characteristics on the console 337188756Ssbruno */ 338103285Sikobstatic void 339188756Ssbrunosbp_show_sdev_info(struct sbp_dev *sdev) 340103285Sikob{ 341103285Sikob struct fw_device *fwdev; 342103285Sikob 343103285Sikob fwdev = sdev->target->fwdev; 344188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 345188756Ssbruno "%s: %s: ordered:%d type:%d EUI:%08x%08x node:%d " 346188756Ssbruno "speed:%d maxrec:%d\n", 347188756Ssbruno __func__, 348188756Ssbruno sdev->bustgtlun, 349108503Ssimokawa (sdev->type & 0x40) >> 6, 350108503Ssimokawa (sdev->type & 0x1f), 351103285Sikob fwdev->eui.hi, 352103285Sikob fwdev->eui.lo, 353103285Sikob fwdev->dst, 354103285Sikob fwdev->speed, 355188756Ssbruno fwdev->maxrec); 356188756Ssbruno 357188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 358188756Ssbruno "%s: %s '%s' '%s' '%s'\n", 359188756Ssbruno __func__, 360188756Ssbruno sdev->bustgtlun, 361188756Ssbruno sdev->vendor, 362188756Ssbruno sdev->product, 363188756Ssbruno sdev->revision); 364103285Sikob} 365103285Sikob 366110184Ssimokawastatic struct { 367110184Ssimokawa int bus; 368110184Ssimokawa int target; 369110184Ssimokawa struct fw_eui64 eui; 370110184Ssimokawa} wired[] = { 371110184Ssimokawa /* Bus Target EUI64 */ 372110184Ssimokawa#if 0 373110184Ssimokawa {0, 2, {0x00018ea0, 0x01fd0154}}, /* Logitec HDD */ 374110184Ssimokawa {0, 0, {0x00018ea6, 0x00100682}}, /* Logitec DVD */ 375110184Ssimokawa {0, 1, {0x00d03200, 0xa412006a}}, /* Yano HDD */ 376110184Ssimokawa#endif 377110184Ssimokawa {-1, -1, {0,0}} 378110184Ssimokawa}; 379110184Ssimokawa 380110184Ssimokawastatic int 381110184Ssimokawasbp_new_target(struct sbp_softc *sbp, struct fw_device *fwdev) 382110184Ssimokawa{ 383110184Ssimokawa int bus, i, target=-1; 384110184Ssimokawa char w[SBP_NUM_TARGETS]; 385110184Ssimokawa 386110184Ssimokawa bzero(w, sizeof(w)); 387110184Ssimokawa bus = device_get_unit(sbp->fd.dev); 388110184Ssimokawa 389110184Ssimokawa /* XXX wired-down configuration should be gotten from 390110184Ssimokawa tunable or device hint */ 391272214Skan for (i = 0; wired[i].bus >= 0; i++) { 392110184Ssimokawa if (wired[i].bus == bus) { 393110184Ssimokawa w[wired[i].target] = 1; 394110184Ssimokawa if (wired[i].eui.hi == fwdev->eui.hi && 395110184Ssimokawa wired[i].eui.lo == fwdev->eui.lo) 396110184Ssimokawa target = wired[i].target; 397110184Ssimokawa } 398110184Ssimokawa } 399110184Ssimokawa if (target >= 0) { 400272214Skan if (target < SBP_NUM_TARGETS && 401110184Ssimokawa sbp->targets[target].fwdev == NULL) 402272214Skan return (target); 403110184Ssimokawa device_printf(sbp->fd.dev, 404272214Skan "target %d is not free for %08x:%08x\n", 405110184Ssimokawa target, fwdev->eui.hi, fwdev->eui.lo); 406110184Ssimokawa target = -1; 407110184Ssimokawa } 408110184Ssimokawa /* non-wired target */ 409272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) 410110184Ssimokawa if (sbp->targets[i].fwdev == NULL && w[i] == 0) { 411110184Ssimokawa target = i; 412110184Ssimokawa break; 413110184Ssimokawa } 414110184Ssimokawa 415110184Ssimokawa return target; 416110184Ssimokawa} 417110184Ssimokawa 418121185Ssimokawastatic void 419121185Ssimokawasbp_alloc_lun(struct sbp_target *target) 420103285Sikob{ 421108503Ssimokawa struct crom_context cc; 422108503Ssimokawa struct csrreg *reg; 423121185Ssimokawa struct sbp_dev *sdev, **newluns; 424121185Ssimokawa struct sbp_softc *sbp; 425121185Ssimokawa int maxlun, lun, i; 426103285Sikob 427121185Ssimokawa sbp = target->sbp; 428266772Sjhb SBP_LOCK_ASSERT(sbp); 429114069Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 430108503Ssimokawa /* XXX shoud parse appropriate unit directories only */ 431108503Ssimokawa maxlun = -1; 432108503Ssimokawa while (cc.depth >= 0) { 433108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 434108503Ssimokawa if (reg == NULL) 435108503Ssimokawa break; 436110839Ssimokawa lun = reg->val & 0xffff; 437108642SsimokawaSBP_DEBUG(0) 438108642Ssimokawa printf("target %d lun %d found\n", target->target_id, lun); 439108642SsimokawaEND_DEBUG 440108503Ssimokawa if (maxlun < lun) 441108503Ssimokawa maxlun = lun; 442108503Ssimokawa crom_next(&cc); 443108503Ssimokawa } 444110839Ssimokawa if (maxlun < 0) 445266772Sjhb device_printf(target->sbp->fd.dev, "%d no LUN found\n", 446121185Ssimokawa target->target_id); 447121185Ssimokawa 448272214Skan maxlun++; 449110839Ssimokawa if (maxlun >= SBP_NUM_LUNS) 450110839Ssimokawa maxlun = SBP_NUM_LUNS; 451121185Ssimokawa 452121185Ssimokawa /* Invalidiate stale devices */ 453272214Skan for (lun = 0; lun < target->num_lun; lun++) { 454121185Ssimokawa sdev = target->luns[lun]; 455121185Ssimokawa if (sdev == NULL) 456121185Ssimokawa continue; 457121185Ssimokawa sdev->flags &= ~VALID_LUN; 458121185Ssimokawa if (lun >= maxlun) { 459121185Ssimokawa /* lost device */ 460121185Ssimokawa sbp_cam_detach_sdev(sdev); 461121185Ssimokawa sbp_free_sdev(sdev); 462187993Ssbruno target->luns[lun] = NULL; 463121185Ssimokawa } 464103285Sikob } 465121185Ssimokawa 466121185Ssimokawa /* Reallocate */ 467121185Ssimokawa if (maxlun != target->num_lun) { 468121185Ssimokawa newluns = (struct sbp_dev **) realloc(target->luns, 469121185Ssimokawa sizeof(struct sbp_dev *) * maxlun, 470121185Ssimokawa M_SBP, M_NOWAIT | M_ZERO); 471272214Skan 472121185Ssimokawa if (newluns == NULL) { 473127468Ssimokawa printf("%s: realloc failed\n", __func__); 474121185Ssimokawa newluns = target->luns; 475121185Ssimokawa maxlun = target->num_lun; 476121185Ssimokawa } 477121185Ssimokawa 478121185Ssimokawa /* 479121185Ssimokawa * We must zero the extended region for the case 480121185Ssimokawa * realloc() doesn't allocate new buffer. 481121185Ssimokawa */ 482121185Ssimokawa if (maxlun > target->num_lun) 483121185Ssimokawa bzero(&newluns[target->num_lun], 484121185Ssimokawa sizeof(struct sbp_dev *) * 485121185Ssimokawa (maxlun - target->num_lun)); 486121185Ssimokawa 487121185Ssimokawa target->luns = newluns; 488121185Ssimokawa target->num_lun = maxlun; 489121185Ssimokawa } 490121185Ssimokawa 491108503Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 492108503Ssimokawa while (cc.depth >= 0) { 493121185Ssimokawa int new = 0; 494121185Ssimokawa 495108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 496108503Ssimokawa if (reg == NULL) 497108503Ssimokawa break; 498110839Ssimokawa lun = reg->val & 0xffff; 499110839Ssimokawa if (lun >= SBP_NUM_LUNS) { 500110839Ssimokawa printf("too large lun %d\n", lun); 501121185Ssimokawa goto next; 502110839Ssimokawa } 503121185Ssimokawa 504121185Ssimokawa sdev = target->luns[lun]; 505121185Ssimokawa if (sdev == NULL) { 506121185Ssimokawa sdev = malloc(sizeof(struct sbp_dev), 507121185Ssimokawa M_SBP, M_NOWAIT | M_ZERO); 508121185Ssimokawa if (sdev == NULL) { 509127468Ssimokawa printf("%s: malloc failed\n", __func__); 510121185Ssimokawa goto next; 511121185Ssimokawa } 512121185Ssimokawa target->luns[lun] = sdev; 513121185Ssimokawa sdev->lun_id = lun; 514121185Ssimokawa sdev->target = target; 515121185Ssimokawa STAILQ_INIT(&sdev->ocbs); 516266772Sjhb callout_init_mtx(&sdev->login_callout, &sbp->mtx, 0); 517121185Ssimokawa sdev->status = SBP_DEV_RESET; 518121185Ssimokawa new = 1; 519188756Ssbruno snprintf(sdev->bustgtlun, 32, "%s:%d:%d", 520188756Ssbruno device_get_nameunit(sdev->target->sbp->fd.dev), 521188756Ssbruno sdev->target->target_id, 522188756Ssbruno sdev->lun_id); 523121185Ssimokawa } 524121185Ssimokawa sdev->flags |= VALID_LUN; 525119196Ssimokawa sdev->type = (reg->val & 0xff0000) >> 16; 526113584Ssimokawa 527121185Ssimokawa if (new == 0) 528121185Ssimokawa goto next; 529121185Ssimokawa 530272214Skan fwdma_malloc(sbp->fd.fc, 531129585Sdfr /* alignment */ sizeof(uint32_t), 532219543Smarius SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT | 533219543Smarius BUS_DMA_COHERENT); 534113584Ssimokawa if (sdev->dma.v_addr == NULL) { 535113584Ssimokawa printf("%s: dma space allocation failed\n", 536127468Ssimokawa __func__); 537121185Ssimokawa free(sdev, M_SBP); 538121185Ssimokawa target->luns[lun] = NULL; 539121185Ssimokawa goto next; 540113584Ssimokawa } 541113584Ssimokawa sdev->login = (struct sbp_login_res *) sdev->dma.v_addr; 542113584Ssimokawa sdev->ocb = (struct sbp_ocb *) 543113584Ssimokawa ((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE); 544113584Ssimokawa bzero((char *)sdev->ocb, 545272214Skan sizeof(struct sbp_ocb) * SBP_QUEUE_LEN); 546113584Ssimokawa 547113584Ssimokawa STAILQ_INIT(&sdev->free_ocbs); 548113584Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) { 549113584Ssimokawa struct sbp_ocb *ocb; 550113584Ssimokawa ocb = &sdev->ocb[i]; 551113584Ssimokawa ocb->bus_addr = sdev->dma.bus_addr 552113584Ssimokawa + SBP_LOGIN_SIZE 553113584Ssimokawa + sizeof(struct sbp_ocb) * i 554113584Ssimokawa + offsetof(struct sbp_ocb, orb[0]); 555113584Ssimokawa if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) { 556113584Ssimokawa printf("sbp_attach: cannot create dmamap\n"); 557121185Ssimokawa /* XXX */ 558121185Ssimokawa goto next; 559113584Ssimokawa } 560266772Sjhb callout_init_mtx(&ocb->timer, &sbp->mtx, 0); 561113584Ssimokawa sbp_free_ocb(sdev, ocb); 562113584Ssimokawa } 563121185Ssimokawanext: 564108503Ssimokawa crom_next(&cc); 565103285Sikob } 566121185Ssimokawa 567272214Skan for (lun = 0; lun < target->num_lun; lun++) { 568121185Ssimokawa sdev = target->luns[lun]; 569121185Ssimokawa if (sdev != NULL && (sdev->flags & VALID_LUN) == 0) { 570121185Ssimokawa sbp_cam_detach_sdev(sdev); 571121185Ssimokawa sbp_free_sdev(sdev); 572121185Ssimokawa target->luns[lun] = NULL; 573121185Ssimokawa } 574121185Ssimokawa } 575121185Ssimokawa} 576121185Ssimokawa 577121185Ssimokawastatic struct sbp_target * 578121185Ssimokawasbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev) 579121185Ssimokawa{ 580121185Ssimokawa int i; 581121185Ssimokawa struct sbp_target *target; 582121185Ssimokawa struct crom_context cc; 583121185Ssimokawa struct csrreg *reg; 584121185Ssimokawa 585121185SsimokawaSBP_DEBUG(1) 586121185Ssimokawa printf("sbp_alloc_target\n"); 587121185SsimokawaEND_DEBUG 588121185Ssimokawa i = sbp_new_target(sbp, fwdev); 589121185Ssimokawa if (i < 0) { 590121185Ssimokawa device_printf(sbp->fd.dev, "increase SBP_NUM_TARGETS!\n"); 591121185Ssimokawa return NULL; 592121185Ssimokawa } 593121185Ssimokawa /* new target */ 594121185Ssimokawa target = &sbp->targets[i]; 595121185Ssimokawa target->fwdev = fwdev; 596121185Ssimokawa target->target_id = i; 597121185Ssimokawa /* XXX we may want to reload mgm port after each bus reset */ 598121185Ssimokawa /* XXX there might be multiple management agents */ 599121185Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 600121185Ssimokawa reg = crom_search_key(&cc, CROM_MGM); 601121185Ssimokawa if (reg == NULL || reg->val == 0) { 602121185Ssimokawa printf("NULL management address\n"); 603121185Ssimokawa target->fwdev = NULL; 604121185Ssimokawa return NULL; 605121185Ssimokawa } 606121185Ssimokawa target->mgm_hi = 0xffff; 607121185Ssimokawa target->mgm_lo = 0xf0000000 | (reg->val << 2); 608121185Ssimokawa target->mgm_ocb_cur = NULL; 609121185SsimokawaSBP_DEBUG(1) 610121185Ssimokawa printf("target:%d mgm_port: %x\n", i, target->mgm_lo); 611121185SsimokawaEND_DEBUG 612121185Ssimokawa STAILQ_INIT(&target->xferlist); 613121185Ssimokawa target->n_xfer = 0; 614121185Ssimokawa STAILQ_INIT(&target->mgm_ocb_queue); 615266772Sjhb callout_init_mtx(&target->mgm_ocb_timeout, &sbp->mtx, 0); 616266772Sjhb callout_init_mtx(&target->scan_callout, &sbp->mtx, 0); 617121185Ssimokawa 618121185Ssimokawa target->luns = NULL; 619121185Ssimokawa target->num_lun = 0; 620114069Ssimokawa return target; 621103285Sikob} 622103285Sikob 623103285Sikobstatic void 624103285Sikobsbp_probe_lun(struct sbp_dev *sdev) 625103285Sikob{ 626103285Sikob struct fw_device *fwdev; 627114069Ssimokawa struct crom_context c, *cc = &c; 628114069Ssimokawa struct csrreg *reg; 629103285Sikob 630103285Sikob bzero(sdev->vendor, sizeof(sdev->vendor)); 631103285Sikob bzero(sdev->product, sizeof(sdev->product)); 632114069Ssimokawa 633114069Ssimokawa fwdev = sdev->target->fwdev; 634114069Ssimokawa crom_init_context(cc, fwdev->csrrom); 635114069Ssimokawa /* get vendor string */ 636114069Ssimokawa crom_search_key(cc, CSRKEY_VENDOR); 637114069Ssimokawa crom_next(cc); 638114069Ssimokawa crom_parse_text(cc, sdev->vendor, sizeof(sdev->vendor)); 639114223Ssimokawa /* skip to the unit directory for SBP-2 */ 640114260Ssimokawa while ((reg = crom_search_key(cc, CSRKEY_VER)) != NULL) { 641114223Ssimokawa if (reg->val == CSRVAL_T10SBP2) 642114223Ssimokawa break; 643114260Ssimokawa crom_next(cc); 644114260Ssimokawa } 645114069Ssimokawa /* get firmware revision */ 646114069Ssimokawa reg = crom_search_key(cc, CSRKEY_FIRM_VER); 647114069Ssimokawa if (reg != NULL) 648114069Ssimokawa snprintf(sdev->revision, sizeof(sdev->revision), 649114069Ssimokawa "%06x", reg->val); 650114069Ssimokawa /* get product string */ 651114069Ssimokawa crom_search_key(cc, CSRKEY_MODEL); 652114069Ssimokawa crom_next(cc); 653114069Ssimokawa crom_parse_text(cc, sdev->product, sizeof(sdev->product)); 654103285Sikob} 655111615Ssimokawa 656103285Sikobstatic void 657111615Ssimokawasbp_login_callout(void *arg) 658103285Sikob{ 659111615Ssimokawa struct sbp_dev *sdev = (struct sbp_dev *)arg; 660266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 661111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL); 662111615Ssimokawa} 663111615Ssimokawa 664122387Ssimokawastatic void 665122387Ssimokawasbp_login(struct sbp_dev *sdev) 666122387Ssimokawa{ 667122387Ssimokawa struct timeval delta; 668122387Ssimokawa struct timeval t; 669122387Ssimokawa int ticks = 0; 670122387Ssimokawa 671122387Ssimokawa microtime(&delta); 672122387Ssimokawa timevalsub(&delta, &sdev->target->sbp->last_busreset); 673122387Ssimokawa t.tv_sec = login_delay / 1000; 674122387Ssimokawa t.tv_usec = (login_delay % 1000) * 1000; 675122387Ssimokawa timevalsub(&t, &delta); 676122387Ssimokawa if (t.tv_sec >= 0 && t.tv_usec > 0) 677122387Ssimokawa ticks = (t.tv_sec * 1000 + t.tv_usec / 1000) * hz / 1000; 678122387SsimokawaSBP_DEBUG(0) 679153706Strhodes printf("%s: sec = %jd usec = %ld ticks = %d\n", __func__, 680153706Strhodes (intmax_t)t.tv_sec, t.tv_usec, ticks); 681122387SsimokawaEND_DEBUG 682122387Ssimokawa callout_reset(&sdev->login_callout, ticks, 683122387Ssimokawa sbp_login_callout, (void *)(sdev)); 684122387Ssimokawa} 685122387Ssimokawa 686114069Ssimokawa#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ 687114069Ssimokawa && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) 688111615Ssimokawa 689111615Ssimokawastatic void 690111615Ssimokawasbp_probe_target(void *arg) 691111615Ssimokawa{ 692111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 693188756Ssbruno struct sbp_softc *sbp = target->sbp; 694103285Sikob struct sbp_dev *sdev; 695111615Ssimokawa int i, alive; 696103285Sikob 697111615Ssimokawa alive = SBP_FWDEV_ALIVE(target->fwdev); 698103285SikobSBP_DEBUG(1) 699188756Ssbruno device_printf(sbp->fd.dev, "%s %d%salive\n", 700188756Ssbruno __func__, target->target_id, 701188756Ssbruno (!alive) ? " not " : ""); 702103285SikobEND_DEBUG 703103285Sikob 704103285Sikob sbp = target->sbp; 705266772Sjhb SBP_LOCK_ASSERT(sbp); 706121185Ssimokawa sbp_alloc_lun(target); 707121185Ssimokawa 708111615Ssimokawa /* XXX untimeout mgm_ocb and dequeue */ 709103285Sikob for (i=0; i < target->num_lun; i++) { 710121185Ssimokawa sdev = target->luns[i]; 711121185Ssimokawa if (sdev == NULL) 712121185Ssimokawa continue; 713103285Sikob if (alive && (sdev->status != SBP_DEV_DEAD)) { 714103285Sikob if (sdev->path != NULL) { 715103285Sikob xpt_freeze_devq(sdev->path, 1); 716272214Skan sdev->freeze++; 717103285Sikob } 718111615Ssimokawa sbp_probe_lun(sdev); 719188756Ssbruno sbp_show_sdev_info(sdev); 720111615Ssimokawa 721111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 722103285Sikob switch (sdev->status) { 723110336Ssimokawa case SBP_DEV_RESET: 724103285Sikob /* new or revived target */ 725113584Ssimokawa if (auto_login) 726111615Ssimokawa sbp_login(sdev); 727103285Sikob break; 728111615Ssimokawa case SBP_DEV_TOATTACH: 729111615Ssimokawa case SBP_DEV_PROBE: 730111615Ssimokawa case SBP_DEV_ATTACHED: 731110336Ssimokawa case SBP_DEV_RETRY: 732110336Ssimokawa default: 733111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); 734110336Ssimokawa break; 735103285Sikob } 736103285Sikob } else { 737103285Sikob switch (sdev->status) { 738103285Sikob case SBP_DEV_ATTACHED: 739103285SikobSBP_DEBUG(0) 740103285Sikob /* the device has gone */ 741188756Ssbruno device_printf(sbp->fd.dev, "%s: lost target\n", 742188756Ssbruno __func__); 743103285SikobEND_DEBUG 744111615Ssimokawa if (sdev->path) { 745103285Sikob xpt_freeze_devq(sdev->path, 1); 746272214Skan sdev->freeze++; 747111615Ssimokawa } 748103285Sikob sdev->status = SBP_DEV_RETRY; 749187993Ssbruno sbp_cam_detach_sdev(sdev); 750187993Ssbruno sbp_free_sdev(sdev); 751187993Ssbruno target->luns[i] = NULL; 752103285Sikob break; 753103285Sikob case SBP_DEV_PROBE: 754103285Sikob case SBP_DEV_TOATTACH: 755103285Sikob sdev->status = SBP_DEV_RESET; 756103285Sikob break; 757103285Sikob case SBP_DEV_RETRY: 758103285Sikob case SBP_DEV_RESET: 759103285Sikob case SBP_DEV_DEAD: 760103285Sikob break; 761103285Sikob } 762103285Sikob } 763103285Sikob } 764103285Sikob} 765103285Sikob 766103285Sikobstatic void 767113584Ssimokawasbp_post_busreset(void *arg) 768113584Ssimokawa{ 769113584Ssimokawa struct sbp_softc *sbp; 770113584Ssimokawa 771113584Ssimokawa sbp = (struct sbp_softc *)arg; 772113584SsimokawaSBP_DEBUG(0) 773113584Ssimokawa printf("sbp_post_busreset\n"); 774113584SsimokawaEND_DEBUG 775266772Sjhb SBP_LOCK(sbp); 776124145Ssimokawa if ((sbp->sim->flags & SIMQ_FREEZED) == 0) { 777124145Ssimokawa xpt_freeze_simq(sbp->sim, /*count*/1); 778124145Ssimokawa sbp->sim->flags |= SIMQ_FREEZED; 779124145Ssimokawa } 780122387Ssimokawa microtime(&sbp->last_busreset); 781266772Sjhb SBP_UNLOCK(sbp); 782113584Ssimokawa} 783113584Ssimokawa 784113584Ssimokawastatic void 785103285Sikobsbp_post_explore(void *arg) 786103285Sikob{ 787103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)arg; 788103285Sikob struct sbp_target *target; 789103285Sikob struct fw_device *fwdev; 790103285Sikob int i, alive; 791103285Sikob 792111199SsimokawaSBP_DEBUG(0) 793111199Ssimokawa printf("sbp_post_explore (sbp_cold=%d)\n", sbp_cold); 794103285SikobEND_DEBUG 795170400Ssimokawa /* We need physical access */ 796170400Ssimokawa if (!firewire_phydma_enable) 797170400Ssimokawa return; 798170400Ssimokawa 799122387Ssimokawa if (sbp_cold > 0) 800272214Skan sbp_cold--; 801122387Ssimokawa 802266772Sjhb SBP_LOCK(sbp); 803122387Ssimokawa#if 0 804122387Ssimokawa /* 805122387Ssimokawa * XXX don't let CAM the bus rest. 806122387Ssimokawa * CAM tries to do something with freezed (DEV_RETRY) devices. 807111615Ssimokawa */ 808111615Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 809103285Sikob#endif 810111615Ssimokawa 811130532Sdfr /* Garbage Collection */ 812272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) { 813103285Sikob target = &sbp->targets[i]; 814110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) 815110193Ssimokawa if (target->fwdev == NULL || target->fwdev == fwdev) 816110193Ssimokawa break; 817121185Ssimokawa if (fwdev == NULL) { 818103285Sikob /* device has removed in lower driver */ 819110145Ssimokawa sbp_cam_detach_target(target); 820121185Ssimokawa sbp_free_target(target); 821103285Sikob } 822103285Sikob } 823103285Sikob /* traverse device list */ 824110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) { 825103285SikobSBP_DEBUG(0) 826188756Ssbruno device_printf(sbp->fd.dev,"%s:: EUI:%08x%08x %s attached, state=%d\n", 827188756Ssbruno __func__, fwdev->eui.hi, fwdev->eui.lo, 828188756Ssbruno (fwdev->status != FWDEVATTACHED) ? "not" : "", 829188756Ssbruno fwdev->status); 830103285SikobEND_DEBUG 831111615Ssimokawa alive = SBP_FWDEV_ALIVE(fwdev); 832272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) { 833103285Sikob target = &sbp->targets[i]; 834272214Skan if (target->fwdev == fwdev) { 835103285Sikob /* known target */ 836103285Sikob break; 837103285Sikob } 838103285Sikob } 839272214Skan if (i == SBP_NUM_TARGETS) { 840103285Sikob if (alive) { 841103285Sikob /* new target */ 842103285Sikob target = sbp_alloc_target(sbp, fwdev); 843103285Sikob if (target == NULL) 844103285Sikob continue; 845103285Sikob } else { 846103285Sikob continue; 847103285Sikob } 848103285Sikob } 849111615Ssimokawa sbp_probe_target((void *)target); 850121185Ssimokawa if (target->num_lun == 0) 851121185Ssimokawa sbp_free_target(target); 852103285Sikob } 853124145Ssimokawa xpt_release_simq(sbp->sim, /*run queue*/TRUE); 854124145Ssimokawa sbp->sim->flags &= ~SIMQ_FREEZED; 855170374Ssimokawa SBP_UNLOCK(sbp); 856103285Sikob} 857103285Sikob 858103285Sikob#if NEED_RESPONSE 859103285Sikobstatic void 860272214Skansbp_loginres_callback(struct fw_xfer *xfer) 861272214Skan{ 862103285Sikob struct sbp_dev *sdev; 863103285Sikob sdev = (struct sbp_dev *)xfer->sc; 864113584SsimokawaSBP_DEBUG(1) 865188756Ssbruno device_printf(sdev->target->sbp->fd.dev,"%s\n", __func__); 866103285SikobEND_DEBUG 867113584Ssimokawa /* recycle */ 868266772Sjhb SBP_LOCK(sdev->target->sbp); 869113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link); 870266772Sjhb SBP_UNLOCK(sdev->target->sbp); 871103285Sikob return; 872103285Sikob} 873103285Sikob#endif 874103285Sikob 875113584Ssimokawastatic __inline void 876113584Ssimokawasbp_xfer_free(struct fw_xfer *xfer) 877113584Ssimokawa{ 878113584Ssimokawa struct sbp_dev *sdev; 879113584Ssimokawa 880113584Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 881113584Ssimokawa fw_xfer_unload(xfer); 882266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 883113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); 884113584Ssimokawa} 885113584Ssimokawa 886103285Sikobstatic void 887114732Ssimokawasbp_reset_start_callback(struct fw_xfer *xfer) 888103285Sikob{ 889114732Ssimokawa struct sbp_dev *tsdev, *sdev = (struct sbp_dev *)xfer->sc; 890114732Ssimokawa struct sbp_target *target = sdev->target; 891114732Ssimokawa int i; 892114732Ssimokawa 893114732Ssimokawa if (xfer->resp != 0) { 894188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 895188756Ssbruno "%s: %s failed: resp=%d\n", __func__, sdev->bustgtlun, xfer->resp); 896114732Ssimokawa } 897114732Ssimokawa 898266772Sjhb SBP_LOCK(target->sbp); 899114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 900121185Ssimokawa tsdev = target->luns[i]; 901121185Ssimokawa if (tsdev != NULL && tsdev->status == SBP_DEV_LOGIN) 902121185Ssimokawa sbp_login(tsdev); 903114732Ssimokawa } 904266772Sjhb SBP_UNLOCK(target->sbp); 905114732Ssimokawa} 906114732Ssimokawa 907114732Ssimokawastatic void 908114732Ssimokawasbp_reset_start(struct sbp_dev *sdev) 909114732Ssimokawa{ 910114732Ssimokawa struct fw_xfer *xfer; 911114732Ssimokawa struct fw_pkt *fp; 912114732Ssimokawa 913114732SsimokawaSBP_DEBUG(0) 914188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 915188756Ssbruno "%s:%s\n", __func__,sdev->bustgtlun); 916114732SsimokawaEND_DEBUG 917114732Ssimokawa 918114732Ssimokawa xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 919167632Ssimokawa xfer->hand = sbp_reset_start_callback; 920120660Ssimokawa fp = &xfer->send.hdr; 921114732Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 922114732Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 923114732Ssimokawa fp->mode.wreqq.data = htonl(0xf); 924114732Ssimokawa fw_asyreq(xfer->fc, -1, xfer); 925114732Ssimokawa} 926114732Ssimokawa 927114732Ssimokawastatic void 928114732Ssimokawasbp_mgm_callback(struct fw_xfer *xfer) 929114732Ssimokawa{ 930103285Sikob struct sbp_dev *sdev; 931114732Ssimokawa int resp; 932114732Ssimokawa 933103285Sikob sdev = (struct sbp_dev *)xfer->sc; 934114732Ssimokawa 935114732SsimokawaSBP_DEBUG(1) 936188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 937188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 938103285SikobEND_DEBUG 939114732Ssimokawa resp = xfer->resp; 940266772Sjhb SBP_LOCK(sdev->target->sbp); 941113584Ssimokawa sbp_xfer_free(xfer); 942266772Sjhb SBP_UNLOCK(sdev->target->sbp); 943103285Sikob} 944103285Sikob 945111615Ssimokawastatic struct sbp_dev * 946111615Ssimokawasbp_next_dev(struct sbp_target *target, int lun) 947111615Ssimokawa{ 948121185Ssimokawa struct sbp_dev **sdevp; 949111615Ssimokawa int i; 950111615Ssimokawa 951121185Ssimokawa for (i = lun, sdevp = &target->luns[lun]; i < target->num_lun; 952121185Ssimokawa i++, sdevp++) 953121185Ssimokawa if (*sdevp != NULL && (*sdevp)->status == SBP_DEV_PROBE) 954272214Skan return (*sdevp); 955272214Skan return (NULL); 956111615Ssimokawa} 957111615Ssimokawa 958111615Ssimokawa#define SCAN_PRI 1 959103285Sikobstatic void 960111615Ssimokawasbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb) 961103285Sikob{ 962111615Ssimokawa struct sbp_target *target; 963103285Sikob struct sbp_dev *sdev; 964111615Ssimokawa 965103285Sikob sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr; 966111615Ssimokawa target = sdev->target; 967266772Sjhb SBP_LOCK_ASSERT(target->sbp); 968110269SsimokawaSBP_DEBUG(0) 969188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 970188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 971103285SikobEND_DEBUG 972111615Ssimokawa if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 973111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 974111615Ssimokawa } else { 975188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 976188756Ssbruno "%s:%s failed\n", __func__, sdev->bustgtlun); 977111615Ssimokawa } 978111615Ssimokawa sdev = sbp_next_dev(target, sdev->lun_id + 1); 979111615Ssimokawa if (sdev == NULL) { 980111615Ssimokawa free(ccb, M_SBP); 981111615Ssimokawa return; 982111615Ssimokawa } 983111615Ssimokawa /* reuse ccb */ 984111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 985111615Ssimokawa ccb->ccb_h.ccb_sdev_ptr = sdev; 986111615Ssimokawa xpt_action(ccb); 987111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 988111615Ssimokawa sdev->freeze = 1; 989103285Sikob} 990103285Sikob 991103285Sikobstatic void 992111615Ssimokawasbp_cam_scan_target(void *arg) 993103285Sikob{ 994111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 995111615Ssimokawa struct sbp_dev *sdev; 996110798Ssimokawa union ccb *ccb; 997103285Sikob 998266772Sjhb SBP_LOCK_ASSERT(target->sbp); 999111615Ssimokawa sdev = sbp_next_dev(target, 0); 1000111615Ssimokawa if (sdev == NULL) { 1001111615Ssimokawa printf("sbp_cam_scan_target: nothing to do for target%d\n", 1002111615Ssimokawa target->target_id); 1003110798Ssimokawa return; 1004110798Ssimokawa } 1005103285SikobSBP_DEBUG(0) 1006188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1007188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1008103285SikobEND_DEBUG 1009111615Ssimokawa ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO); 1010111615Ssimokawa if (ccb == NULL) { 1011111615Ssimokawa printf("sbp_cam_scan_target: malloc failed\n"); 1012111615Ssimokawa return; 1013111615Ssimokawa } 1014111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 1015103285Sikob ccb->ccb_h.func_code = XPT_SCAN_LUN; 1016111615Ssimokawa ccb->ccb_h.cbfcnp = sbp_cam_scan_lun; 1017111615Ssimokawa ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1018103285Sikob ccb->crcn.flags = CAM_FLAG_NONE; 1019103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 1020103285Sikob 1021103285Sikob /* The scan is in progress now. */ 1022111040Ssimokawa xpt_action(ccb); 1023111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1024111615Ssimokawa sdev->freeze = 1; 1025103285Sikob} 1026103285Sikob 1027111615Ssimokawastatic __inline void 1028111615Ssimokawasbp_scan_dev(struct sbp_dev *sdev) 1029111615Ssimokawa{ 1030111040Ssimokawa sdev->status = SBP_DEV_PROBE; 1031274819Ssmh callout_reset_sbt(&sdev->target->scan_callout, SBT_1MS * scan_delay, 0, 1032274819Ssmh sbp_cam_scan_target, (void *)sdev->target, 0); 1033103285Sikob} 1034103285Sikob 1035103285Sikobstatic void 1036103285Sikobsbp_do_attach(struct fw_xfer *xfer) 1037103285Sikob{ 1038103285Sikob struct sbp_dev *sdev; 1039111615Ssimokawa struct sbp_target *target; 1040111615Ssimokawa struct sbp_softc *sbp; 1041103285Sikob 1042103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1043111615Ssimokawa target = sdev->target; 1044111615Ssimokawa sbp = target->sbp; 1045266772Sjhb SBP_LOCK(sbp); 1046103285SikobSBP_DEBUG(0) 1047188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1048188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1049103285SikobEND_DEBUG 1050113584Ssimokawa sbp_xfer_free(xfer); 1051111199Ssimokawa 1052103285Sikob if (sdev->path == NULL) 1053249468Smav xpt_create_path(&sdev->path, NULL, 1054111615Ssimokawa cam_sim_path(target->sbp->sim), 1055111615Ssimokawa target->target_id, sdev->lun_id); 1056103285Sikob 1057111199Ssimokawa /* 1058111199Ssimokawa * Let CAM scan the bus if we are in the boot process. 1059111199Ssimokawa * XXX xpt_scan_bus cannot detect LUN larger than 0 1060266772Sjhb * if LUN 0 doesn't exist. 1061111199Ssimokawa */ 1062111199Ssimokawa if (sbp_cold > 0) { 1063111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1064266772Sjhb SBP_UNLOCK(sbp); 1065111199Ssimokawa return; 1066111199Ssimokawa } 1067111199Ssimokawa 1068111615Ssimokawa sbp_scan_dev(sdev); 1069266772Sjhb SBP_UNLOCK(sbp); 1070103285Sikob} 1071103285Sikob 1072103285Sikobstatic void 1073103285Sikobsbp_agent_reset_callback(struct fw_xfer *xfer) 1074103285Sikob{ 1075103285Sikob struct sbp_dev *sdev; 1076103285Sikob 1077103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1078103285SikobSBP_DEBUG(1) 1079188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1080188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1081103285SikobEND_DEBUG 1082114732Ssimokawa if (xfer->resp != 0) { 1083188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1084188756Ssbruno "%s:%s resp=%d\n", __func__, sdev->bustgtlun, xfer->resp); 1085114732Ssimokawa } 1086114732Ssimokawa 1087266772Sjhb SBP_LOCK(sdev->target->sbp); 1088113584Ssimokawa sbp_xfer_free(xfer); 1089111615Ssimokawa if (sdev->path) { 1090111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1091111615Ssimokawa sdev->freeze = 0; 1092111615Ssimokawa } 1093266772Sjhb SBP_UNLOCK(sdev->target->sbp); 1094103285Sikob} 1095103285Sikob 1096103285Sikobstatic void 1097110336Ssimokawasbp_agent_reset(struct sbp_dev *sdev) 1098103285Sikob{ 1099103285Sikob struct fw_xfer *xfer; 1100103285Sikob struct fw_pkt *fp; 1101103285Sikob 1102266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 1103103285SikobSBP_DEBUG(0) 1104188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1105188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1106103285SikobEND_DEBUG 1107103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04); 1108103285Sikob if (xfer == NULL) 1109103285Sikob return; 1110115788Ssimokawa if (sdev->status == SBP_DEV_ATTACHED || sdev->status == SBP_DEV_PROBE) 1111167632Ssimokawa xfer->hand = sbp_agent_reset_callback; 1112110336Ssimokawa else 1113167632Ssimokawa xfer->hand = sbp_do_attach; 1114120660Ssimokawa fp = &xfer->send.hdr; 1115103285Sikob fp->mode.wreqq.data = htonl(0xf); 1116103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1117111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_BDR_SENT); 1118103285Sikob} 1119103285Sikob 1120103285Sikobstatic void 1121103285Sikobsbp_busy_timeout_callback(struct fw_xfer *xfer) 1122103285Sikob{ 1123103285Sikob struct sbp_dev *sdev; 1124103285Sikob 1125103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1126103285SikobSBP_DEBUG(1) 1127188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1128188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1129103285SikobEND_DEBUG 1130266772Sjhb SBP_LOCK(sdev->target->sbp); 1131113584Ssimokawa sbp_xfer_free(xfer); 1132110336Ssimokawa sbp_agent_reset(sdev); 1133266772Sjhb SBP_UNLOCK(sdev->target->sbp); 1134103285Sikob} 1135103285Sikob 1136103285Sikobstatic void 1137103285Sikobsbp_busy_timeout(struct sbp_dev *sdev) 1138103285Sikob{ 1139103285Sikob struct fw_pkt *fp; 1140103285Sikob struct fw_xfer *xfer; 1141103285SikobSBP_DEBUG(0) 1142188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1143188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1144103285SikobEND_DEBUG 1145103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 1146103285Sikob 1147167632Ssimokawa xfer->hand = sbp_busy_timeout_callback; 1148120660Ssimokawa fp = &xfer->send.hdr; 1149113584Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 1150113584Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; 1151272214Skan fp->mode.wreqq.data = htonl((1 << (13 + 12)) | 0xf); 1152103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1153103285Sikob} 1154103285Sikob 1155103285Sikobstatic void 1156121185Ssimokawasbp_orb_pointer_callback(struct fw_xfer *xfer) 1157121185Ssimokawa{ 1158121185Ssimokawa struct sbp_dev *sdev; 1159121185Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 1160121185Ssimokawa 1161170807SsimokawaSBP_DEBUG(2) 1162188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1163188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1164121185SsimokawaEND_DEBUG 1165121185Ssimokawa if (xfer->resp != 0) { 1166121185Ssimokawa /* XXX */ 1167127468Ssimokawa printf("%s: xfer->resp = %d\n", __func__, xfer->resp); 1168121185Ssimokawa } 1169266772Sjhb SBP_LOCK(sdev->target->sbp); 1170121185Ssimokawa sbp_xfer_free(xfer); 1171170807Ssimokawa 1172121185Ssimokawa sdev->flags &= ~ORB_POINTER_ACTIVE; 1173121185Ssimokawa 1174121185Ssimokawa if ((sdev->flags & ORB_POINTER_NEED) != 0) { 1175121185Ssimokawa struct sbp_ocb *ocb; 1176121185Ssimokawa 1177121185Ssimokawa sdev->flags &= ~ORB_POINTER_NEED; 1178121185Ssimokawa ocb = STAILQ_FIRST(&sdev->ocbs); 1179121185Ssimokawa if (ocb != NULL) 1180121185Ssimokawa sbp_orb_pointer(sdev, ocb); 1181121185Ssimokawa } 1182170807Ssimokawa SBP_UNLOCK(sdev->target->sbp); 1183121185Ssimokawa return; 1184121185Ssimokawa} 1185121185Ssimokawa 1186121185Ssimokawastatic void 1187103285Sikobsbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) 1188103285Sikob{ 1189103285Sikob struct fw_xfer *xfer; 1190103285Sikob struct fw_pkt *fp; 1191121185SsimokawaSBP_DEBUG(1) 1192188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1193188756Ssbruno "%s:%s 0x%08x\n", 1194188756Ssbruno __func__, sdev->bustgtlun, 1195188756Ssbruno (uint32_t)ocb->bus_addr); 1196103285SikobEND_DEBUG 1197103285Sikob 1198266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 1199170807Ssimokawa 1200121185Ssimokawa if ((sdev->flags & ORB_POINTER_ACTIVE) != 0) { 1201122421SsimokawaSBP_DEBUG(0) 1202127468Ssimokawa printf("%s: orb pointer active\n", __func__); 1203122421SsimokawaEND_DEBUG 1204121185Ssimokawa sdev->flags |= ORB_POINTER_NEED; 1205121185Ssimokawa return; 1206121185Ssimokawa } 1207121185Ssimokawa 1208121185Ssimokawa sdev->flags |= ORB_POINTER_ACTIVE; 1209266772Sjhb xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08); 1210103285Sikob if (xfer == NULL) 1211103285Sikob return; 1212167632Ssimokawa xfer->hand = sbp_orb_pointer_callback; 1213103285Sikob 1214120660Ssimokawa fp = &xfer->send.hdr; 1215113584Ssimokawa fp->mode.wreqb.len = 8; 1216103285Sikob fp->mode.wreqb.extcode = 0; 1217272214Skan xfer->send.payload[0] = 1218272214Skan htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS) << 16)); 1219129585Sdfr xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr); 1220103285Sikob 1221266772Sjhb if (fw_asyreq(xfer->fc, -1, xfer) != 0) { 1222266772Sjhb sbp_xfer_free(xfer); 1223266772Sjhb ocb->ccb->ccb_h.status = CAM_REQ_INVALID; 1224266772Sjhb xpt_done(ocb->ccb); 1225103285Sikob } 1226103285Sikob} 1227103285Sikob 1228103285Sikobstatic void 1229127468Ssimokawasbp_doorbell_callback(struct fw_xfer *xfer) 1230121185Ssimokawa{ 1231121185Ssimokawa struct sbp_dev *sdev; 1232121185Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 1233127468Ssimokawa 1234127468SsimokawaSBP_DEBUG(1) 1235188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1236188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1237121185SsimokawaEND_DEBUG 1238121185Ssimokawa if (xfer->resp != 0) { 1239121185Ssimokawa /* XXX */ 1240188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1241188756Ssbruno "%s: xfer->resp = %d\n", __func__, xfer->resp); 1242121185Ssimokawa } 1243266772Sjhb SBP_LOCK(sdev->target->sbp); 1244121185Ssimokawa sbp_xfer_free(xfer); 1245127468Ssimokawa sdev->flags &= ~ORB_DOORBELL_ACTIVE; 1246127468Ssimokawa if ((sdev->flags & ORB_DOORBELL_NEED) != 0) { 1247127468Ssimokawa sdev->flags &= ~ORB_DOORBELL_NEED; 1248127468Ssimokawa sbp_doorbell(sdev); 1249127468Ssimokawa } 1250266772Sjhb SBP_UNLOCK(sdev->target->sbp); 1251121185Ssimokawa} 1252121185Ssimokawa 1253121185Ssimokawastatic void 1254103285Sikobsbp_doorbell(struct sbp_dev *sdev) 1255103285Sikob{ 1256103285Sikob struct fw_xfer *xfer; 1257103285Sikob struct fw_pkt *fp; 1258103285SikobSBP_DEBUG(1) 1259188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1260188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1261103285SikobEND_DEBUG 1262103285Sikob 1263127468Ssimokawa if ((sdev->flags & ORB_DOORBELL_ACTIVE) != 0) { 1264127468Ssimokawa sdev->flags |= ORB_DOORBELL_NEED; 1265127468Ssimokawa return; 1266127468Ssimokawa } 1267127468Ssimokawa sdev->flags |= ORB_DOORBELL_ACTIVE; 1268266772Sjhb xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10); 1269103285Sikob if (xfer == NULL) 1270103285Sikob return; 1271167632Ssimokawa xfer->hand = sbp_doorbell_callback; 1272127468Ssimokawa fp = &xfer->send.hdr; 1273103285Sikob fp->mode.wreqq.data = htonl(0xf); 1274103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1275103285Sikob} 1276103285Sikob 1277103285Sikobstatic struct fw_xfer * 1278266772Sjhbsbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) 1279103285Sikob{ 1280103285Sikob struct fw_xfer *xfer; 1281103285Sikob struct fw_pkt *fp; 1282113584Ssimokawa struct sbp_target *target; 1283266772Sjhb int new = 0; 1284103285Sikob 1285266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 1286170807Ssimokawa 1287113584Ssimokawa target = sdev->target; 1288113584Ssimokawa xfer = STAILQ_FIRST(&target->xferlist); 1289113584Ssimokawa if (xfer == NULL) { 1290113584Ssimokawa if (target->n_xfer > 5 /* XXX */) { 1291113584Ssimokawa printf("sbp: no more xfer for this target\n"); 1292272214Skan return (NULL); 1293113584Ssimokawa } 1294120660Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 8, 0); 1295272214Skan if (xfer == NULL) { 1296113584Ssimokawa printf("sbp: fw_xfer_alloc_buf failed\n"); 1297113584Ssimokawa return NULL; 1298113584Ssimokawa } 1299272214Skan target->n_xfer++; 1300113584Ssimokawa if (debug) 1301113584Ssimokawa printf("sbp: alloc %d xfer\n", target->n_xfer); 1302113584Ssimokawa new = 1; 1303113584Ssimokawa } else { 1304113584Ssimokawa STAILQ_REMOVE_HEAD(&target->xferlist, link); 1305103285Sikob } 1306113584Ssimokawa 1307113584Ssimokawa if (new) { 1308120660Ssimokawa xfer->recv.pay_len = 0; 1309120660Ssimokawa xfer->send.spd = min(sdev->target->fwdev->speed, max_speed); 1310113584Ssimokawa xfer->fc = sdev->target->sbp->fd.fc; 1311103285Sikob } 1312120660Ssimokawa 1313120660Ssimokawa if (tcode == FWTCODE_WREQB) 1314120660Ssimokawa xfer->send.pay_len = 8; 1315120660Ssimokawa else 1316120660Ssimokawa xfer->send.pay_len = 0; 1317120660Ssimokawa 1318103285Sikob xfer->sc = (caddr_t)sdev; 1319120660Ssimokawa fp = &xfer->send.hdr; 1320113584Ssimokawa fp->mode.wreqq.dest_hi = sdev->login->cmd_hi; 1321113584Ssimokawa fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset; 1322103285Sikob fp->mode.wreqq.tlrt = 0; 1323103285Sikob fp->mode.wreqq.tcode = tcode; 1324103285Sikob fp->mode.wreqq.pri = 0; 1325120660Ssimokawa fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst; 1326103285Sikob 1327103285Sikob return xfer; 1328103285Sikob} 1329103285Sikob 1330103285Sikobstatic void 1331111615Ssimokawasbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) 1332103285Sikob{ 1333103285Sikob struct fw_xfer *xfer; 1334103285Sikob struct fw_pkt *fp; 1335103285Sikob struct sbp_ocb *ocb; 1336111615Ssimokawa struct sbp_target *target; 1337266772Sjhb int nid; 1338103285Sikob 1339111615Ssimokawa target = sdev->target; 1340111615Ssimokawa nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; 1341111615Ssimokawa 1342266772Sjhb SBP_LOCK_ASSERT(target->sbp); 1343111615Ssimokawa if (func == ORB_FUN_RUNQUEUE) { 1344111615Ssimokawa ocb = STAILQ_FIRST(&target->mgm_ocb_queue); 1345111615Ssimokawa if (target->mgm_ocb_cur != NULL || ocb == NULL) { 1346111615Ssimokawa return; 1347111615Ssimokawa } 1348111615Ssimokawa STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); 1349111615Ssimokawa goto start; 1350111615Ssimokawa } 1351113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 1352122528Ssimokawa /* XXX */ 1353103285Sikob return; 1354103285Sikob } 1355103285Sikob ocb->flags = OCB_ACT_MGM; 1356103285Sikob ocb->sdev = sdev; 1357103285Sikob 1358120660Ssimokawa bzero((void *)ocb->orb, sizeof(ocb->orb)); 1359103285Sikob ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI); 1360120660Ssimokawa ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id)); 1361103285Sikob 1362107653SsimokawaSBP_DEBUG(0) 1363188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1364188756Ssbruno "%s:%s %s\n", 1365188756Ssbruno __func__,sdev->bustgtlun, 1366272214Skan orb_fun_name[(func >> 16) & 0xf]); 1367107653SsimokawaEND_DEBUG 1368103285Sikob switch (func) { 1369103285Sikob case ORB_FUN_LGI: 1370120660Ssimokawa ocb->orb[0] = ocb->orb[1] = 0; /* password */ 1371103285Sikob ocb->orb[2] = htonl(nid << 16); 1372113584Ssimokawa ocb->orb[3] = htonl(sdev->dma.bus_addr); 1373121792Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | sdev->lun_id); 1374122387Ssimokawa if (ex_login) 1375121792Ssimokawa ocb->orb[4] |= htonl(ORB_EXV); 1376113584Ssimokawa ocb->orb[5] = htonl(SBP_LOGIN_SIZE); 1377113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD); 1378103285Sikob break; 1379110336Ssimokawa case ORB_FUN_ATA: 1380111615Ssimokawa ocb->orb[0] = htonl((0 << 16) | 0); 1381113584Ssimokawa ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff); 1382110336Ssimokawa /* fall through */ 1383103285Sikob case ORB_FUN_RCN: 1384103285Sikob case ORB_FUN_LGO: 1385103285Sikob case ORB_FUN_LUR: 1386103285Sikob case ORB_FUN_RST: 1387103285Sikob case ORB_FUN_ATS: 1388113584Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id); 1389103285Sikob break; 1390103285Sikob } 1391103285Sikob 1392111615Ssimokawa if (target->mgm_ocb_cur != NULL) { 1393111615Ssimokawa /* there is a standing ORB */ 1394111615Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); 1395111615Ssimokawa return; 1396111615Ssimokawa } 1397111615Ssimokawastart: 1398111615Ssimokawa target->mgm_ocb_cur = ocb; 1399111615Ssimokawa 1400274819Ssmh callout_reset(&target->mgm_ocb_timeout, 5 * hz, 1401114732Ssimokawa sbp_mgm_timeout, (caddr_t)ocb); 1402103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); 1403272214Skan if (xfer == NULL) { 1404103285Sikob return; 1405103285Sikob } 1406167632Ssimokawa xfer->hand = sbp_mgm_callback; 1407103285Sikob 1408120660Ssimokawa fp = &xfer->send.hdr; 1409113584Ssimokawa fp->mode.wreqb.dest_hi = sdev->target->mgm_hi; 1410113584Ssimokawa fp->mode.wreqb.dest_lo = sdev->target->mgm_lo; 1411113584Ssimokawa fp->mode.wreqb.len = 8; 1412103285Sikob fp->mode.wreqb.extcode = 0; 1413120660Ssimokawa xfer->send.payload[0] = htonl(nid << 16); 1414120660Ssimokawa xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff); 1415103285Sikob 1416103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1417103285Sikob} 1418103285Sikob 1419103285Sikobstatic void 1420105792Ssimokawasbp_print_scsi_cmd(struct sbp_ocb *ocb) 1421103285Sikob{ 1422103285Sikob struct ccb_scsiio *csio; 1423103285Sikob 1424103285Sikob csio = &ocb->ccb->csio; 1425257381Snwhitehorn printf("%s:%d:%jx XPT_SCSI_IO: " 1426103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 1427103285Sikob ", flags: 0x%02x, " 1428103285Sikob "%db cmd/%db data/%db sense\n", 1429103285Sikob device_get_nameunit(ocb->sdev->target->sbp->fd.dev), 1430257381Snwhitehorn ocb->ccb->ccb_h.target_id, 1431257381Snwhitehorn (uintmax_t)ocb->ccb->ccb_h.target_lun, 1432103285Sikob csio->cdb_io.cdb_bytes[0], 1433103285Sikob csio->cdb_io.cdb_bytes[1], 1434103285Sikob csio->cdb_io.cdb_bytes[2], 1435103285Sikob csio->cdb_io.cdb_bytes[3], 1436103285Sikob csio->cdb_io.cdb_bytes[4], 1437103285Sikob csio->cdb_io.cdb_bytes[5], 1438103285Sikob csio->cdb_io.cdb_bytes[6], 1439103285Sikob csio->cdb_io.cdb_bytes[7], 1440103285Sikob csio->cdb_io.cdb_bytes[8], 1441103285Sikob csio->cdb_io.cdb_bytes[9], 1442103285Sikob ocb->ccb->ccb_h.flags & CAM_DIR_MASK, 1443103285Sikob csio->cdb_len, csio->dxfer_len, 1444103285Sikob csio->sense_len); 1445105792Ssimokawa} 1446105792Ssimokawa 1447105792Ssimokawastatic void 1448105792Ssimokawasbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb) 1449105792Ssimokawa{ 1450105792Ssimokawa struct sbp_cmd_status *sbp_cmd_status; 1451225950Sken struct scsi_sense_data_fixed *sense; 1452105792Ssimokawa 1453105792Ssimokawa sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data; 1454225950Sken sense = (struct scsi_sense_data_fixed *)&ocb->ccb->csio.sense_data; 1455105792Ssimokawa 1456105792SsimokawaSBP_DEBUG(0) 1457105792Ssimokawa sbp_print_scsi_cmd(ocb); 1458103285Sikob /* XXX need decode status */ 1459188756Ssbruno printf("%s: SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", 1460188756Ssbruno ocb->sdev->bustgtlun, 1461103285Sikob sbp_cmd_status->status, 1462103285Sikob sbp_cmd_status->sfmt, 1463103285Sikob sbp_cmd_status->valid, 1464103285Sikob sbp_cmd_status->s_key, 1465103285Sikob sbp_cmd_status->s_code, 1466103285Sikob sbp_cmd_status->s_qlfr, 1467188756Ssbruno sbp_status->len); 1468103285SikobEND_DEBUG 1469103285Sikob 1470110071Ssimokawa switch (sbp_cmd_status->status) { 1471110071Ssimokawa case SCSI_STATUS_CHECK_COND: 1472110071Ssimokawa case SCSI_STATUS_BUSY: 1473110071Ssimokawa case SCSI_STATUS_CMD_TERMINATED: 1474272214Skan if (sbp_cmd_status->sfmt == SBP_SFMT_CURR) { 1475103285Sikob sense->error_code = SSD_CURRENT_ERROR; 1476272214Skan } else { 1477103285Sikob sense->error_code = SSD_DEFERRED_ERROR; 1478103285Sikob } 1479272214Skan if (sbp_cmd_status->valid) 1480103285Sikob sense->error_code |= SSD_ERRCODE_VALID; 1481103285Sikob sense->flags = sbp_cmd_status->s_key; 1482272214Skan if (sbp_cmd_status->mark) 1483103285Sikob sense->flags |= SSD_FILEMARK; 1484272214Skan if (sbp_cmd_status->eom) 1485103285Sikob sense->flags |= SSD_EOM; 1486272214Skan if (sbp_cmd_status->ill_len) 1487103285Sikob sense->flags |= SSD_ILI; 1488119556Ssimokawa 1489119556Ssimokawa bcopy(&sbp_cmd_status->info, &sense->info[0], 4); 1490119556Ssimokawa 1491103285Sikob if (sbp_status->len <= 1) 1492272214Skan /* XXX not scsi status. shouldn't be happened */ 1493103285Sikob sense->extra_len = 0; 1494103285Sikob else if (sbp_status->len <= 4) 1495103285Sikob /* add_sense_code(_qual), info, cmd_spec_info */ 1496103285Sikob sense->extra_len = 6; 1497103285Sikob else 1498103285Sikob /* fru, sense_key_spec */ 1499103285Sikob sense->extra_len = 10; 1500119556Ssimokawa 1501119556Ssimokawa bcopy(&sbp_cmd_status->cdb, &sense->cmd_spec_info[0], 4); 1502119556Ssimokawa 1503103285Sikob sense->add_sense_code = sbp_cmd_status->s_code; 1504103285Sikob sense->add_sense_code_qual = sbp_cmd_status->s_qlfr; 1505103285Sikob sense->fru = sbp_cmd_status->fru; 1506103285Sikob 1507119556Ssimokawa bcopy(&sbp_cmd_status->s_keydep[0], 1508119556Ssimokawa &sense->sense_key_spec[0], 3); 1509119556Ssimokawa 1510201758Smbr ocb->ccb->csio.scsi_status = sbp_cmd_status->status; 1511103285Sikob ocb->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR 1512103285Sikob | CAM_AUTOSNS_VALID; 1513103285Sikob/* 1514103285Sikob{ 1515129585Sdfr uint8_t j, *tmp; 1516103285Sikob tmp = sense; 1517272214Skan for (j = 0; j < 32; j += 8) { 1518272214Skan printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n", 1519272214Skan tmp[j], tmp[j + 1], tmp[j + 2], tmp[j + 3], 1520272214Skan tmp[j + 4], tmp[j + 5], tmp[j + 6], tmp[j + 7]); 1521103285Sikob } 1522103285Sikob 1523103285Sikob} 1524103285Sikob*/ 1525110071Ssimokawa break; 1526110071Ssimokawa default: 1527188756Ssbruno device_printf(ocb->sdev->target->sbp->fd.dev, 1528188756Ssbruno "%s:%s unknown scsi status 0x%x\n", 1529188756Ssbruno __func__, ocb->sdev->bustgtlun, 1530188756Ssbruno sbp_cmd_status->status); 1531103285Sikob } 1532103285Sikob} 1533103285Sikob 1534103285Sikobstatic void 1535103285Sikobsbp_fix_inq_data(struct sbp_ocb *ocb) 1536103285Sikob{ 1537103285Sikob union ccb *ccb; 1538103285Sikob struct sbp_dev *sdev; 1539103285Sikob struct scsi_inquiry_data *inq; 1540103285Sikob 1541103285Sikob ccb = ocb->ccb; 1542103285Sikob sdev = ocb->sdev; 1543103285Sikob 1544103285Sikob if (ccb->csio.cdb_io.cdb_bytes[1] & SI_EVPD) 1545103285Sikob return; 1546103285SikobSBP_DEBUG(1) 1547188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1548188756Ssbruno "%s:%s\n", __func__, sdev->bustgtlun); 1549103285SikobEND_DEBUG 1550103285Sikob inq = (struct scsi_inquiry_data *) ccb->csio.data_ptr; 1551103285Sikob switch (SID_TYPE(inq)) { 1552103285Sikob case T_DIRECT: 1553118291Ssimokawa#if 0 1554272214Skan /* 1555103285Sikob * XXX Convert Direct Access device to RBC. 1556108281Ssimokawa * I've never seen FireWire DA devices which support READ_6. 1557103285Sikob */ 1558103285Sikob if (SID_TYPE(inq) == T_DIRECT) 1559103285Sikob inq->device |= T_RBC; /* T_DIRECT == 0 */ 1560103285Sikob#endif 1561103285Sikob /* fall through */ 1562103285Sikob case T_RBC: 1563103285Sikob /* 1564103285Sikob * Override vendor/product/revision information. 1565103285Sikob * Some devices sometimes return strange strings. 1566103285Sikob */ 1567111615Ssimokawa#if 1 1568103285Sikob bcopy(sdev->vendor, inq->vendor, sizeof(inq->vendor)); 1569103285Sikob bcopy(sdev->product, inq->product, sizeof(inq->product)); 1570272214Skan bcopy(sdev->revision + 2, inq->revision, sizeof(inq->revision)); 1571111615Ssimokawa#endif 1572103285Sikob break; 1573103285Sikob } 1574127468Ssimokawa /* 1575127468Ssimokawa * Force to enable/disable tagged queuing. 1576127468Ssimokawa * XXX CAM also checks SCP_QUEUE_DQUE flag in the control mode page. 1577127468Ssimokawa */ 1578127468Ssimokawa if (sbp_tags > 0) 1579127468Ssimokawa inq->flags |= SID_CmdQue; 1580127468Ssimokawa else if (sbp_tags < 0) 1581127468Ssimokawa inq->flags &= ~SID_CmdQue; 1582127468Ssimokawa 1583103285Sikob} 1584103285Sikob 1585103285Sikobstatic void 1586113584Ssimokawasbp_recv1(struct fw_xfer *xfer) 1587113584Ssimokawa{ 1588103285Sikob struct fw_pkt *rfp; 1589103285Sikob#if NEED_RESPONSE 1590103285Sikob struct fw_pkt *sfp; 1591103285Sikob#endif 1592103285Sikob struct sbp_softc *sbp; 1593103285Sikob struct sbp_dev *sdev; 1594103285Sikob struct sbp_ocb *ocb; 1595103285Sikob struct sbp_login_res *login_res = NULL; 1596103285Sikob struct sbp_status *sbp_status; 1597103285Sikob struct sbp_target *target; 1598111704Ssimokawa int orb_fun, status_valid0, status_valid, t, l, reset_agent = 0; 1599129585Sdfr uint32_t addr; 1600103285Sikob/* 1601129585Sdfr uint32_t *ld; 1602103285Sikob ld = xfer->recv.buf; 1603103285Sikobprintf("sbp %x %d %d %08x %08x %08x %08x\n", 1604103285Sikob xfer->resp, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 1605103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 1606103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11])); 1607103285Sikob*/ 1608113584Ssimokawa sbp = (struct sbp_softc *)xfer->sc; 1609266772Sjhb SBP_LOCK_ASSERT(sbp); 1610272214Skan if (xfer->resp != 0) { 1611122529Ssimokawa printf("sbp_recv: xfer->resp = %d\n", xfer->resp); 1612113584Ssimokawa goto done0; 1613103285Sikob } 1614272214Skan if (xfer->recv.payload == NULL) { 1615120660Ssimokawa printf("sbp_recv: xfer->recv.payload == NULL\n"); 1616113584Ssimokawa goto done0; 1617103285Sikob } 1618120660Ssimokawa rfp = &xfer->recv.hdr; 1619272214Skan if (rfp->mode.wreqb.tcode != FWTCODE_WREQB) { 1620103285Sikob printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); 1621113584Ssimokawa goto done0; 1622103285Sikob } 1623120660Ssimokawa sbp_status = (struct sbp_status *)xfer->recv.payload; 1624113584Ssimokawa addr = rfp->mode.wreqb.dest_lo; 1625103285SikobSBP_DEBUG(2) 1626103285Sikob printf("received address 0x%x\n", addr); 1627103285SikobEND_DEBUG 1628110189Ssimokawa t = SBP_ADDR2TRG(addr); 1629110189Ssimokawa if (t >= SBP_NUM_TARGETS) { 1630110189Ssimokawa device_printf(sbp->fd.dev, 1631110189Ssimokawa "sbp_recv1: invalid target %d\n", t); 1632113584Ssimokawa goto done0; 1633110189Ssimokawa } 1634110189Ssimokawa target = &sbp->targets[t]; 1635110189Ssimokawa l = SBP_ADDR2LUN(addr); 1636121185Ssimokawa if (l >= target->num_lun || target->luns[l] == NULL) { 1637110189Ssimokawa device_printf(sbp->fd.dev, 1638110189Ssimokawa "sbp_recv1: invalid lun %d (target=%d)\n", l, t); 1639113584Ssimokawa goto done0; 1640110189Ssimokawa } 1641121185Ssimokawa sdev = target->luns[l]; 1642103285Sikob 1643110189Ssimokawa ocb = NULL; 1644110189Ssimokawa switch (sbp_status->src) { 1645110189Ssimokawa case 0: 1646110189Ssimokawa case 1: 1647111615Ssimokawa /* check mgm_ocb_cur first */ 1648111615Ssimokawa ocb = target->mgm_ocb_cur; 1649111615Ssimokawa if (ocb != NULL) { 1650111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 1651111615Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1652111615Ssimokawa target->mgm_ocb_cur = NULL; 1653111615Ssimokawa break; 1654111615Ssimokawa } 1655111615Ssimokawa } 1656111615Ssimokawa ocb = sbp_dequeue_ocb(sdev, sbp_status); 1657110189Ssimokawa if (ocb == NULL) { 1658188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1659188756Ssbruno "%s:%s No ocb(%x) on the queue\n", 1660188756Ssbruno __func__,sdev->bustgtlun, 1661188756Ssbruno ntohl(sbp_status->orb_lo)); 1662110189Ssimokawa } 1663110189Ssimokawa break; 1664110189Ssimokawa case 2: 1665110189Ssimokawa /* unsolicit */ 1666188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1667188756Ssbruno "%s:%s unsolicit status received\n", 1668188756Ssbruno __func__, sdev->bustgtlun); 1669110189Ssimokawa break; 1670110189Ssimokawa default: 1671188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1672188756Ssbruno "%s:%s unknown sbp_status->src\n", 1673188756Ssbruno __func__, sdev->bustgtlun); 1674110189Ssimokawa } 1675110189Ssimokawa 1676111615Ssimokawa status_valid0 = (sbp_status->src < 2 1677110189Ssimokawa && sbp_status->resp == ORB_RES_CMPL 1678111615Ssimokawa && sbp_status->dead == 0); 1679111615Ssimokawa status_valid = (status_valid0 && sbp_status->status == 0); 1680103285Sikob 1681272214Skan if (!status_valid0 || debug > 2) { 1682103285Sikob int status; 1683110129SsimokawaSBP_DEBUG(0) 1684188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1685188756Ssbruno "%s:%s ORB status src:%x resp:%x dead:%x" 1686103285Sikob " len:%x stat:%x orb:%x%08x\n", 1687188756Ssbruno __func__, sdev->bustgtlun, 1688103285Sikob sbp_status->src, sbp_status->resp, sbp_status->dead, 1689103285Sikob sbp_status->len, sbp_status->status, 1690108280Ssimokawa ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); 1691110129SsimokawaEND_DEBUG 1692188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1693188756Ssbruno "%s\n", sdev->bustgtlun); 1694103285Sikob status = sbp_status->status; 1695272214Skan switch (sbp_status->resp) { 1696103285Sikob case 0: 1697103285Sikob if (status > MAX_ORB_STATUS0) 1698103285Sikob printf("%s\n", orb_status0[MAX_ORB_STATUS0]); 1699110189Ssimokawa else 1700110129Ssimokawa printf("%s\n", orb_status0[status]); 1701103285Sikob break; 1702103285Sikob case 1: 1703110336Ssimokawa printf("Obj: %s, Error: %s\n", 1704272214Skan orb_status1_object[(status >> 6) & 3], 1705103285Sikob orb_status1_serial_bus_error[status & 0xf]); 1706103285Sikob break; 1707110129Ssimokawa case 2: 1708110129Ssimokawa printf("Illegal request\n"); 1709110129Ssimokawa break; 1710110129Ssimokawa case 3: 1711110129Ssimokawa printf("Vendor dependent\n"); 1712110129Ssimokawa break; 1713103285Sikob default: 1714110129Ssimokawa printf("unknown respose code %d\n", sbp_status->resp); 1715103285Sikob } 1716103285Sikob } 1717103285Sikob 1718103285Sikob /* we have to reset the fetch agent if it's dead */ 1719103285Sikob if (sbp_status->dead) { 1720111615Ssimokawa if (sdev->path) { 1721103285Sikob xpt_freeze_devq(sdev->path, 1); 1722272214Skan sdev->freeze++; 1723111615Ssimokawa } 1724111704Ssimokawa reset_agent = 1; 1725103285Sikob } 1726103285Sikob 1727111704Ssimokawa if (ocb == NULL) 1728111704Ssimokawa goto done; 1729103285Sikob 1730272214Skan switch (ntohl(ocb->orb[4]) & ORB_FMT_MSK) { 1731103285Sikob case ORB_FMT_NOP: 1732103285Sikob break; 1733103285Sikob case ORB_FMT_VED: 1734103285Sikob break; 1735103285Sikob case ORB_FMT_STD: 1736272214Skan switch (ocb->flags) { 1737103285Sikob case OCB_ACT_MGM: 1738103285Sikob orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK; 1739120842Ssimokawa reset_agent = 0; 1740272214Skan switch (orb_fun) { 1741103285Sikob case ORB_FUN_LGI: 1742113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD); 1743113584Ssimokawa login_res = sdev->login; 1744103285Sikob login_res->len = ntohs(login_res->len); 1745103285Sikob login_res->id = ntohs(login_res->id); 1746103285Sikob login_res->cmd_hi = ntohs(login_res->cmd_hi); 1747103285Sikob login_res->cmd_lo = ntohl(login_res->cmd_lo); 1748103285Sikob if (status_valid) { 1749103285SikobSBP_DEBUG(0) 1750188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1751188756Ssbruno "%s:%s login: len %d, ID %d, cmd %08x%08x, recon_hold %d\n", 1752188756Ssbruno __func__, sdev->bustgtlun, 1753188756Ssbruno login_res->len, login_res->id, 1754188756Ssbruno login_res->cmd_hi, login_res->cmd_lo, 1755188756Ssbruno ntohs(login_res->recon_hold)); 1756103285SikobEND_DEBUG 1757103285Sikob sbp_busy_timeout(sdev); 1758103285Sikob } else { 1759110336Ssimokawa /* forgot logout? */ 1760188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1761188756Ssbruno "%s:%s login failed\n", 1762188756Ssbruno __func__, sdev->bustgtlun); 1763103285Sikob sdev->status = SBP_DEV_RESET; 1764103285Sikob } 1765103285Sikob break; 1766103285Sikob case ORB_FUN_RCN: 1767113584Ssimokawa login_res = sdev->login; 1768103285Sikob if (status_valid) { 1769103285SikobSBP_DEBUG(0) 1770188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1771188756Ssbruno "%s:%s reconnect: len %d, ID %d, cmd %08x%08x\n", 1772188756Ssbruno __func__, sdev->bustgtlun, 1773188756Ssbruno login_res->len, login_res->id, 1774188756Ssbruno login_res->cmd_hi, login_res->cmd_lo); 1775103285SikobEND_DEBUG 1776111615Ssimokawa if (sdev->status == SBP_DEV_ATTACHED) 1777111615Ssimokawa sbp_scan_dev(sdev); 1778111615Ssimokawa else 1779111615Ssimokawa sbp_agent_reset(sdev); 1780103285Sikob } else { 1781103285Sikob /* reconnection hold time exceed? */ 1782110336SsimokawaSBP_DEBUG(0) 1783188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1784188756Ssbruno "%s:%s reconnect failed\n", 1785188756Ssbruno __func__, sdev->bustgtlun); 1786110336SsimokawaEND_DEBUG 1787111615Ssimokawa sbp_login(sdev); 1788103285Sikob } 1789103285Sikob break; 1790103285Sikob case ORB_FUN_LGO: 1791103285Sikob sdev->status = SBP_DEV_RESET; 1792103285Sikob break; 1793110336Ssimokawa case ORB_FUN_RST: 1794110336Ssimokawa sbp_busy_timeout(sdev); 1795110336Ssimokawa break; 1796103285Sikob case ORB_FUN_LUR: 1797103285Sikob case ORB_FUN_ATA: 1798103285Sikob case ORB_FUN_ATS: 1799110336Ssimokawa sbp_agent_reset(sdev); 1800103285Sikob break; 1801103285Sikob default: 1802188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 1803188756Ssbruno "%s:%s unknown function %d\n", 1804188756Ssbruno __func__, sdev->bustgtlun, orb_fun); 1805103285Sikob break; 1806103285Sikob } 1807111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 1808103285Sikob break; 1809103285Sikob case OCB_ACT_CMD: 1810114732Ssimokawa sdev->timeout = 0; 1811272214Skan if (ocb->ccb != NULL) { 1812103285Sikob union ccb *ccb; 1813188756Ssbruno 1814103285Sikob ccb = ocb->ccb; 1815272214Skan if (sbp_status->len > 1) { 1816103285Sikob sbp_scsi_status(sbp_status, ocb); 1817272214Skan } else { 1818272214Skan if (sbp_status->resp != ORB_RES_CMPL) { 1819103285Sikob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1820272214Skan } else { 1821103285Sikob ccb->ccb_h.status = CAM_REQ_CMP; 1822103285Sikob } 1823103285Sikob } 1824103285Sikob /* fix up inq data */ 1825103285Sikob if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY) 1826103285Sikob sbp_fix_inq_data(ocb); 1827103285Sikob xpt_done(ccb); 1828103285Sikob } 1829103285Sikob break; 1830103285Sikob default: 1831103285Sikob break; 1832103285Sikob } 1833103285Sikob } 1834103285Sikob 1835127468Ssimokawa if (!use_doorbell) 1836127468Ssimokawa sbp_free_ocb(sdev, ocb); 1837111704Ssimokawadone: 1838111704Ssimokawa if (reset_agent) 1839111704Ssimokawa sbp_agent_reset(sdev); 1840103285Sikob 1841113584Ssimokawadone0: 1842120660Ssimokawa xfer->recv.pay_len = SBP_RECV_LEN; 1843103285Sikob/* The received packet is usually small enough to be stored within 1844103285Sikob * the buffer. In that case, the controller return ack_complete and 1845103285Sikob * no respose is necessary. 1846103285Sikob * 1847272214Skan * XXX fwohci.c and firewire.c should inform event_code such as 1848103285Sikob * ack_complete or ack_pending to upper driver. 1849103285Sikob */ 1850103285Sikob#if NEED_RESPONSE 1851103285Sikob xfer->send.off = 0; 1852103285Sikob sfp = (struct fw_pkt *)xfer->send.buf; 1853103285Sikob sfp->mode.wres.dst = rfp->mode.wreqb.src; 1854113584Ssimokawa xfer->dst = sfp->mode.wres.dst; 1855103285Sikob xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1856167632Ssimokawa xfer->hand = sbp_loginres_callback; 1857103285Sikob 1858103285Sikob sfp->mode.wres.tlrt = rfp->mode.wreqb.tlrt; 1859103285Sikob sfp->mode.wres.tcode = FWTCODE_WRES; 1860103285Sikob sfp->mode.wres.rtcode = 0; 1861103285Sikob sfp->mode.wres.pri = 0; 1862103285Sikob 1863103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1864103285Sikob#else 1865113584Ssimokawa /* recycle */ 1866113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1867103285Sikob#endif 1868103285Sikob} 1869103285Sikob 1870103285Sikobstatic void 1871103285Sikobsbp_recv(struct fw_xfer *xfer) 1872103285Sikob{ 1873266772Sjhb struct sbp_softc *sbp; 1874103285Sikob 1875266772Sjhb sbp = (struct sbp_softc *)xfer->sc; 1876266772Sjhb SBP_LOCK(sbp); 1877103285Sikob sbp_recv1(xfer); 1878266772Sjhb SBP_UNLOCK(sbp); 1879103285Sikob} 1880103285Sikob/* 1881103285Sikob * sbp_attach() 1882103285Sikob */ 1883103285Sikobstatic int 1884103285Sikobsbp_attach(device_t dev) 1885103285Sikob{ 1886103285Sikob struct sbp_softc *sbp; 1887103285Sikob struct cam_devq *devq; 1888170374Ssimokawa struct firewire_comm *fc; 1889266772Sjhb int i, error; 1890103285Sikob 1891167624Ssimokawa if (DFLTPHYS > SBP_MAXPHYS) 1892167624Ssimokawa device_printf(dev, "Warning, DFLTPHYS(%dKB) is larger than " 1893167624Ssimokawa "SBP_MAXPHYS(%dKB).\n", DFLTPHYS / 1024, 1894167624Ssimokawa SBP_MAXPHYS / 1024); 1895167624Ssimokawa 1896170400Ssimokawa if (!firewire_phydma_enable) 1897170400Ssimokawa device_printf(dev, "Warning, hw.firewire.phydma_enable must be 1 " 1898170400Ssimokawa "for SBP over FireWire.\n"); 1899103285SikobSBP_DEBUG(0) 1900111199Ssimokawa printf("sbp_attach (cold=%d)\n", cold); 1901103285SikobEND_DEBUG 1902103285Sikob 1903111199Ssimokawa if (cold) 1904272214Skan sbp_cold++; 1905266772Sjhb sbp = device_get_softc(dev); 1906103285Sikob sbp->fd.dev = dev; 1907170374Ssimokawa sbp->fd.fc = fc = device_get_ivars(dev); 1908170374Ssimokawa mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF); 1909124251Ssimokawa 1910124251Ssimokawa if (max_speed < 0) 1911170374Ssimokawa max_speed = fc->speed; 1912124251Ssimokawa 1913170374Ssimokawa error = bus_dma_tag_create(/*parent*/fc->dmat, 1914113584Ssimokawa /* XXX shoud be 4 for sane backend? */ 1915113584Ssimokawa /*alignment*/1, 1916103285Sikob /*boundary*/0, 1917103285Sikob /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1918103285Sikob /*highaddr*/BUS_SPACE_MAXADDR, 1919103285Sikob /*filter*/NULL, /*filterarg*/NULL, 1920103285Sikob /*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX, 1921113474Ssimokawa /*maxsegsz*/SBP_SEG_MAX, 1922103285Sikob /*flags*/BUS_DMA_ALLOCNOW, 1923117126Sscottl /*lockfunc*/busdma_lock_mutex, 1924170374Ssimokawa /*lockarg*/&sbp->mtx, 1925117228Ssimokawa &sbp->dmat); 1926103285Sikob if (error != 0) { 1927103285Sikob printf("sbp_attach: Could not allocate DMA tag " 1928103285Sikob "- error %d\n", error); 1929103285Sikob return (ENOMEM); 1930103285Sikob } 1931103285Sikob 1932103285Sikob devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB); 1933103285Sikob if (devq == NULL) 1934103285Sikob return (ENXIO); 1935103285Sikob 1936272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) { 1937103285Sikob sbp->targets[i].fwdev = NULL; 1938103285Sikob sbp->targets[i].luns = NULL; 1939267660Skan sbp->targets[i].sbp = sbp; 1940103285Sikob } 1941103285Sikob 1942103285Sikob sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp, 1943103285Sikob device_get_unit(dev), 1944170374Ssimokawa &sbp->mtx, 1945111615Ssimokawa /*untagged*/ 1, 1946122528Ssimokawa /*tagged*/ SBP_QUEUE_LEN - 1, 1947111615Ssimokawa devq); 1948103285Sikob 1949103285Sikob if (sbp->sim == NULL) { 1950103285Sikob cam_simq_free(devq); 1951103285Sikob return (ENXIO); 1952103285Sikob } 1953103285Sikob 1954170374Ssimokawa SBP_LOCK(sbp); 1955170872Sscottl if (xpt_bus_register(sbp->sim, dev, /*bus*/0) != CAM_SUCCESS) 1956111615Ssimokawa goto fail; 1957103285Sikob 1958249468Smav if (xpt_create_path(&sbp->path, NULL, cam_sim_path(sbp->sim), 1959120660Ssimokawa CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1960120660Ssimokawa xpt_bus_deregister(cam_sim_path(sbp->sim)); 1961111615Ssimokawa goto fail; 1962120660Ssimokawa } 1963170374Ssimokawa SBP_UNLOCK(sbp); 1964111615Ssimokawa 1965103285Sikob /* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */ 1966120660Ssimokawa sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0); 1967120660Ssimokawa sbp->fwb.end = sbp->fwb.start + 0xffff; 1968113584Ssimokawa /* pre-allocate xfer */ 1969113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 1970169130Ssimokawa fw_xferlist_add(&sbp->fwb.xferlist, M_SBP, 1971169130Ssimokawa /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB/2, 1972170374Ssimokawa fc, (void *)sbp, sbp_recv); 1973103285Sikob 1974170374Ssimokawa fw_bindadd(fc, &sbp->fwb); 1975170374Ssimokawa 1976113584Ssimokawa sbp->fd.post_busreset = sbp_post_busreset; 1977103285Sikob sbp->fd.post_explore = sbp_post_explore; 1978103285Sikob 1979170374Ssimokawa if (fc->status != -1) { 1980122387Ssimokawa sbp_post_busreset((void *)sbp); 1981111199Ssimokawa sbp_post_explore((void *)sbp); 1982111199Ssimokawa } 1983170374Ssimokawa SBP_LOCK(sbp); 1984122387Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 1985170374Ssimokawa SBP_UNLOCK(sbp); 1986111199Ssimokawa 1987103285Sikob return (0); 1988111615Ssimokawafail: 1989170374Ssimokawa SBP_UNLOCK(sbp); 1990111615Ssimokawa cam_sim_free(sbp->sim, /*free_devq*/TRUE); 1991111615Ssimokawa return (ENXIO); 1992103285Sikob} 1993103285Sikob 1994103285Sikobstatic int 1995110145Ssimokawasbp_logout_all(struct sbp_softc *sbp) 1996110145Ssimokawa{ 1997110145Ssimokawa struct sbp_target *target; 1998110145Ssimokawa struct sbp_dev *sdev; 1999110145Ssimokawa int i, j; 2000110145Ssimokawa 2001110145SsimokawaSBP_DEBUG(0) 2002110145Ssimokawa printf("sbp_logout_all\n"); 2003110145SsimokawaEND_DEBUG 2004266772Sjhb SBP_LOCK_ASSERT(sbp); 2005272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) { 2006110145Ssimokawa target = &sbp->targets[i]; 2007110145Ssimokawa if (target->luns == NULL) 2008110145Ssimokawa continue; 2009110145Ssimokawa for (j = 0; j < target->num_lun; j++) { 2010121185Ssimokawa sdev = target->luns[j]; 2011121185Ssimokawa if (sdev == NULL) 2012121185Ssimokawa continue; 2013113584Ssimokawa callout_stop(&sdev->login_callout); 2014110336Ssimokawa if (sdev->status >= SBP_DEV_TOATTACH && 2015110336Ssimokawa sdev->status <= SBP_DEV_ATTACHED) 2016111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); 2017110145Ssimokawa } 2018110145Ssimokawa } 2019113584Ssimokawa 2020110145Ssimokawa return 0; 2021110145Ssimokawa} 2022110145Ssimokawa 2023110145Ssimokawastatic int 2024110145Ssimokawasbp_shutdown(device_t dev) 2025110145Ssimokawa{ 2026110145Ssimokawa struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 2027110145Ssimokawa 2028266772Sjhb SBP_LOCK(sbp); 2029110145Ssimokawa sbp_logout_all(sbp); 2030266772Sjhb SBP_UNLOCK(sbp); 2031110145Ssimokawa return (0); 2032110145Ssimokawa} 2033110145Ssimokawa 2034121185Ssimokawastatic void 2035121185Ssimokawasbp_free_sdev(struct sbp_dev *sdev) 2036121185Ssimokawa{ 2037266772Sjhb struct sbp_softc *sbp; 2038121185Ssimokawa int i; 2039121185Ssimokawa 2040121185Ssimokawa if (sdev == NULL) 2041121185Ssimokawa return; 2042266772Sjhb sbp = sdev->target->sbp; 2043266772Sjhb SBP_UNLOCK(sbp); 2044266772Sjhb callout_drain(&sdev->login_callout); 2045266772Sjhb for (i = 0; i < SBP_QUEUE_LEN; i++) { 2046266772Sjhb callout_drain(&sdev->ocb[i].timer); 2047266772Sjhb bus_dmamap_destroy(sbp->dmat, sdev->ocb[i].dmamap); 2048266772Sjhb } 2049266772Sjhb fwdma_free(sbp->fd.fc, &sdev->dma); 2050121185Ssimokawa free(sdev, M_SBP); 2051266772Sjhb SBP_LOCK(sbp); 2052121185Ssimokawa} 2053121185Ssimokawa 2054121185Ssimokawastatic void 2055121185Ssimokawasbp_free_target(struct sbp_target *target) 2056121185Ssimokawa{ 2057121185Ssimokawa struct sbp_softc *sbp; 2058121185Ssimokawa struct fw_xfer *xfer, *next; 2059121185Ssimokawa int i; 2060121185Ssimokawa 2061121185Ssimokawa if (target->luns == NULL) 2062121185Ssimokawa return; 2063121185Ssimokawa sbp = target->sbp; 2064266772Sjhb SBP_LOCK_ASSERT(sbp); 2065266772Sjhb SBP_UNLOCK(sbp); 2066266772Sjhb callout_drain(&target->mgm_ocb_timeout); 2067266772Sjhb callout_drain(&target->scan_callout); 2068266772Sjhb SBP_LOCK(sbp); 2069121185Ssimokawa for (i = 0; i < target->num_lun; i++) 2070121185Ssimokawa sbp_free_sdev(target->luns[i]); 2071121185Ssimokawa 2072266772Sjhb STAILQ_FOREACH_SAFE(xfer, &target->xferlist, link, next) { 2073121185Ssimokawa fw_xfer_free_buf(xfer); 2074121185Ssimokawa } 2075121185Ssimokawa STAILQ_INIT(&target->xferlist); 2076121185Ssimokawa free(target->luns, M_SBP); 2077201758Smbr target->num_lun = 0; 2078121185Ssimokawa target->luns = NULL; 2079121185Ssimokawa target->fwdev = NULL; 2080121185Ssimokawa} 2081121185Ssimokawa 2082110145Ssimokawastatic int 2083103285Sikobsbp_detach(device_t dev) 2084103285Sikob{ 2085103285Sikob struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 2086103285Sikob struct firewire_comm *fc = sbp->fd.fc; 2087121185Ssimokawa int i; 2088103285Sikob 2089103285SikobSBP_DEBUG(0) 2090103285Sikob printf("sbp_detach\n"); 2091103285SikobEND_DEBUG 2092113584Ssimokawa 2093266772Sjhb SBP_LOCK(sbp); 2094272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) 2095110145Ssimokawa sbp_cam_detach_target(&sbp->targets[i]); 2096170374Ssimokawa 2097120660Ssimokawa xpt_async(AC_LOST_DEVICE, sbp->path, NULL); 2098111615Ssimokawa xpt_free_path(sbp->path); 2099103285Sikob xpt_bus_deregister(cam_sim_path(sbp->sim)); 2100170378Sgallatin cam_sim_free(sbp->sim, /*free_devq*/ TRUE); 2101110145Ssimokawa 2102110145Ssimokawa sbp_logout_all(sbp); 2103266772Sjhb SBP_UNLOCK(sbp); 2104113584Ssimokawa 2105110145Ssimokawa /* XXX wait for logout completion */ 2106167086Sjhb pause("sbpdtc", hz/2); 2107110145Ssimokawa 2108266772Sjhb SBP_LOCK(sbp); 2109272214Skan for (i = 0; i < SBP_NUM_TARGETS; i++) 2110121185Ssimokawa sbp_free_target(&sbp->targets[i]); 2111266772Sjhb SBP_UNLOCK(sbp); 2112113584Ssimokawa 2113110145Ssimokawa fw_bindremove(fc, &sbp->fwb); 2114169130Ssimokawa fw_xferlist_remove(&sbp->fwb.xferlist); 2115113584Ssimokawa 2116103285Sikob bus_dma_tag_destroy(sbp->dmat); 2117170374Ssimokawa mtx_destroy(&sbp->mtx); 2118110145Ssimokawa 2119103285Sikob return (0); 2120103285Sikob} 2121103285Sikob 2122103285Sikobstatic void 2123121185Ssimokawasbp_cam_detach_sdev(struct sbp_dev *sdev) 2124121185Ssimokawa{ 2125121185Ssimokawa if (sdev == NULL) 2126121185Ssimokawa return; 2127121185Ssimokawa if (sdev->status == SBP_DEV_DEAD) 2128121185Ssimokawa return; 2129121185Ssimokawa if (sdev->status == SBP_DEV_RESET) 2130121185Ssimokawa return; 2131266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2132170374Ssimokawa sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE); 2133121185Ssimokawa if (sdev->path) { 2134121185Ssimokawa xpt_release_devq(sdev->path, 2135121185Ssimokawa sdev->freeze, TRUE); 2136121185Ssimokawa sdev->freeze = 0; 2137121185Ssimokawa xpt_async(AC_LOST_DEVICE, sdev->path, NULL); 2138121185Ssimokawa xpt_free_path(sdev->path); 2139121185Ssimokawa sdev->path = NULL; 2140121185Ssimokawa } 2141121185Ssimokawa} 2142121185Ssimokawa 2143121185Ssimokawastatic void 2144110145Ssimokawasbp_cam_detach_target(struct sbp_target *target) 2145103285Sikob{ 2146103285Sikob int i; 2147103285Sikob 2148266772Sjhb SBP_LOCK_ASSERT(target->sbp); 2149103285Sikob if (target->luns != NULL) { 2150108529SsimokawaSBP_DEBUG(0) 2151103285Sikob printf("sbp_detach_target %d\n", target->target_id); 2152108529SsimokawaEND_DEBUG 2153111615Ssimokawa callout_stop(&target->scan_callout); 2154121185Ssimokawa for (i = 0; i < target->num_lun; i++) 2155121185Ssimokawa sbp_cam_detach_sdev(target->luns[i]); 2156103285Sikob } 2157103285Sikob} 2158103285Sikob 2159103285Sikobstatic void 2160114732Ssimokawasbp_target_reset(struct sbp_dev *sdev, int method) 2161114732Ssimokawa{ 2162114732Ssimokawa int i; 2163114732Ssimokawa struct sbp_target *target = sdev->target; 2164114732Ssimokawa struct sbp_dev *tsdev; 2165114732Ssimokawa 2166266772Sjhb SBP_LOCK_ASSERT(target->sbp); 2167114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 2168121185Ssimokawa tsdev = target->luns[i]; 2169121185Ssimokawa if (tsdev == NULL) 2170121185Ssimokawa continue; 2171114732Ssimokawa if (tsdev->status == SBP_DEV_DEAD) 2172114732Ssimokawa continue; 2173114732Ssimokawa if (tsdev->status == SBP_DEV_RESET) 2174114732Ssimokawa continue; 2175114732Ssimokawa xpt_freeze_devq(tsdev->path, 1); 2176272214Skan tsdev->freeze++; 2177114732Ssimokawa sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT); 2178114732Ssimokawa if (method == 2) 2179114732Ssimokawa tsdev->status = SBP_DEV_LOGIN; 2180114732Ssimokawa } 2181272214Skan switch (method) { 2182114732Ssimokawa case 1: 2183114732Ssimokawa printf("target reset\n"); 2184114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); 2185114732Ssimokawa break; 2186114732Ssimokawa case 2: 2187114732Ssimokawa printf("reset start\n"); 2188114732Ssimokawa sbp_reset_start(sdev); 2189114732Ssimokawa break; 2190114732Ssimokawa } 2191272214Skan 2192114732Ssimokawa} 2193114732Ssimokawa 2194114732Ssimokawastatic void 2195114732Ssimokawasbp_mgm_timeout(void *arg) 2196114732Ssimokawa{ 2197114732Ssimokawa struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2198114732Ssimokawa struct sbp_dev *sdev = ocb->sdev; 2199114732Ssimokawa struct sbp_target *target = sdev->target; 2200114732Ssimokawa 2201266772Sjhb SBP_LOCK_ASSERT(target->sbp); 2202188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2203188756Ssbruno "%s:%s request timeout(mgm orb:0x%08x)\n", 2204188756Ssbruno __func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr); 2205114732Ssimokawa target->mgm_ocb_cur = NULL; 2206114732Ssimokawa sbp_free_ocb(sdev, ocb); 2207114732Ssimokawa#if 0 2208114732Ssimokawa /* XXX */ 2209121185Ssimokawa printf("run next request\n"); 2210114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 2211114732Ssimokawa#endif 2212188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2213188756Ssbruno "%s:%s reset start\n", 2214188756Ssbruno __func__, sdev->bustgtlun); 2215114732Ssimokawa sbp_reset_start(sdev); 2216114732Ssimokawa} 2217114732Ssimokawa 2218114732Ssimokawastatic void 2219103285Sikobsbp_timeout(void *arg) 2220103285Sikob{ 2221103285Sikob struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2222103285Sikob struct sbp_dev *sdev = ocb->sdev; 2223103285Sikob 2224188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2225188756Ssbruno "%s:%s request timeout(cmd orb:0x%08x) ... ", 2226188756Ssbruno __func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr); 2227103285Sikob 2228266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2229272214Skan sdev->timeout++; 2230272214Skan switch (sdev->timeout) { 2231114732Ssimokawa case 1: 2232110336Ssimokawa printf("agent reset\n"); 2233114732Ssimokawa xpt_freeze_devq(sdev->path, 1); 2234272214Skan sdev->freeze++; 2235114732Ssimokawa sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); 2236110336Ssimokawa sbp_agent_reset(sdev); 2237114732Ssimokawa break; 2238114732Ssimokawa case 2: 2239114732Ssimokawa case 3: 2240114732Ssimokawa sbp_target_reset(sdev, sdev->timeout - 1); 2241114732Ssimokawa break; 2242114732Ssimokawa#if 0 2243114732Ssimokawa default: 2244114732Ssimokawa /* XXX give up */ 2245114732Ssimokawa sbp_cam_detach_target(target); 2246114732Ssimokawa if (target->luns != NULL) 2247114732Ssimokawa free(target->luns, M_SBP); 2248201758Smbr target->num_lun = 0; 2249114732Ssimokawa target->luns = NULL; 2250114732Ssimokawa target->fwdev = NULL; 2251114732Ssimokawa#endif 2252110336Ssimokawa } 2253103285Sikob} 2254103285Sikob 2255103285Sikobstatic void 2256266772Sjhbsbp_action(struct cam_sim *sim, union ccb *ccb) 2257103285Sikob{ 2258103285Sikob 2259103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)sim->softc; 2260103285Sikob struct sbp_target *target = NULL; 2261103285Sikob struct sbp_dev *sdev = NULL; 2262103285Sikob 2263266772Sjhb if (sbp != NULL) 2264266772Sjhb SBP_LOCK_ASSERT(sbp); 2265103285Sikob /* target:lun -> sdev mapping */ 2266103285Sikob if (sbp != NULL 2267103285Sikob && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD 2268103285Sikob && ccb->ccb_h.target_id < SBP_NUM_TARGETS) { 2269103285Sikob target = &sbp->targets[ccb->ccb_h.target_id]; 2270103285Sikob if (target->fwdev != NULL 2271103285Sikob && ccb->ccb_h.target_lun != CAM_LUN_WILDCARD 2272103285Sikob && ccb->ccb_h.target_lun < target->num_lun) { 2273121185Ssimokawa sdev = target->luns[ccb->ccb_h.target_lun]; 2274121185Ssimokawa if (sdev != NULL && sdev->status != SBP_DEV_ATTACHED && 2275103285Sikob sdev->status != SBP_DEV_PROBE) 2276103285Sikob sdev = NULL; 2277103285Sikob } 2278103285Sikob } 2279103285Sikob 2280103285SikobSBP_DEBUG(1) 2281103285Sikob if (sdev == NULL) 2282257381Snwhitehorn printf("invalid target %d lun %jx\n", 2283257381Snwhitehorn ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun); 2284103285SikobEND_DEBUG 2285103285Sikob 2286103285Sikob switch (ccb->ccb_h.func_code) { 2287103285Sikob case XPT_SCSI_IO: 2288103285Sikob case XPT_RESET_DEV: 2289103285Sikob case XPT_GET_TRAN_SETTINGS: 2290103285Sikob case XPT_SET_TRAN_SETTINGS: 2291103285Sikob case XPT_CALC_GEOMETRY: 2292103285Sikob if (sdev == NULL) { 2293103285SikobSBP_DEBUG(1) 2294257381Snwhitehorn printf("%s:%d:%jx:func_code 0x%04x: " 2295103285Sikob "Invalid target (target needed)\n", 2296103285Sikob device_get_nameunit(sbp->fd.dev), 2297257381Snwhitehorn ccb->ccb_h.target_id, 2298257381Snwhitehorn (uintmax_t)ccb->ccb_h.target_lun, 2299103285Sikob ccb->ccb_h.func_code); 2300103285SikobEND_DEBUG 2301103285Sikob 2302108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2303103285Sikob xpt_done(ccb); 2304103285Sikob return; 2305103285Sikob } 2306103285Sikob break; 2307103285Sikob case XPT_PATH_INQ: 2308103285Sikob case XPT_NOOP: 2309103285Sikob /* The opcodes sometimes aimed at a target (sc is valid), 2310103285Sikob * sometimes aimed at the SIM (sc is invalid and target is 2311103285Sikob * CAM_TARGET_WILDCARD) 2312103285Sikob */ 2313272214Skan if (sbp == NULL && 2314103285Sikob ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 2315103285SikobSBP_DEBUG(0) 2316257381Snwhitehorn printf("%s:%d:%jx func_code 0x%04x: " 2317103285Sikob "Invalid target (no wildcard)\n", 2318103285Sikob device_get_nameunit(sbp->fd.dev), 2319257381Snwhitehorn ccb->ccb_h.target_id, 2320257381Snwhitehorn (uintmax_t)ccb->ccb_h.target_lun, 2321103285Sikob ccb->ccb_h.func_code); 2322103285SikobEND_DEBUG 2323108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2324103285Sikob xpt_done(ccb); 2325103285Sikob return; 2326103285Sikob } 2327103285Sikob break; 2328103285Sikob default: 2329103285Sikob /* XXX Hm, we should check the input parameters */ 2330103285Sikob break; 2331103285Sikob } 2332103285Sikob 2333103285Sikob switch (ccb->ccb_h.func_code) { 2334103285Sikob case XPT_SCSI_IO: 2335103285Sikob { 2336103285Sikob struct ccb_scsiio *csio; 2337103285Sikob struct sbp_ocb *ocb; 2338113584Ssimokawa int speed; 2339106506Ssimokawa void *cdb; 2340103285Sikob 2341103285Sikob csio = &ccb->csio; 2342170374Ssimokawa mtx_assert(sim->mtx, MA_OWNED); 2343103285Sikob 2344121185SsimokawaSBP_DEBUG(2) 2345257381Snwhitehorn printf("%s:%d:%jx XPT_SCSI_IO: " 2346103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 2347103285Sikob ", flags: 0x%02x, " 2348103285Sikob "%db cmd/%db data/%db sense\n", 2349103285Sikob device_get_nameunit(sbp->fd.dev), 2350257381Snwhitehorn ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun, 2351103285Sikob csio->cdb_io.cdb_bytes[0], 2352103285Sikob csio->cdb_io.cdb_bytes[1], 2353103285Sikob csio->cdb_io.cdb_bytes[2], 2354103285Sikob csio->cdb_io.cdb_bytes[3], 2355103285Sikob csio->cdb_io.cdb_bytes[4], 2356103285Sikob csio->cdb_io.cdb_bytes[5], 2357103285Sikob csio->cdb_io.cdb_bytes[6], 2358103285Sikob csio->cdb_io.cdb_bytes[7], 2359103285Sikob csio->cdb_io.cdb_bytes[8], 2360103285Sikob csio->cdb_io.cdb_bytes[9], 2361103285Sikob ccb->ccb_h.flags & CAM_DIR_MASK, 2362103285Sikob csio->cdb_len, csio->dxfer_len, 2363103285Sikob csio->sense_len); 2364103285SikobEND_DEBUG 2365272214Skan if (sdev == NULL) { 2366103285Sikob ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2367103285Sikob xpt_done(ccb); 2368103285Sikob return; 2369103285Sikob } 2370103285Sikob#if 0 2371103285Sikob /* if we are in probe stage, pass only probe commands */ 2372103285Sikob if (sdev->status == SBP_DEV_PROBE) { 2373103285Sikob char *name; 2374103285Sikob name = xpt_path_periph(ccb->ccb_h.path)->periph_name; 2375103285Sikob printf("probe stage, periph name: %s\n", name); 2376103285Sikob if (strcmp(name, "probe") != 0) { 2377103285Sikob ccb->ccb_h.status = CAM_REQUEUE_REQ; 2378103285Sikob xpt_done(ccb); 2379103285Sikob return; 2380103285Sikob } 2381103285Sikob } 2382103285Sikob#endif 2383122528Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 2384170807Ssimokawa ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2385127468Ssimokawa if (sdev->freeze == 0) { 2386127468Ssimokawa xpt_freeze_devq(sdev->path, 1); 2387272214Skan sdev->freeze++; 2388127468Ssimokawa } 2389122528Ssimokawa xpt_done(ccb); 2390103285Sikob return; 2391122528Ssimokawa } 2392113584Ssimokawa 2393103285Sikob ocb->flags = OCB_ACT_CMD; 2394103285Sikob ocb->sdev = sdev; 2395103285Sikob ocb->ccb = ccb; 2396103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 2397258780Seadler ocb->orb[0] = htonl(1U << 31); 2398103285Sikob ocb->orb[1] = 0; 2399272214Skan ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS) << 16)); 2400113584Ssimokawa ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); 2401103285Sikob speed = min(target->fwdev->speed, max_speed); 2402103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) 2403103285Sikob | ORB_CMD_MAXP(speed + 7)); 2404272214Skan if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2405103285Sikob ocb->orb[4] |= htonl(ORB_CMD_IN); 2406103285Sikob } 2407103285Sikob 2408106506Ssimokawa if (csio->ccb_h.flags & CAM_CDB_POINTER) 2409106506Ssimokawa cdb = (void *)csio->cdb_io.cdb_ptr; 2410106506Ssimokawa else 2411106506Ssimokawa cdb = (void *)&csio->cdb_io.cdb_bytes; 2412120660Ssimokawa bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len); 2413103285Sikob/* 2414103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3])); 2415103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); 2416103285Sikob*/ 2417103285Sikob if (ccb->csio.dxfer_len > 0) { 2418247109Simp int error; 2419103285Sikob 2420246713Skib error = bus_dmamap_load_ccb(/*dma tag*/sbp->dmat, 2421103285Sikob /*dma map*/ocb->dmamap, 2422246713Skib ccb, 2423103285Sikob sbp_execute_ocb, 2424103285Sikob ocb, 2425103285Sikob /*flags*/0); 2426113584Ssimokawa if (error) 2427113584Ssimokawa printf("sbp: bus_dmamap_load error %d\n", error); 2428103285Sikob } else 2429103285Sikob sbp_execute_ocb(ocb, NULL, 0, 0); 2430103285Sikob break; 2431103285Sikob } 2432103285Sikob case XPT_CALC_GEOMETRY: 2433103285Sikob { 2434103285Sikob struct ccb_calc_geometry *ccg; 2435116351Snjl 2436103285Sikob ccg = &ccb->ccg; 2437103285Sikob if (ccg->block_size == 0) { 2438266772Sjhb printf("sbp_action: block_size is 0.\n"); 2439103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2440103285Sikob xpt_done(ccb); 2441103285Sikob break; 2442103285Sikob } 2443103285SikobSBP_DEBUG(1) 2444257381Snwhitehorn printf("%s:%d:%d:%jx:XPT_CALC_GEOMETRY: " 2445114540Sjake "Volume size = %jd\n", 2446114927Ssimokawa device_get_nameunit(sbp->fd.dev), 2447114927Ssimokawa cam_sim_path(sbp->sim), 2448257381Snwhitehorn ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun, 2449271795Swill (uintmax_t)ccg->volume_size); 2450103285SikobEND_DEBUG 2451103285Sikob 2452116351Snjl cam_calc_geometry(ccg, /*extended*/1); 2453103285Sikob xpt_done(ccb); 2454103285Sikob break; 2455103285Sikob } 2456103285Sikob case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2457103285Sikob { 2458103285Sikob 2459103285SikobSBP_DEBUG(1) 2460103285Sikob printf("%s:%d:XPT_RESET_BUS: \n", 2461103285Sikob device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); 2462103285SikobEND_DEBUG 2463103285Sikob 2464103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2465103285Sikob xpt_done(ccb); 2466103285Sikob break; 2467103285Sikob } 2468103285Sikob case XPT_PATH_INQ: /* Path routing inquiry */ 2469103285Sikob { 2470103285Sikob struct ccb_pathinq *cpi = &ccb->cpi; 2471272214Skan 2472103285SikobSBP_DEBUG(1) 2473257381Snwhitehorn printf("%s:%d:%jx XPT_PATH_INQ:.\n", 2474103285Sikob device_get_nameunit(sbp->fd.dev), 2475257381Snwhitehorn ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun); 2476103285SikobEND_DEBUG 2477103285Sikob cpi->version_num = 1; /* XXX??? */ 2478111615Ssimokawa cpi->hba_inquiry = PI_TAG_ABLE; 2479103285Sikob cpi->target_sprt = 0; 2480118105Snjl cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE; 2481103285Sikob cpi->hba_eng_cnt = 0; 2482103285Sikob cpi->max_target = SBP_NUM_TARGETS - 1; 2483103285Sikob cpi->max_lun = SBP_NUM_LUNS - 1; 2484103285Sikob cpi->initiator_id = SBP_INITIATOR; 2485103285Sikob cpi->bus_id = sim->bus_id; 2486103285Sikob cpi->base_transfer_speed = 400 * 1000 / 8; 2487103285Sikob strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2488103285Sikob strncpy(cpi->hba_vid, "SBP", HBA_IDLEN); 2489103285Sikob strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); 2490103285Sikob cpi->unit_number = sim->unit_number; 2491163816Smjacob cpi->transport = XPORT_SPI; /* XX should have a FireWire */ 2492163816Smjacob cpi->transport_version = 2; 2493163816Smjacob cpi->protocol = PROTO_SCSI; 2494163816Smjacob cpi->protocol_version = SCSI_REV_2; 2495103285Sikob 2496103285Sikob cpi->ccb_h.status = CAM_REQ_CMP; 2497103285Sikob xpt_done(ccb); 2498103285Sikob break; 2499103285Sikob } 2500103285Sikob case XPT_GET_TRAN_SETTINGS: 2501103285Sikob { 2502103285Sikob struct ccb_trans_settings *cts = &ccb->cts; 2503163816Smjacob struct ccb_trans_settings_scsi *scsi = 2504163816Smjacob &cts->proto_specific.scsi; 2505163816Smjacob struct ccb_trans_settings_spi *spi = 2506163816Smjacob &cts->xport_specific.spi; 2507163816Smjacob 2508163816Smjacob cts->protocol = PROTO_SCSI; 2509163816Smjacob cts->protocol_version = SCSI_REV_2; 2510163816Smjacob cts->transport = XPORT_SPI; /* should have a FireWire */ 2511163816Smjacob cts->transport_version = 2; 2512163816Smjacob spi->valid = CTS_SPI_VALID_DISC; 2513163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2514163816Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 2515163816Smjacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2516103285SikobSBP_DEBUG(1) 2517257381Snwhitehorn printf("%s:%d:%jx XPT_GET_TRAN_SETTINGS:.\n", 2518103285Sikob device_get_nameunit(sbp->fd.dev), 2519257381Snwhitehorn ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun); 2520103285SikobEND_DEBUG 2521103285Sikob cts->ccb_h.status = CAM_REQ_CMP; 2522103285Sikob xpt_done(ccb); 2523103285Sikob break; 2524103285Sikob } 2525103285Sikob case XPT_ABORT: 2526103285Sikob ccb->ccb_h.status = CAM_UA_ABORT; 2527103285Sikob xpt_done(ccb); 2528103285Sikob break; 2529111615Ssimokawa case XPT_SET_TRAN_SETTINGS: 2530111615Ssimokawa /* XXX */ 2531103285Sikob default: 2532103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2533103285Sikob xpt_done(ccb); 2534103285Sikob break; 2535103285Sikob } 2536103285Sikob return; 2537103285Sikob} 2538103285Sikob 2539103285Sikobstatic void 2540272214Skansbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error) 2541103285Sikob{ 2542103285Sikob int i; 2543103285Sikob struct sbp_ocb *ocb; 2544103285Sikob struct sbp_ocb *prev; 2545105633Ssimokawa bus_dma_segment_t *s; 2546103285Sikob 2547103285Sikob if (error) 2548103285Sikob printf("sbp_execute_ocb: error=%d\n", error); 2549103285Sikob 2550103285Sikob ocb = (struct sbp_ocb *)arg; 2551113584Ssimokawa 2552121185SsimokawaSBP_DEBUG(2) 2553113584Ssimokawa printf("sbp_execute_ocb: seg %d", seg); 2554113584Ssimokawa for (i = 0; i < seg; i++) 2555113972Ssimokawa printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr, 2556113972Ssimokawa (uintmax_t)segments[i].ds_len); 2557113584Ssimokawa printf("\n"); 2558113584SsimokawaEND_DEBUG 2559113584Ssimokawa 2560103285Sikob if (seg == 1) { 2561103285Sikob /* direct pointer */ 2562113474Ssimokawa s = &segments[0]; 2563113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2564113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2565113474Ssimokawa ocb->orb[3] = htonl(s->ds_addr); 2566113474Ssimokawa ocb->orb[4] |= htonl(s->ds_len); 2567272214Skan } else if (seg > 1) { 2568103285Sikob /* page table */ 2569103285Sikob for (i = 0; i < seg; i++) { 2570105633Ssimokawa s = &segments[i]; 2571108877SsimokawaSBP_DEBUG(0) 2572108877Ssimokawa /* XXX LSI Logic "< 16 byte" bug might be hit */ 2573105633Ssimokawa if (s->ds_len < 16) 2574105633Ssimokawa printf("sbp_execute_ocb: warning, " 2575106543Ssimokawa "segment length(%zd) is less than 16." 2576272214Skan "(seg=%d/%d)\n", (size_t)s->ds_len, i + 1, seg); 2577108877SsimokawaEND_DEBUG 2578113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2579113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2580105633Ssimokawa ocb->ind_ptr[i].hi = htonl(s->ds_len << 16); 2581105633Ssimokawa ocb->ind_ptr[i].lo = htonl(s->ds_addr); 2582103285Sikob } 2583103285Sikob ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg); 2584103285Sikob } 2585272214Skan 2586113584Ssimokawa if (seg > 0) 2587113584Ssimokawa bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap, 2588113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2589113584Ssimokawa BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 2590103285Sikob prev = sbp_enqueue_ocb(ocb->sdev, ocb); 2591113584Ssimokawa fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE); 2592127468Ssimokawa if (use_doorbell) { 2593127468Ssimokawa if (prev == NULL) { 2594127468Ssimokawa if (ocb->sdev->last_ocb != NULL) 2595127468Ssimokawa sbp_doorbell(ocb->sdev); 2596127468Ssimokawa else 2597272214Skan sbp_orb_pointer(ocb->sdev, ocb); 2598127468Ssimokawa } 2599127468Ssimokawa } else { 2600127468Ssimokawa if (prev == NULL || (ocb->sdev->flags & ORB_LINK_DEAD) != 0) { 2601127468Ssimokawa ocb->sdev->flags &= ~ORB_LINK_DEAD; 2602272214Skan sbp_orb_pointer(ocb->sdev, ocb); 2603127468Ssimokawa } 2604120842Ssimokawa } 2605103285Sikob} 2606103285Sikob 2607103285Sikobstatic void 2608103285Sikobsbp_poll(struct cam_sim *sim) 2609272214Skan{ 2610120847Ssimokawa struct sbp_softc *sbp; 2611120847Ssimokawa struct firewire_comm *fc; 2612120847Ssimokawa 2613120847Ssimokawa sbp = (struct sbp_softc *)sim->softc; 2614120847Ssimokawa fc = sbp->fd.fc; 2615120847Ssimokawa 2616120847Ssimokawa fc->poll(fc, 0, -1); 2617120847Ssimokawa 2618103285Sikob return; 2619103285Sikob} 2620120847Ssimokawa 2621103285Sikobstatic struct sbp_ocb * 2622111615Ssimokawasbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status) 2623103285Sikob{ 2624103285Sikob struct sbp_ocb *ocb; 2625103285Sikob struct sbp_ocb *next; 2626266772Sjhb int order = 0; 2627103285Sikob 2628103285SikobSBP_DEBUG(1) 2629188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2630188756Ssbruno "%s:%s 0x%08x src %d\n", 2631188756Ssbruno __func__, sdev->bustgtlun, ntohl(sbp_status->orb_lo), sbp_status->src); 2632103285SikobEND_DEBUG 2633266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2634266772Sjhb STAILQ_FOREACH_SAFE(ocb, &sdev->ocbs, ocb, next) { 2635111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 2636103285Sikob /* found */ 2637111819Ssimokawa STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); 2638103285Sikob if (ocb->ccb != NULL) 2639266772Sjhb callout_stop(&ocb->timer); 2640113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2641113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, 2642113584Ssimokawa ocb->dmamap, 2643113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2644113584Ssimokawa BUS_DMASYNC_POSTREAD : 2645113584Ssimokawa BUS_DMASYNC_POSTWRITE); 2646113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, 2647113584Ssimokawa ocb->dmamap); 2648103285Sikob } 2649127468Ssimokawa if (!use_doorbell) { 2650127468Ssimokawa if (sbp_status->src == SRC_NO_NEXT) { 2651127468Ssimokawa if (next != NULL) 2652272214Skan sbp_orb_pointer(sdev, next); 2653127468Ssimokawa else if (order > 0) { 2654127468Ssimokawa /* 2655127468Ssimokawa * Unordered execution 2656127468Ssimokawa * We need to send pointer for 2657127468Ssimokawa * next ORB 2658127468Ssimokawa */ 2659127468Ssimokawa sdev->flags |= ORB_LINK_DEAD; 2660127468Ssimokawa } 2661120842Ssimokawa } 2662127468Ssimokawa } else { 2663127468Ssimokawa /* 2664127468Ssimokawa * XXX this is not correct for unordered 2665272214Skan * execution. 2666127468Ssimokawa */ 2667170807Ssimokawa if (sdev->last_ocb != NULL) { 2668127468Ssimokawa sbp_free_ocb(sdev, sdev->last_ocb); 2669170807Ssimokawa } 2670127468Ssimokawa sdev->last_ocb = ocb; 2671127468Ssimokawa if (next != NULL && 2672127468Ssimokawa sbp_status->src == SRC_NO_NEXT) 2673127468Ssimokawa sbp_doorbell(sdev); 2674120842Ssimokawa } 2675103285Sikob break; 2676111819Ssimokawa } else 2677272214Skan order++; 2678103285Sikob } 2679103285SikobSBP_DEBUG(0) 2680103285Sikob if (ocb && order > 0) { 2681188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2682188756Ssbruno "%s:%s unordered execution order:%d\n", 2683188756Ssbruno __func__, sdev->bustgtlun, order); 2684103285Sikob } 2685103285SikobEND_DEBUG 2686103285Sikob return (ocb); 2687103285Sikob} 2688103285Sikob 2689103285Sikobstatic struct sbp_ocb * 2690103285Sikobsbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2691103285Sikob{ 2692127468Ssimokawa struct sbp_ocb *prev, *prev2; 2693103285Sikob 2694266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2695121185SsimokawaSBP_DEBUG(1) 2696188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2697188756Ssbruno "%s:%s 0x%08jx\n", __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr); 2698103285SikobEND_DEBUG 2699127468Ssimokawa prev2 = prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb); 2700103285Sikob STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb); 2701103285Sikob 2702274819Ssmh if (ocb->ccb != NULL) { 2703274819Ssmh callout_reset_sbt(&ocb->timer, 2704274819Ssmh SBT_1MS * ocb->ccb->ccb_h.timeout, 0, sbp_timeout, 2705274819Ssmh ocb, 0); 2706274819Ssmh } 2707103285Sikob 2708127468Ssimokawa if (use_doorbell && prev == NULL) 2709127468Ssimokawa prev2 = sdev->last_ocb; 2710127468Ssimokawa 2711170807Ssimokawa if (prev2 != NULL && (ocb->sdev->flags & ORB_LINK_DEAD) == 0) { 2712170807SsimokawaSBP_DEBUG(1) 2713120842Ssimokawa printf("linking chain 0x%jx -> 0x%jx\n", 2714127468Ssimokawa (uintmax_t)prev2->bus_addr, (uintmax_t)ocb->bus_addr); 2715103285SikobEND_DEBUG 2716170724Ssimokawa /* 2717170724Ssimokawa * Suppress compiler optimization so that orb[1] must be written first. 2718170724Ssimokawa * XXX We may need an explicit memory barrier for other architectures 2719170724Ssimokawa * other than i386/amd64. 2720170724Ssimokawa */ 2721170724Ssimokawa *(volatile uint32_t *)&prev2->orb[1] = htonl(ocb->bus_addr); 2722170724Ssimokawa *(volatile uint32_t *)&prev2->orb[0] = 0; 2723103285Sikob } 2724103285Sikob 2725103285Sikob return prev; 2726103285Sikob} 2727103285Sikob 2728103285Sikobstatic struct sbp_ocb * 2729113584Ssimokawasbp_get_ocb(struct sbp_dev *sdev) 2730103285Sikob{ 2731103285Sikob struct sbp_ocb *ocb; 2732170374Ssimokawa 2733266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2734113584Ssimokawa ocb = STAILQ_FIRST(&sdev->free_ocbs); 2735103285Sikob if (ocb == NULL) { 2736127468Ssimokawa sdev->flags |= ORB_SHORTAGE; 2737103285Sikob printf("ocb shortage!!!\n"); 2738103285Sikob return NULL; 2739103285Sikob } 2740113584Ssimokawa STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb); 2741103285Sikob ocb->ccb = NULL; 2742103285Sikob return (ocb); 2743103285Sikob} 2744103285Sikob 2745103285Sikobstatic void 2746113584Ssimokawasbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2747103285Sikob{ 2748103285Sikob ocb->flags = 0; 2749103285Sikob ocb->ccb = NULL; 2750170374Ssimokawa 2751266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2752113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); 2753127468Ssimokawa if ((sdev->flags & ORB_SHORTAGE) != 0) { 2754127468Ssimokawa int count; 2755127468Ssimokawa 2756127468Ssimokawa sdev->flags &= ~ORB_SHORTAGE; 2757127468Ssimokawa count = sdev->freeze; 2758127468Ssimokawa sdev->freeze = 0; 2759127468Ssimokawa xpt_release_devq(sdev->path, count, TRUE); 2760127468Ssimokawa } 2761103285Sikob} 2762103285Sikob 2763103285Sikobstatic void 2764103285Sikobsbp_abort_ocb(struct sbp_ocb *ocb, int status) 2765103285Sikob{ 2766103285Sikob struct sbp_dev *sdev; 2767103285Sikob 2768103285Sikob sdev = ocb->sdev; 2769266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2770113584SsimokawaSBP_DEBUG(0) 2771188756Ssbruno device_printf(sdev->target->sbp->fd.dev, 2772188756Ssbruno "%s:%s 0x%jx\n", __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr); 2773113584SsimokawaEND_DEBUG 2774113584SsimokawaSBP_DEBUG(1) 2775105792Ssimokawa if (ocb->ccb != NULL) 2776105792Ssimokawa sbp_print_scsi_cmd(ocb); 2777103285SikobEND_DEBUG 2778113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2779113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap, 2780113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2781113584Ssimokawa BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 2782113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap); 2783113584Ssimokawa } 2784111819Ssimokawa if (ocb->ccb != NULL) { 2785266772Sjhb callout_stop(&ocb->timer); 2786103285Sikob ocb->ccb->ccb_h.status = status; 2787103285Sikob xpt_done(ocb->ccb); 2788103285Sikob } 2789113584Ssimokawa sbp_free_ocb(sdev, ocb); 2790103285Sikob} 2791103285Sikob 2792103285Sikobstatic void 2793103285Sikobsbp_abort_all_ocbs(struct sbp_dev *sdev, int status) 2794103285Sikob{ 2795105792Ssimokawa struct sbp_ocb *ocb, *next; 2796105792Ssimokawa STAILQ_HEAD(, sbp_ocb) temp; 2797103285Sikob 2798170807Ssimokawa STAILQ_INIT(&temp); 2799266772Sjhb SBP_LOCK_ASSERT(sdev->target->sbp); 2800170807Ssimokawa STAILQ_CONCAT(&temp, &sdev->ocbs); 2801105792Ssimokawa STAILQ_INIT(&sdev->ocbs); 2802170807Ssimokawa 2803266772Sjhb STAILQ_FOREACH_SAFE(ocb, &temp, ocb, next) { 2804103285Sikob sbp_abort_ocb(ocb, status); 2805103285Sikob } 2806127468Ssimokawa if (sdev->last_ocb != NULL) { 2807127468Ssimokawa sbp_free_ocb(sdev, sdev->last_ocb); 2808127468Ssimokawa sdev->last_ocb = NULL; 2809127468Ssimokawa } 2810103285Sikob} 2811103285Sikob 2812103285Sikobstatic devclass_t sbp_devclass; 2813103285Sikob 2814103285Sikobstatic device_method_t sbp_methods[] = { 2815103285Sikob /* device interface */ 2816103285Sikob DEVMETHOD(device_identify, sbp_identify), 2817103285Sikob DEVMETHOD(device_probe, sbp_probe), 2818103285Sikob DEVMETHOD(device_attach, sbp_attach), 2819103285Sikob DEVMETHOD(device_detach, sbp_detach), 2820110145Ssimokawa DEVMETHOD(device_shutdown, sbp_shutdown), 2821103285Sikob 2822103285Sikob { 0, 0 } 2823103285Sikob}; 2824103285Sikob 2825103285Sikobstatic driver_t sbp_driver = { 2826103285Sikob "sbp", 2827103285Sikob sbp_methods, 2828103285Sikob sizeof(struct sbp_softc), 2829103285Sikob}; 2830103285SikobDRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0); 2831103285SikobMODULE_VERSION(sbp, 1); 2832103285SikobMODULE_DEPEND(sbp, firewire, 1, 1, 1); 2833103285SikobMODULE_DEPEND(sbp, cam, 1, 1, 1); 2834