sbp.c revision 170724
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. 33103285Sikob * 34103285Sikob * $FreeBSD: head/sys/dev/firewire/sbp.c 170724 2007-06-14 12:52:13Z simokawa $ 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> 46127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 47117126Sscottl#include <sys/lock.h> 48117126Sscottl#include <sys/mutex.h> 49117732Ssimokawa#endif 50103285Sikob 51127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500106 52112136Ssimokawa#include <sys/devicestat.h> /* for struct devstat */ 53112136Ssimokawa#endif 54103285Sikob 55127468Ssimokawa#ifdef __DragonFly__ 56127468Ssimokawa#include <bus/cam/cam.h> 57127468Ssimokawa#include <bus/cam/cam_ccb.h> 58127468Ssimokawa#include <bus/cam/cam_sim.h> 59127468Ssimokawa#include <bus/cam/cam_xpt_sim.h> 60127468Ssimokawa#include <bus/cam/cam_debug.h> 61127468Ssimokawa#include <bus/cam/cam_periph.h> 62127468Ssimokawa#include <bus/cam/scsi/scsi_all.h> 63127468Ssimokawa 64127468Ssimokawa#include <bus/firewire/firewire.h> 65127468Ssimokawa#include <bus/firewire/firewirereg.h> 66127468Ssimokawa#include <bus/firewire/fwdma.h> 67127468Ssimokawa#include <bus/firewire/iec13213.h> 68127468Ssimokawa#include "sbp.h" 69127468Ssimokawa#else 70103285Sikob#include <cam/cam.h> 71103285Sikob#include <cam/cam_ccb.h> 72103285Sikob#include <cam/cam_sim.h> 73103285Sikob#include <cam/cam_xpt_sim.h> 74103285Sikob#include <cam/cam_debug.h> 75103285Sikob#include <cam/cam_periph.h> 76103285Sikob#include <cam/scsi/scsi_all.h> 77103285Sikob 78103285Sikob#include <dev/firewire/firewire.h> 79103285Sikob#include <dev/firewire/firewirereg.h> 80113584Ssimokawa#include <dev/firewire/fwdma.h> 81103285Sikob#include <dev/firewire/iec13213.h> 82120660Ssimokawa#include <dev/firewire/sbp.h> 83127468Ssimokawa#endif 84103285Sikob 85103285Sikob#define ccb_sdev_ptr spriv_ptr0 86103285Sikob#define ccb_sbp_ptr spriv_ptr1 87103285Sikob 88111615Ssimokawa#define SBP_NUM_TARGETS 8 /* MAX 64 */ 89121185Ssimokawa/* 90121185Ssimokawa * Scan_bus doesn't work for more than 8 LUNs 91121185Ssimokawa * because of CAM_SCSI2_MAXLUN in cam_xpt.c 92121185Ssimokawa */ 93121185Ssimokawa#define SBP_NUM_LUNS 64 94167622Ssimokawa#define SBP_MAXPHYS MIN(MAXPHYS, (512*1024) /* 512KB */) 95113584Ssimokawa#define SBP_DMA_SIZE PAGE_SIZE 96113584Ssimokawa#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res) 97113584Ssimokawa#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb)) 98103285Sikob#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) 99113584Ssimokawa 100111615Ssimokawa/* 101111615Ssimokawa * STATUS FIFO addressing 102111615Ssimokawa * bit 103111615Ssimokawa * ----------------------- 104130532Sdfr * 0- 1( 2): 0 (alignment) 105111615Ssimokawa * 2- 7( 6): target 106111615Ssimokawa * 8-15( 8): lun 107120660Ssimokawa * 16-31( 8): reserved 108111615Ssimokawa * 32-47(16): SBP_BIND_HI 109111615Ssimokawa * 48-64(16): bus_id, node_id 110111615Ssimokawa */ 111103285Sikob#define SBP_BIND_HI 0x1 112120660Ssimokawa#define SBP_DEV2ADDR(t, l) \ 113120660Ssimokawa (((u_int64_t)SBP_BIND_HI << 32) \ 114120660Ssimokawa | (((l) & 0xff) << 8) \ 115120660Ssimokawa | (((t) & 0x3f) << 2)) 116103285Sikob#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f) 117103285Sikob#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff) 118120660Ssimokawa#define SBP_INITIATOR 7 119103285Sikob 120103285Sikobstatic char *orb_fun_name[] = { 121120660Ssimokawa ORB_FUN_NAMES 122103285Sikob}; 123103285Sikob 124111203Ssimokawastatic int debug = 0; 125103285Sikobstatic int auto_login = 1; 126124251Ssimokawastatic int max_speed = -1; 127111199Ssimokawastatic int sbp_cold = 1; 128122387Ssimokawastatic int ex_login = 1; 129122387Ssimokawastatic int login_delay = 1000; /* msec */ 130122387Ssimokawastatic int scan_delay = 500; /* msec */ 131127468Ssimokawastatic int use_doorbell = 0; 132127468Ssimokawastatic int sbp_tags = 0; 133103285Sikob 134103285SikobSYSCTL_DECL(_hw_firewire); 135103285SikobSYSCTL_NODE(_hw_firewire, OID_AUTO, sbp, CTLFLAG_RD, 0, "SBP-II Subsystem"); 136103285SikobSYSCTL_INT(_debug, OID_AUTO, sbp_debug, CTLFLAG_RW, &debug, 0, 137103285Sikob "SBP debug flag"); 138103285SikobSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RW, &auto_login, 0, 139103285Sikob "SBP perform login automatically"); 140103285SikobSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0, 141103285Sikob "SBP transfer max speed"); 142121792SsimokawaSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, exclusive_login, CTLFLAG_RW, 143130677Ssimokawa &ex_login, 0, "SBP enable exclusive login"); 144122387SsimokawaSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, login_delay, CTLFLAG_RW, 145122387Ssimokawa &login_delay, 0, "SBP login delay in msec"); 146122387SsimokawaSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, scan_delay, CTLFLAG_RW, 147122387Ssimokawa &scan_delay, 0, "SBP scan delay in msec"); 148127468SsimokawaSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, use_doorbell, CTLFLAG_RW, 149127468Ssimokawa &use_doorbell, 0, "SBP use doorbell request"); 150127468SsimokawaSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, tags, CTLFLAG_RW, &sbp_tags, 0, 151127468Ssimokawa "SBP tagged queuing support"); 152103285Sikob 153122387SsimokawaTUNABLE_INT("hw.firewire.sbp.auto_login", &auto_login); 154122387SsimokawaTUNABLE_INT("hw.firewire.sbp.max_speed", &max_speed); 155122387SsimokawaTUNABLE_INT("hw.firewire.sbp.exclusive_login", &ex_login); 156122387SsimokawaTUNABLE_INT("hw.firewire.sbp.login_delay", &login_delay); 157122387SsimokawaTUNABLE_INT("hw.firewire.sbp.scan_delay", &scan_delay); 158127468SsimokawaTUNABLE_INT("hw.firewire.sbp.use_doorbell", &use_doorbell); 159127468SsimokawaTUNABLE_INT("hw.firewire.sbp.tags", &sbp_tags); 160122387Ssimokawa 161103285Sikob#define NEED_RESPONSE 0 162103285Sikob 163113584Ssimokawa#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE) 164113584Ssimokawa#ifdef __sparc64__ /* iommu */ 165167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, SBP_SEG_MAX) 166113584Ssimokawa#else 167167622Ssimokawa#define SBP_IND_MAX howmany(SBP_MAXPHYS, PAGE_SIZE) 168113584Ssimokawa#endif 169103285Sikobstruct sbp_ocb { 170103285Sikob STAILQ_ENTRY(sbp_ocb) ocb; 171103285Sikob union ccb *ccb; 172113584Ssimokawa bus_addr_t bus_addr; 173129585Sdfr uint32_t orb[8]; 174129585Sdfr#define IND_PTR_OFFSET (8*sizeof(uint32_t)) 175120660Ssimokawa struct ind_ptr ind_ptr[SBP_IND_MAX]; 176103285Sikob struct sbp_dev *sdev; 177113584Ssimokawa int flags; /* XXX should be removed */ 178103285Sikob bus_dmamap_t dmamap; 179103285Sikob}; 180113584Ssimokawa 181103285Sikob#define OCB_ACT_MGM 0 182103285Sikob#define OCB_ACT_CMD 1 183113584Ssimokawa#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo)) 184103285Sikob 185103285Sikobstruct sbp_dev{ 186103285Sikob#define SBP_DEV_RESET 0 /* accept login */ 187114732Ssimokawa#define SBP_DEV_LOGIN 1 /* to login */ 188110336Ssimokawa#if 0 189103285Sikob#define SBP_DEV_RECONN 2 /* to reconnect */ 190110336Ssimokawa#endif 191103285Sikob#define SBP_DEV_TOATTACH 3 /* to attach */ 192103285Sikob#define SBP_DEV_PROBE 4 /* scan lun */ 193103285Sikob#define SBP_DEV_ATTACHED 5 /* in operation */ 194103285Sikob#define SBP_DEV_DEAD 6 /* unavailable unit */ 195103285Sikob#define SBP_DEV_RETRY 7 /* unavailable unit */ 196129585Sdfr uint8_t status:4, 197114732Ssimokawa timeout:4; 198129585Sdfr uint8_t type; 199129585Sdfr uint16_t lun_id; 200129585Sdfr uint16_t freeze; 201121185Ssimokawa#define ORB_LINK_DEAD (1 << 0) 202121185Ssimokawa#define VALID_LUN (1 << 1) 203121185Ssimokawa#define ORB_POINTER_ACTIVE (1 << 2) 204121185Ssimokawa#define ORB_POINTER_NEED (1 << 3) 205127468Ssimokawa#define ORB_DOORBELL_ACTIVE (1 << 4) 206127468Ssimokawa#define ORB_DOORBELL_NEED (1 << 5) 207127468Ssimokawa#define ORB_SHORTAGE (1 << 6) 208129585Sdfr uint16_t flags; 209103285Sikob struct cam_path *path; 210103285Sikob struct sbp_target *target; 211113584Ssimokawa struct fwdma_alloc dma; 212113584Ssimokawa struct sbp_login_res *login; 213111615Ssimokawa struct callout login_callout; 214113584Ssimokawa struct sbp_ocb *ocb; 215103285Sikob STAILQ_HEAD(, sbp_ocb) ocbs; 216113584Ssimokawa STAILQ_HEAD(, sbp_ocb) free_ocbs; 217127468Ssimokawa struct sbp_ocb *last_ocb; 218103285Sikob char vendor[32]; 219103285Sikob char product[32]; 220103285Sikob char revision[10]; 221103285Sikob}; 222103285Sikob 223103285Sikobstruct sbp_target { 224103285Sikob int target_id; 225103285Sikob int num_lun; 226121185Ssimokawa struct sbp_dev **luns; 227103285Sikob struct sbp_softc *sbp; 228103285Sikob struct fw_device *fwdev; 229129585Sdfr uint32_t mgm_hi, mgm_lo; 230111615Ssimokawa struct sbp_ocb *mgm_ocb_cur; 231111615Ssimokawa STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; 232111615Ssimokawa struct callout mgm_ocb_timeout; 233111615Ssimokawa struct callout scan_callout; 234113584Ssimokawa STAILQ_HEAD(, fw_xfer) xferlist; 235113584Ssimokawa int n_xfer; 236103285Sikob}; 237103285Sikob 238103285Sikobstruct sbp_softc { 239103285Sikob struct firewire_dev_comm fd; 240103285Sikob struct cam_sim *sim; 241111615Ssimokawa struct cam_path *path; 242103285Sikob struct sbp_target targets[SBP_NUM_TARGETS]; 243103285Sikob struct fw_bind fwb; 244103285Sikob bus_dma_tag_t dmat; 245122387Ssimokawa struct timeval last_busreset; 246124145Ssimokawa#define SIMQ_FREEZED 1 247124145Ssimokawa int flags; 248170374Ssimokawa struct mtx mtx; 249103285Sikob}; 250170374Ssimokawa#define SBP_LOCK(sbp) mtx_lock(&(sbp)->mtx) 251170374Ssimokawa#define SBP_UNLOCK(sbp) mtx_unlock(&(sbp)->mtx) 252122387Ssimokawa 253124169Ssimokawastatic void sbp_post_explore (void *); 254124169Ssimokawastatic void sbp_recv (struct fw_xfer *); 255124169Ssimokawastatic void sbp_mgm_callback (struct fw_xfer *); 256121185Ssimokawa#if 0 257124169Ssimokawastatic void sbp_cmd_callback (struct fw_xfer *); 258121185Ssimokawa#endif 259124169Ssimokawastatic void sbp_orb_pointer (struct sbp_dev *, struct sbp_ocb *); 260127468Ssimokawastatic void sbp_doorbell(struct sbp_dev *); 261124169Ssimokawastatic void sbp_execute_ocb (void *, bus_dma_segment_t *, int, int); 262124169Ssimokawastatic void sbp_free_ocb (struct sbp_dev *, struct sbp_ocb *); 263124169Ssimokawastatic void sbp_abort_ocb (struct sbp_ocb *, int); 264124169Ssimokawastatic void sbp_abort_all_ocbs (struct sbp_dev *, int); 265124169Ssimokawastatic struct fw_xfer * sbp_write_cmd (struct sbp_dev *, int, int); 266124169Ssimokawastatic struct sbp_ocb * sbp_get_ocb (struct sbp_dev *); 267124169Ssimokawastatic struct sbp_ocb * sbp_enqueue_ocb (struct sbp_dev *, struct sbp_ocb *); 268124169Ssimokawastatic struct sbp_ocb * sbp_dequeue_ocb (struct sbp_dev *, struct sbp_status *); 269121185Ssimokawastatic void sbp_cam_detach_sdev(struct sbp_dev *); 270121185Ssimokawastatic void sbp_free_sdev(struct sbp_dev *); 271124169Ssimokawastatic void sbp_cam_detach_target (struct sbp_target *); 272124169Ssimokawastatic void sbp_free_target (struct sbp_target *); 273124169Ssimokawastatic void sbp_mgm_timeout (void *arg); 274124169Ssimokawastatic void sbp_timeout (void *arg); 275124169Ssimokawastatic void sbp_mgm_orb (struct sbp_dev *, int, struct sbp_ocb *); 276103285Sikob 277108281SsimokawaMALLOC_DEFINE(M_SBP, "sbp", "SBP-II/FireWire"); 278103285Sikob 279103285Sikob/* cam related functions */ 280103285Sikobstatic void sbp_action(struct cam_sim *sim, union ccb *ccb); 281103285Sikobstatic void sbp_poll(struct cam_sim *sim); 282111615Ssimokawastatic void sbp_cam_scan_lun(struct cam_periph *, union ccb *); 283111615Ssimokawastatic void sbp_cam_scan_target(void *arg); 284103285Sikob 285103285Sikobstatic char *orb_status0[] = { 286103285Sikob /* 0 */ "No additional information to report", 287103285Sikob /* 1 */ "Request type not supported", 288103285Sikob /* 2 */ "Speed not supported", 289103285Sikob /* 3 */ "Page size not supported", 290103285Sikob /* 4 */ "Access denied", 291103285Sikob /* 5 */ "Logical unit not supported", 292103285Sikob /* 6 */ "Maximum payload too small", 293103285Sikob /* 7 */ "Reserved for future standardization", 294103285Sikob /* 8 */ "Resources unavailable", 295103285Sikob /* 9 */ "Function rejected", 296103285Sikob /* A */ "Login ID not recognized", 297103285Sikob /* B */ "Dummy ORB completed", 298103285Sikob /* C */ "Request aborted", 299103285Sikob /* FF */ "Unspecified error" 300103285Sikob#define MAX_ORB_STATUS0 0xd 301103285Sikob}; 302103285Sikob 303103285Sikobstatic char *orb_status1_object[] = { 304103285Sikob /* 0 */ "Operation request block (ORB)", 305103285Sikob /* 1 */ "Data buffer", 306103285Sikob /* 2 */ "Page table", 307103285Sikob /* 3 */ "Unable to specify" 308103285Sikob}; 309103285Sikob 310103285Sikobstatic char *orb_status1_serial_bus_error[] = { 311103285Sikob /* 0 */ "Missing acknowledge", 312103285Sikob /* 1 */ "Reserved; not to be used", 313103285Sikob /* 2 */ "Time-out error", 314103285Sikob /* 3 */ "Reserved; not to be used", 315103285Sikob /* 4 */ "Busy retry limit exceeded(X)", 316103285Sikob /* 5 */ "Busy retry limit exceeded(A)", 317103285Sikob /* 6 */ "Busy retry limit exceeded(B)", 318103285Sikob /* 7 */ "Reserved for future standardization", 319103285Sikob /* 8 */ "Reserved for future standardization", 320103285Sikob /* 9 */ "Reserved for future standardization", 321103285Sikob /* A */ "Reserved for future standardization", 322103285Sikob /* B */ "Tardy retry limit exceeded", 323103285Sikob /* C */ "Conflict error", 324103285Sikob /* D */ "Data error", 325103285Sikob /* E */ "Type error", 326103285Sikob /* F */ "Address error" 327103285Sikob}; 328103285Sikob 329103285Sikobstatic void 330103285Sikobsbp_identify(driver_t *driver, device_t parent) 331103285Sikob{ 332103285Sikob device_t child; 333103285SikobSBP_DEBUG(0) 334103285Sikob printf("sbp_identify\n"); 335103285SikobEND_DEBUG 336103285Sikob 337103285Sikob child = BUS_ADD_CHILD(parent, 0, "sbp", device_get_unit(parent)); 338103285Sikob} 339103285Sikob 340103285Sikob/* 341103285Sikob * sbp_probe() 342103285Sikob */ 343103285Sikobstatic int 344103285Sikobsbp_probe(device_t dev) 345103285Sikob{ 346103285Sikob device_t pa; 347103285Sikob 348103285SikobSBP_DEBUG(0) 349103285Sikob printf("sbp_probe\n"); 350103285SikobEND_DEBUG 351103285Sikob 352103285Sikob pa = device_get_parent(dev); 353103285Sikob if(device_get_unit(dev) != device_get_unit(pa)){ 354103285Sikob return(ENXIO); 355103285Sikob } 356103285Sikob 357120660Ssimokawa device_set_desc(dev, "SBP-2/SCSI over FireWire"); 358111615Ssimokawa 359132432Ssimokawa#if 0 360111615Ssimokawa if (bootverbose) 361111615Ssimokawa debug = bootverbose; 362132432Ssimokawa#endif 363132432Ssimokawa 364103285Sikob return (0); 365103285Sikob} 366103285Sikob 367103285Sikobstatic void 368103285Sikobsbp_show_sdev_info(struct sbp_dev *sdev, int new) 369103285Sikob{ 370103285Sikob struct fw_device *fwdev; 371103285Sikob 372103285Sikob printf("%s:%d:%d ", 373103285Sikob device_get_nameunit(sdev->target->sbp->fd.dev), 374103285Sikob sdev->target->target_id, 375103285Sikob sdev->lun_id 376103285Sikob ); 377103285Sikob if (new == 2) { 378103285Sikob return; 379103285Sikob } 380103285Sikob fwdev = sdev->target->fwdev; 381103285Sikob printf("ordered:%d type:%d EUI:%08x%08x node:%d " 382103285Sikob "speed:%d maxrec:%d", 383108503Ssimokawa (sdev->type & 0x40) >> 6, 384108503Ssimokawa (sdev->type & 0x1f), 385103285Sikob fwdev->eui.hi, 386103285Sikob fwdev->eui.lo, 387103285Sikob fwdev->dst, 388103285Sikob fwdev->speed, 389103285Sikob fwdev->maxrec 390103285Sikob ); 391103285Sikob if (new) 392103285Sikob printf(" new!\n"); 393103285Sikob else 394103285Sikob printf("\n"); 395103285Sikob sbp_show_sdev_info(sdev, 2); 396103285Sikob printf("'%s' '%s' '%s'\n", sdev->vendor, sdev->product, sdev->revision); 397103285Sikob} 398103285Sikob 399110184Ssimokawastatic struct { 400110184Ssimokawa int bus; 401110184Ssimokawa int target; 402110184Ssimokawa struct fw_eui64 eui; 403110184Ssimokawa} wired[] = { 404110184Ssimokawa /* Bus Target EUI64 */ 405110184Ssimokawa#if 0 406110184Ssimokawa {0, 2, {0x00018ea0, 0x01fd0154}}, /* Logitec HDD */ 407110184Ssimokawa {0, 0, {0x00018ea6, 0x00100682}}, /* Logitec DVD */ 408110184Ssimokawa {0, 1, {0x00d03200, 0xa412006a}}, /* Yano HDD */ 409110184Ssimokawa#endif 410110184Ssimokawa {-1, -1, {0,0}} 411110184Ssimokawa}; 412110184Ssimokawa 413110184Ssimokawastatic int 414110184Ssimokawasbp_new_target(struct sbp_softc *sbp, struct fw_device *fwdev) 415110184Ssimokawa{ 416110184Ssimokawa int bus, i, target=-1; 417110184Ssimokawa char w[SBP_NUM_TARGETS]; 418110184Ssimokawa 419110184Ssimokawa bzero(w, sizeof(w)); 420110184Ssimokawa bus = device_get_unit(sbp->fd.dev); 421110184Ssimokawa 422110184Ssimokawa /* XXX wired-down configuration should be gotten from 423110184Ssimokawa tunable or device hint */ 424110184Ssimokawa for (i = 0; wired[i].bus >= 0; i ++) { 425110184Ssimokawa if (wired[i].bus == bus) { 426110184Ssimokawa w[wired[i].target] = 1; 427110184Ssimokawa if (wired[i].eui.hi == fwdev->eui.hi && 428110184Ssimokawa wired[i].eui.lo == fwdev->eui.lo) 429110184Ssimokawa target = wired[i].target; 430110184Ssimokawa } 431110184Ssimokawa } 432110184Ssimokawa if (target >= 0) { 433110184Ssimokawa if(target < SBP_NUM_TARGETS && 434110184Ssimokawa sbp->targets[target].fwdev == NULL) 435110184Ssimokawa return(target); 436110184Ssimokawa device_printf(sbp->fd.dev, 437110184Ssimokawa "target %d is not free for %08x:%08x\n", 438110184Ssimokawa target, fwdev->eui.hi, fwdev->eui.lo); 439110184Ssimokawa target = -1; 440110184Ssimokawa } 441110184Ssimokawa /* non-wired target */ 442110184Ssimokawa for (i = 0; i < SBP_NUM_TARGETS; i ++) 443110184Ssimokawa if (sbp->targets[i].fwdev == NULL && w[i] == 0) { 444110184Ssimokawa target = i; 445110184Ssimokawa break; 446110184Ssimokawa } 447110184Ssimokawa 448110184Ssimokawa return target; 449110184Ssimokawa} 450110184Ssimokawa 451121185Ssimokawastatic void 452121185Ssimokawasbp_alloc_lun(struct sbp_target *target) 453103285Sikob{ 454108503Ssimokawa struct crom_context cc; 455108503Ssimokawa struct csrreg *reg; 456121185Ssimokawa struct sbp_dev *sdev, **newluns; 457121185Ssimokawa struct sbp_softc *sbp; 458121185Ssimokawa int maxlun, lun, i; 459103285Sikob 460121185Ssimokawa sbp = target->sbp; 461114069Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 462108503Ssimokawa /* XXX shoud parse appropriate unit directories only */ 463108503Ssimokawa maxlun = -1; 464108503Ssimokawa while (cc.depth >= 0) { 465108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 466108503Ssimokawa if (reg == NULL) 467108503Ssimokawa break; 468110839Ssimokawa lun = reg->val & 0xffff; 469108642SsimokawaSBP_DEBUG(0) 470108642Ssimokawa printf("target %d lun %d found\n", target->target_id, lun); 471108642SsimokawaEND_DEBUG 472108503Ssimokawa if (maxlun < lun) 473108503Ssimokawa maxlun = lun; 474108503Ssimokawa crom_next(&cc); 475108503Ssimokawa } 476110839Ssimokawa if (maxlun < 0) 477121185Ssimokawa printf("%s:%d no LUN found\n", 478121185Ssimokawa device_get_nameunit(target->sbp->fd.dev), 479121185Ssimokawa target->target_id); 480121185Ssimokawa 481121185Ssimokawa maxlun ++; 482110839Ssimokawa if (maxlun >= SBP_NUM_LUNS) 483110839Ssimokawa maxlun = SBP_NUM_LUNS; 484121185Ssimokawa 485121185Ssimokawa /* Invalidiate stale devices */ 486121185Ssimokawa for (lun = 0; lun < target->num_lun; lun ++) { 487121185Ssimokawa sdev = target->luns[lun]; 488121185Ssimokawa if (sdev == NULL) 489121185Ssimokawa continue; 490121185Ssimokawa sdev->flags &= ~VALID_LUN; 491121185Ssimokawa if (lun >= maxlun) { 492121185Ssimokawa /* lost device */ 493121185Ssimokawa sbp_cam_detach_sdev(sdev); 494121185Ssimokawa sbp_free_sdev(sdev); 495121185Ssimokawa } 496103285Sikob } 497121185Ssimokawa 498121185Ssimokawa /* Reallocate */ 499121185Ssimokawa if (maxlun != target->num_lun) { 500121185Ssimokawa newluns = (struct sbp_dev **) realloc(target->luns, 501121185Ssimokawa sizeof(struct sbp_dev *) * maxlun, 502121185Ssimokawa M_SBP, M_NOWAIT | M_ZERO); 503121185Ssimokawa 504121185Ssimokawa if (newluns == NULL) { 505127468Ssimokawa printf("%s: realloc failed\n", __func__); 506121185Ssimokawa newluns = target->luns; 507121185Ssimokawa maxlun = target->num_lun; 508121185Ssimokawa } 509121185Ssimokawa 510121185Ssimokawa /* 511121185Ssimokawa * We must zero the extended region for the case 512121185Ssimokawa * realloc() doesn't allocate new buffer. 513121185Ssimokawa */ 514121185Ssimokawa if (maxlun > target->num_lun) 515121185Ssimokawa bzero(&newluns[target->num_lun], 516121185Ssimokawa sizeof(struct sbp_dev *) * 517121185Ssimokawa (maxlun - target->num_lun)); 518121185Ssimokawa 519121185Ssimokawa target->luns = newluns; 520121185Ssimokawa target->num_lun = maxlun; 521121185Ssimokawa } 522121185Ssimokawa 523108503Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 524108503Ssimokawa while (cc.depth >= 0) { 525121185Ssimokawa int new = 0; 526121185Ssimokawa 527108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 528108503Ssimokawa if (reg == NULL) 529108503Ssimokawa break; 530110839Ssimokawa lun = reg->val & 0xffff; 531110839Ssimokawa if (lun >= SBP_NUM_LUNS) { 532110839Ssimokawa printf("too large lun %d\n", lun); 533121185Ssimokawa goto next; 534110839Ssimokawa } 535121185Ssimokawa 536121185Ssimokawa sdev = target->luns[lun]; 537121185Ssimokawa if (sdev == NULL) { 538121185Ssimokawa sdev = malloc(sizeof(struct sbp_dev), 539121185Ssimokawa M_SBP, M_NOWAIT | M_ZERO); 540121185Ssimokawa if (sdev == NULL) { 541127468Ssimokawa printf("%s: malloc failed\n", __func__); 542121185Ssimokawa goto next; 543121185Ssimokawa } 544121185Ssimokawa target->luns[lun] = sdev; 545121185Ssimokawa sdev->lun_id = lun; 546121185Ssimokawa sdev->target = target; 547121185Ssimokawa STAILQ_INIT(&sdev->ocbs); 548121185Ssimokawa CALLOUT_INIT(&sdev->login_callout); 549121185Ssimokawa sdev->status = SBP_DEV_RESET; 550121185Ssimokawa new = 1; 551121185Ssimokawa } 552121185Ssimokawa sdev->flags |= VALID_LUN; 553119196Ssimokawa sdev->type = (reg->val & 0xff0000) >> 16; 554113584Ssimokawa 555121185Ssimokawa if (new == 0) 556121185Ssimokawa goto next; 557121185Ssimokawa 558113584Ssimokawa fwdma_malloc(sbp->fd.fc, 559129585Sdfr /* alignment */ sizeof(uint32_t), 560113584Ssimokawa SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT); 561113584Ssimokawa if (sdev->dma.v_addr == NULL) { 562113584Ssimokawa printf("%s: dma space allocation failed\n", 563127468Ssimokawa __func__); 564121185Ssimokawa free(sdev, M_SBP); 565121185Ssimokawa target->luns[lun] = NULL; 566121185Ssimokawa goto next; 567113584Ssimokawa } 568113584Ssimokawa sdev->login = (struct sbp_login_res *) sdev->dma.v_addr; 569113584Ssimokawa sdev->ocb = (struct sbp_ocb *) 570113584Ssimokawa ((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE); 571113584Ssimokawa bzero((char *)sdev->ocb, 572113584Ssimokawa sizeof (struct sbp_ocb) * SBP_QUEUE_LEN); 573113584Ssimokawa 574113584Ssimokawa STAILQ_INIT(&sdev->free_ocbs); 575113584Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) { 576113584Ssimokawa struct sbp_ocb *ocb; 577113584Ssimokawa ocb = &sdev->ocb[i]; 578113584Ssimokawa ocb->bus_addr = sdev->dma.bus_addr 579113584Ssimokawa + SBP_LOGIN_SIZE 580113584Ssimokawa + sizeof(struct sbp_ocb) * i 581113584Ssimokawa + offsetof(struct sbp_ocb, orb[0]); 582113584Ssimokawa if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) { 583113584Ssimokawa printf("sbp_attach: cannot create dmamap\n"); 584121185Ssimokawa /* XXX */ 585121185Ssimokawa goto next; 586113584Ssimokawa } 587113584Ssimokawa sbp_free_ocb(sdev, ocb); 588113584Ssimokawa } 589121185Ssimokawanext: 590108503Ssimokawa crom_next(&cc); 591103285Sikob } 592121185Ssimokawa 593121185Ssimokawa for (lun = 0; lun < target->num_lun; lun ++) { 594121185Ssimokawa sdev = target->luns[lun]; 595121185Ssimokawa if (sdev != NULL && (sdev->flags & VALID_LUN) == 0) { 596121185Ssimokawa sbp_cam_detach_sdev(sdev); 597121185Ssimokawa sbp_free_sdev(sdev); 598121185Ssimokawa target->luns[lun] = NULL; 599121185Ssimokawa } 600121185Ssimokawa } 601121185Ssimokawa} 602121185Ssimokawa 603121185Ssimokawastatic struct sbp_target * 604121185Ssimokawasbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev) 605121185Ssimokawa{ 606121185Ssimokawa int i; 607121185Ssimokawa struct sbp_target *target; 608121185Ssimokawa struct crom_context cc; 609121185Ssimokawa struct csrreg *reg; 610121185Ssimokawa 611121185SsimokawaSBP_DEBUG(1) 612121185Ssimokawa printf("sbp_alloc_target\n"); 613121185SsimokawaEND_DEBUG 614121185Ssimokawa i = sbp_new_target(sbp, fwdev); 615121185Ssimokawa if (i < 0) { 616121185Ssimokawa device_printf(sbp->fd.dev, "increase SBP_NUM_TARGETS!\n"); 617121185Ssimokawa return NULL; 618121185Ssimokawa } 619121185Ssimokawa /* new target */ 620121185Ssimokawa target = &sbp->targets[i]; 621121185Ssimokawa target->sbp = sbp; 622121185Ssimokawa target->fwdev = fwdev; 623121185Ssimokawa target->target_id = i; 624121185Ssimokawa /* XXX we may want to reload mgm port after each bus reset */ 625121185Ssimokawa /* XXX there might be multiple management agents */ 626121185Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 627121185Ssimokawa reg = crom_search_key(&cc, CROM_MGM); 628121185Ssimokawa if (reg == NULL || reg->val == 0) { 629121185Ssimokawa printf("NULL management address\n"); 630121185Ssimokawa target->fwdev = NULL; 631121185Ssimokawa return NULL; 632121185Ssimokawa } 633121185Ssimokawa target->mgm_hi = 0xffff; 634121185Ssimokawa target->mgm_lo = 0xf0000000 | (reg->val << 2); 635121185Ssimokawa target->mgm_ocb_cur = NULL; 636121185SsimokawaSBP_DEBUG(1) 637121185Ssimokawa printf("target:%d mgm_port: %x\n", i, target->mgm_lo); 638121185SsimokawaEND_DEBUG 639121185Ssimokawa STAILQ_INIT(&target->xferlist); 640121185Ssimokawa target->n_xfer = 0; 641121185Ssimokawa STAILQ_INIT(&target->mgm_ocb_queue); 642121185Ssimokawa CALLOUT_INIT(&target->mgm_ocb_timeout); 643121185Ssimokawa CALLOUT_INIT(&target->scan_callout); 644121185Ssimokawa 645121185Ssimokawa target->luns = NULL; 646121185Ssimokawa target->num_lun = 0; 647114069Ssimokawa return target; 648103285Sikob} 649103285Sikob 650103285Sikobstatic void 651103285Sikobsbp_probe_lun(struct sbp_dev *sdev) 652103285Sikob{ 653103285Sikob struct fw_device *fwdev; 654114069Ssimokawa struct crom_context c, *cc = &c; 655114069Ssimokawa struct csrreg *reg; 656103285Sikob 657103285Sikob bzero(sdev->vendor, sizeof(sdev->vendor)); 658103285Sikob bzero(sdev->product, sizeof(sdev->product)); 659114069Ssimokawa 660114069Ssimokawa fwdev = sdev->target->fwdev; 661114069Ssimokawa crom_init_context(cc, fwdev->csrrom); 662114069Ssimokawa /* get vendor string */ 663114069Ssimokawa crom_search_key(cc, CSRKEY_VENDOR); 664114069Ssimokawa crom_next(cc); 665114069Ssimokawa crom_parse_text(cc, sdev->vendor, sizeof(sdev->vendor)); 666114223Ssimokawa /* skip to the unit directory for SBP-2 */ 667114260Ssimokawa while ((reg = crom_search_key(cc, CSRKEY_VER)) != NULL) { 668114223Ssimokawa if (reg->val == CSRVAL_T10SBP2) 669114223Ssimokawa break; 670114260Ssimokawa crom_next(cc); 671114260Ssimokawa } 672114069Ssimokawa /* get firmware revision */ 673114069Ssimokawa reg = crom_search_key(cc, CSRKEY_FIRM_VER); 674114069Ssimokawa if (reg != NULL) 675114069Ssimokawa snprintf(sdev->revision, sizeof(sdev->revision), 676114069Ssimokawa "%06x", reg->val); 677114069Ssimokawa /* get product string */ 678114069Ssimokawa crom_search_key(cc, CSRKEY_MODEL); 679114069Ssimokawa crom_next(cc); 680114069Ssimokawa crom_parse_text(cc, sdev->product, sizeof(sdev->product)); 681103285Sikob} 682111615Ssimokawa 683103285Sikobstatic void 684111615Ssimokawasbp_login_callout(void *arg) 685103285Sikob{ 686111615Ssimokawa struct sbp_dev *sdev = (struct sbp_dev *)arg; 687111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL); 688111615Ssimokawa} 689111615Ssimokawa 690122387Ssimokawastatic void 691122387Ssimokawasbp_login(struct sbp_dev *sdev) 692122387Ssimokawa{ 693122387Ssimokawa struct timeval delta; 694122387Ssimokawa struct timeval t; 695122387Ssimokawa int ticks = 0; 696122387Ssimokawa 697122387Ssimokawa microtime(&delta); 698122387Ssimokawa timevalsub(&delta, &sdev->target->sbp->last_busreset); 699122387Ssimokawa t.tv_sec = login_delay / 1000; 700122387Ssimokawa t.tv_usec = (login_delay % 1000) * 1000; 701122387Ssimokawa timevalsub(&t, &delta); 702122387Ssimokawa if (t.tv_sec >= 0 && t.tv_usec > 0) 703122387Ssimokawa ticks = (t.tv_sec * 1000 + t.tv_usec / 1000) * hz / 1000; 704122387SsimokawaSBP_DEBUG(0) 705153706Strhodes printf("%s: sec = %jd usec = %ld ticks = %d\n", __func__, 706153706Strhodes (intmax_t)t.tv_sec, t.tv_usec, ticks); 707122387SsimokawaEND_DEBUG 708122387Ssimokawa callout_reset(&sdev->login_callout, ticks, 709122387Ssimokawa sbp_login_callout, (void *)(sdev)); 710122387Ssimokawa} 711122387Ssimokawa 712114069Ssimokawa#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ 713114069Ssimokawa && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) 714111615Ssimokawa 715111615Ssimokawastatic void 716111615Ssimokawasbp_probe_target(void *arg) 717111615Ssimokawa{ 718111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 719103285Sikob struct sbp_softc *sbp; 720103285Sikob struct sbp_dev *sdev; 721103285Sikob struct firewire_comm *fc; 722111615Ssimokawa int i, alive; 723103285Sikob 724111615Ssimokawa alive = SBP_FWDEV_ALIVE(target->fwdev); 725103285SikobSBP_DEBUG(1) 726103285Sikob printf("sbp_probe_target %d\n", target->target_id); 727103285Sikob if (!alive) 728103285Sikob printf("not alive\n"); 729103285SikobEND_DEBUG 730103285Sikob 731103285Sikob sbp = target->sbp; 732103285Sikob fc = target->sbp->fd.fc; 733121185Ssimokawa sbp_alloc_lun(target); 734121185Ssimokawa 735111615Ssimokawa /* XXX untimeout mgm_ocb and dequeue */ 736103285Sikob for (i=0; i < target->num_lun; i++) { 737121185Ssimokawa sdev = target->luns[i]; 738121185Ssimokawa if (sdev == NULL) 739121185Ssimokawa continue; 740103285Sikob if (alive && (sdev->status != SBP_DEV_DEAD)) { 741103285Sikob if (sdev->path != NULL) { 742170374Ssimokawa SBP_LOCK(sbp); 743103285Sikob xpt_freeze_devq(sdev->path, 1); 744111615Ssimokawa sdev->freeze ++; 745170374Ssimokawa SBP_UNLOCK(sbp); 746103285Sikob } 747111615Ssimokawa sbp_probe_lun(sdev); 748111615SsimokawaSBP_DEBUG(0) 749111615Ssimokawa sbp_show_sdev_info(sdev, 750111615Ssimokawa (sdev->status == SBP_DEV_RESET)); 751111615SsimokawaEND_DEBUG 752111615Ssimokawa 753111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 754103285Sikob switch (sdev->status) { 755110336Ssimokawa case SBP_DEV_RESET: 756103285Sikob /* new or revived target */ 757113584Ssimokawa if (auto_login) 758111615Ssimokawa sbp_login(sdev); 759103285Sikob break; 760111615Ssimokawa case SBP_DEV_TOATTACH: 761111615Ssimokawa case SBP_DEV_PROBE: 762111615Ssimokawa case SBP_DEV_ATTACHED: 763110336Ssimokawa case SBP_DEV_RETRY: 764110336Ssimokawa default: 765111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); 766110336Ssimokawa break; 767103285Sikob } 768103285Sikob } else { 769103285Sikob switch (sdev->status) { 770103285Sikob case SBP_DEV_ATTACHED: 771103285SikobSBP_DEBUG(0) 772103285Sikob /* the device has gone */ 773103285Sikob sbp_show_sdev_info(sdev, 2); 774103285Sikob printf("lost target\n"); 775103285SikobEND_DEBUG 776111615Ssimokawa if (sdev->path) { 777170374Ssimokawa SBP_LOCK(sbp); 778103285Sikob xpt_freeze_devq(sdev->path, 1); 779111615Ssimokawa sdev->freeze ++; 780170374Ssimokawa SBP_UNLOCK(sbp); 781111615Ssimokawa } 782103285Sikob sdev->status = SBP_DEV_RETRY; 783111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 784103285Sikob break; 785103285Sikob case SBP_DEV_PROBE: 786103285Sikob case SBP_DEV_TOATTACH: 787103285Sikob sdev->status = SBP_DEV_RESET; 788103285Sikob break; 789103285Sikob case SBP_DEV_RETRY: 790103285Sikob case SBP_DEV_RESET: 791103285Sikob case SBP_DEV_DEAD: 792103285Sikob break; 793103285Sikob } 794103285Sikob } 795103285Sikob } 796103285Sikob} 797103285Sikob 798103285Sikobstatic void 799113584Ssimokawasbp_post_busreset(void *arg) 800113584Ssimokawa{ 801113584Ssimokawa struct sbp_softc *sbp; 802113584Ssimokawa 803113584Ssimokawa sbp = (struct sbp_softc *)arg; 804113584SsimokawaSBP_DEBUG(0) 805113584Ssimokawa printf("sbp_post_busreset\n"); 806113584SsimokawaEND_DEBUG 807124145Ssimokawa if ((sbp->sim->flags & SIMQ_FREEZED) == 0) { 808170374Ssimokawa SBP_LOCK(sbp); 809124145Ssimokawa xpt_freeze_simq(sbp->sim, /*count*/1); 810124145Ssimokawa sbp->sim->flags |= SIMQ_FREEZED; 811170374Ssimokawa SBP_UNLOCK(sbp); 812124145Ssimokawa } 813122387Ssimokawa microtime(&sbp->last_busreset); 814113584Ssimokawa} 815113584Ssimokawa 816113584Ssimokawastatic void 817103285Sikobsbp_post_explore(void *arg) 818103285Sikob{ 819103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)arg; 820103285Sikob struct sbp_target *target; 821103285Sikob struct fw_device *fwdev; 822103285Sikob int i, alive; 823103285Sikob 824111199SsimokawaSBP_DEBUG(0) 825111199Ssimokawa printf("sbp_post_explore (sbp_cold=%d)\n", sbp_cold); 826103285SikobEND_DEBUG 827170400Ssimokawa /* We need physical access */ 828170400Ssimokawa if (!firewire_phydma_enable) 829170400Ssimokawa return; 830170400Ssimokawa 831122387Ssimokawa if (sbp_cold > 0) 832122387Ssimokawa sbp_cold --; 833122387Ssimokawa 834122387Ssimokawa#if 0 835122387Ssimokawa /* 836122387Ssimokawa * XXX don't let CAM the bus rest. 837122387Ssimokawa * CAM tries to do something with freezed (DEV_RETRY) devices. 838111615Ssimokawa */ 839111615Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 840103285Sikob#endif 841111615Ssimokawa 842130532Sdfr /* Garbage Collection */ 843103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 844103285Sikob target = &sbp->targets[i]; 845110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) 846110193Ssimokawa if (target->fwdev == NULL || target->fwdev == fwdev) 847110193Ssimokawa break; 848121185Ssimokawa if (fwdev == NULL) { 849103285Sikob /* device has removed in lower driver */ 850110145Ssimokawa sbp_cam_detach_target(target); 851121185Ssimokawa sbp_free_target(target); 852103285Sikob } 853103285Sikob } 854103285Sikob /* traverse device list */ 855110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) { 856103285SikobSBP_DEBUG(0) 857103285Sikob printf("sbp_post_explore: EUI:%08x%08x ", 858103285Sikob fwdev->eui.hi, fwdev->eui.lo); 859114069Ssimokawa if (fwdev->status != FWDEVATTACHED) 860103285Sikob printf("not attached, state=%d.\n", fwdev->status); 861114069Ssimokawa else 862114069Ssimokawa printf("attached\n"); 863103285SikobEND_DEBUG 864111615Ssimokawa alive = SBP_FWDEV_ALIVE(fwdev); 865103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 866103285Sikob target = &sbp->targets[i]; 867103285Sikob if(target->fwdev == fwdev ) { 868103285Sikob /* known target */ 869103285Sikob break; 870103285Sikob } 871103285Sikob } 872103285Sikob if(i == SBP_NUM_TARGETS){ 873103285Sikob if (alive) { 874103285Sikob /* new target */ 875103285Sikob target = sbp_alloc_target(sbp, fwdev); 876103285Sikob if (target == NULL) 877103285Sikob continue; 878103285Sikob } else { 879103285Sikob continue; 880103285Sikob } 881103285Sikob } 882111615Ssimokawa sbp_probe_target((void *)target); 883121185Ssimokawa if (target->num_lun == 0) 884121185Ssimokawa sbp_free_target(target); 885103285Sikob } 886170374Ssimokawa SBP_LOCK(sbp); 887124145Ssimokawa xpt_release_simq(sbp->sim, /*run queue*/TRUE); 888124145Ssimokawa sbp->sim->flags &= ~SIMQ_FREEZED; 889170374Ssimokawa SBP_UNLOCK(sbp); 890103285Sikob} 891103285Sikob 892103285Sikob#if NEED_RESPONSE 893103285Sikobstatic void 894103285Sikobsbp_loginres_callback(struct fw_xfer *xfer){ 895113584Ssimokawa int s; 896103285Sikob struct sbp_dev *sdev; 897103285Sikob sdev = (struct sbp_dev *)xfer->sc; 898113584SsimokawaSBP_DEBUG(1) 899103285Sikob sbp_show_sdev_info(sdev, 2); 900103285Sikob printf("sbp_loginres_callback\n"); 901103285SikobEND_DEBUG 902113584Ssimokawa /* recycle */ 903113584Ssimokawa s = splfw(); 904113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link); 905113584Ssimokawa splx(s); 906103285Sikob return; 907103285Sikob} 908103285Sikob#endif 909103285Sikob 910113584Ssimokawastatic __inline void 911113584Ssimokawasbp_xfer_free(struct fw_xfer *xfer) 912113584Ssimokawa{ 913113584Ssimokawa struct sbp_dev *sdev; 914113584Ssimokawa int s; 915113584Ssimokawa 916113584Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 917113584Ssimokawa fw_xfer_unload(xfer); 918113584Ssimokawa s = splfw(); 919170374Ssimokawa SBP_LOCK(sdev->target->sbp); 920113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); 921170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 922113584Ssimokawa splx(s); 923113584Ssimokawa} 924113584Ssimokawa 925103285Sikobstatic void 926114732Ssimokawasbp_reset_start_callback(struct fw_xfer *xfer) 927103285Sikob{ 928114732Ssimokawa struct sbp_dev *tsdev, *sdev = (struct sbp_dev *)xfer->sc; 929114732Ssimokawa struct sbp_target *target = sdev->target; 930114732Ssimokawa int i; 931114732Ssimokawa 932114732Ssimokawa if (xfer->resp != 0) { 933114732Ssimokawa sbp_show_sdev_info(sdev, 2); 934114732Ssimokawa printf("sbp_reset_start failed: resp=%d\n", xfer->resp); 935114732Ssimokawa } 936114732Ssimokawa 937114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 938121185Ssimokawa tsdev = target->luns[i]; 939121185Ssimokawa if (tsdev != NULL && tsdev->status == SBP_DEV_LOGIN) 940121185Ssimokawa sbp_login(tsdev); 941114732Ssimokawa } 942114732Ssimokawa} 943114732Ssimokawa 944114732Ssimokawastatic void 945114732Ssimokawasbp_reset_start(struct sbp_dev *sdev) 946114732Ssimokawa{ 947114732Ssimokawa struct fw_xfer *xfer; 948114732Ssimokawa struct fw_pkt *fp; 949114732Ssimokawa 950114732SsimokawaSBP_DEBUG(0) 951114732Ssimokawa sbp_show_sdev_info(sdev, 2); 952114732Ssimokawa printf("sbp_reset_start\n"); 953114732SsimokawaEND_DEBUG 954114732Ssimokawa 955114732Ssimokawa xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 956167632Ssimokawa xfer->hand = sbp_reset_start_callback; 957120660Ssimokawa fp = &xfer->send.hdr; 958114732Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 959114732Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 960114732Ssimokawa fp->mode.wreqq.data = htonl(0xf); 961114732Ssimokawa fw_asyreq(xfer->fc, -1, xfer); 962114732Ssimokawa} 963114732Ssimokawa 964114732Ssimokawastatic void 965114732Ssimokawasbp_mgm_callback(struct fw_xfer *xfer) 966114732Ssimokawa{ 967103285Sikob struct sbp_dev *sdev; 968114732Ssimokawa int resp; 969114732Ssimokawa 970103285Sikob sdev = (struct sbp_dev *)xfer->sc; 971114732Ssimokawa 972114732SsimokawaSBP_DEBUG(1) 973103285Sikob sbp_show_sdev_info(sdev, 2); 974114732Ssimokawa printf("sbp_mgm_callback\n"); 975103285SikobEND_DEBUG 976114732Ssimokawa resp = xfer->resp; 977113584Ssimokawa sbp_xfer_free(xfer); 978114732Ssimokawa#if 0 979114732Ssimokawa if (resp != 0) { 980114732Ssimokawa sbp_show_sdev_info(sdev, 2); 981114732Ssimokawa printf("management ORB failed(%d) ... RESET_START\n", resp); 982114732Ssimokawa sbp_reset_start(sdev); 983114732Ssimokawa } 984114732Ssimokawa#endif 985103285Sikob return; 986103285Sikob} 987103285Sikob 988111615Ssimokawastatic struct sbp_dev * 989111615Ssimokawasbp_next_dev(struct sbp_target *target, int lun) 990111615Ssimokawa{ 991121185Ssimokawa struct sbp_dev **sdevp; 992111615Ssimokawa int i; 993111615Ssimokawa 994121185Ssimokawa for (i = lun, sdevp = &target->luns[lun]; i < target->num_lun; 995121185Ssimokawa i++, sdevp++) 996121185Ssimokawa if (*sdevp != NULL && (*sdevp)->status == SBP_DEV_PROBE) 997121185Ssimokawa return(*sdevp); 998121185Ssimokawa return(NULL); 999111615Ssimokawa} 1000111615Ssimokawa 1001111615Ssimokawa#define SCAN_PRI 1 1002103285Sikobstatic void 1003111615Ssimokawasbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb) 1004103285Sikob{ 1005111615Ssimokawa struct sbp_target *target; 1006103285Sikob struct sbp_dev *sdev; 1007111615Ssimokawa 1008103285Sikob sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr; 1009111615Ssimokawa target = sdev->target; 1010110269SsimokawaSBP_DEBUG(0) 1011103285Sikob sbp_show_sdev_info(sdev, 2); 1012111615Ssimokawa printf("sbp_cam_scan_lun\n"); 1013103285SikobEND_DEBUG 1014111615Ssimokawa if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1015111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1016111615Ssimokawa } else { 1017111615Ssimokawa sbp_show_sdev_info(sdev, 2); 1018111615Ssimokawa printf("scan failed\n"); 1019111615Ssimokawa } 1020111615Ssimokawa sdev = sbp_next_dev(target, sdev->lun_id + 1); 1021111615Ssimokawa if (sdev == NULL) { 1022111615Ssimokawa free(ccb, M_SBP); 1023111615Ssimokawa return; 1024111615Ssimokawa } 1025111615Ssimokawa /* reuse ccb */ 1026111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 1027111615Ssimokawa ccb->ccb_h.ccb_sdev_ptr = sdev; 1028111615Ssimokawa xpt_action(ccb); 1029111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1030111615Ssimokawa sdev->freeze = 1; 1031103285Sikob} 1032103285Sikob 1033103285Sikobstatic void 1034111615Ssimokawasbp_cam_scan_target(void *arg) 1035103285Sikob{ 1036111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 1037111615Ssimokawa struct sbp_dev *sdev; 1038110798Ssimokawa union ccb *ccb; 1039103285Sikob 1040111615Ssimokawa sdev = sbp_next_dev(target, 0); 1041111615Ssimokawa if (sdev == NULL) { 1042111615Ssimokawa printf("sbp_cam_scan_target: nothing to do for target%d\n", 1043111615Ssimokawa target->target_id); 1044110798Ssimokawa return; 1045110798Ssimokawa } 1046103285SikobSBP_DEBUG(0) 1047103285Sikob sbp_show_sdev_info(sdev, 2); 1048111615Ssimokawa printf("sbp_cam_scan_target\n"); 1049103285SikobEND_DEBUG 1050111615Ssimokawa ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO); 1051111615Ssimokawa if (ccb == NULL) { 1052111615Ssimokawa printf("sbp_cam_scan_target: malloc failed\n"); 1053111615Ssimokawa return; 1054111615Ssimokawa } 1055111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 1056103285Sikob ccb->ccb_h.func_code = XPT_SCAN_LUN; 1057111615Ssimokawa ccb->ccb_h.cbfcnp = sbp_cam_scan_lun; 1058111615Ssimokawa ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1059103285Sikob ccb->crcn.flags = CAM_FLAG_NONE; 1060103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 1061103285Sikob 1062103285Sikob /* The scan is in progress now. */ 1063170374Ssimokawa SBP_LOCK(target->sbp); 1064111040Ssimokawa xpt_action(ccb); 1065111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1066111615Ssimokawa sdev->freeze = 1; 1067170374Ssimokawa SBP_UNLOCK(target->sbp); 1068103285Sikob} 1069103285Sikob 1070111615Ssimokawastatic __inline void 1071111615Ssimokawasbp_scan_dev(struct sbp_dev *sdev) 1072111615Ssimokawa{ 1073111040Ssimokawa sdev->status = SBP_DEV_PROBE; 1074122387Ssimokawa callout_reset(&sdev->target->scan_callout, scan_delay * hz / 1000, 1075111615Ssimokawa sbp_cam_scan_target, (void *)sdev->target); 1076103285Sikob} 1077103285Sikob 1078103285Sikobstatic void 1079103285Sikobsbp_do_attach(struct fw_xfer *xfer) 1080103285Sikob{ 1081103285Sikob struct sbp_dev *sdev; 1082111615Ssimokawa struct sbp_target *target; 1083111615Ssimokawa struct sbp_softc *sbp; 1084103285Sikob 1085103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1086111615Ssimokawa target = sdev->target; 1087111615Ssimokawa sbp = target->sbp; 1088103285SikobSBP_DEBUG(0) 1089103285Sikob sbp_show_sdev_info(sdev, 2); 1090103285Sikob printf("sbp_do_attach\n"); 1091103285SikobEND_DEBUG 1092113584Ssimokawa sbp_xfer_free(xfer); 1093111199Ssimokawa 1094103285Sikob if (sdev->path == NULL) 1095103285Sikob xpt_create_path(&sdev->path, xpt_periph, 1096111615Ssimokawa cam_sim_path(target->sbp->sim), 1097111615Ssimokawa target->target_id, sdev->lun_id); 1098103285Sikob 1099111199Ssimokawa /* 1100111199Ssimokawa * Let CAM scan the bus if we are in the boot process. 1101111199Ssimokawa * XXX xpt_scan_bus cannot detect LUN larger than 0 1102111199Ssimokawa * if LUN 0 doesn't exists. 1103111199Ssimokawa */ 1104111199Ssimokawa if (sbp_cold > 0) { 1105111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1106111199Ssimokawa return; 1107111199Ssimokawa } 1108111199Ssimokawa 1109111615Ssimokawa sbp_scan_dev(sdev); 1110103285Sikob return; 1111103285Sikob} 1112103285Sikob 1113103285Sikobstatic void 1114103285Sikobsbp_agent_reset_callback(struct fw_xfer *xfer) 1115103285Sikob{ 1116103285Sikob struct sbp_dev *sdev; 1117103285Sikob 1118103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1119103285SikobSBP_DEBUG(1) 1120103285Sikob sbp_show_sdev_info(sdev, 2); 1121127468Ssimokawa printf("%s\n", __func__); 1122103285SikobEND_DEBUG 1123114732Ssimokawa if (xfer->resp != 0) { 1124114732Ssimokawa sbp_show_sdev_info(sdev, 2); 1125127468Ssimokawa printf("%s: resp=%d\n", __func__, xfer->resp); 1126114732Ssimokawa } 1127114732Ssimokawa 1128113584Ssimokawa sbp_xfer_free(xfer); 1129111615Ssimokawa if (sdev->path) { 1130170374Ssimokawa SBP_LOCK(sdev->target->sbp); 1131111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1132111615Ssimokawa sdev->freeze = 0; 1133170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 1134111615Ssimokawa } 1135103285Sikob} 1136103285Sikob 1137103285Sikobstatic void 1138110336Ssimokawasbp_agent_reset(struct sbp_dev *sdev) 1139103285Sikob{ 1140103285Sikob struct fw_xfer *xfer; 1141103285Sikob struct fw_pkt *fp; 1142103285Sikob 1143103285SikobSBP_DEBUG(0) 1144103285Sikob sbp_show_sdev_info(sdev, 2); 1145103285Sikob printf("sbp_agent_reset\n"); 1146103285SikobEND_DEBUG 1147103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04); 1148103285Sikob if (xfer == NULL) 1149103285Sikob return; 1150115788Ssimokawa if (sdev->status == SBP_DEV_ATTACHED || sdev->status == SBP_DEV_PROBE) 1151167632Ssimokawa xfer->hand = sbp_agent_reset_callback; 1152110336Ssimokawa else 1153167632Ssimokawa xfer->hand = sbp_do_attach; 1154120660Ssimokawa fp = &xfer->send.hdr; 1155103285Sikob fp->mode.wreqq.data = htonl(0xf); 1156103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1157111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_BDR_SENT); 1158103285Sikob} 1159103285Sikob 1160103285Sikobstatic void 1161103285Sikobsbp_busy_timeout_callback(struct fw_xfer *xfer) 1162103285Sikob{ 1163103285Sikob struct sbp_dev *sdev; 1164103285Sikob 1165103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1166103285SikobSBP_DEBUG(1) 1167103285Sikob sbp_show_sdev_info(sdev, 2); 1168110336Ssimokawa printf("sbp_busy_timeout_callback\n"); 1169103285SikobEND_DEBUG 1170113584Ssimokawa sbp_xfer_free(xfer); 1171110336Ssimokawa sbp_agent_reset(sdev); 1172103285Sikob} 1173103285Sikob 1174103285Sikobstatic void 1175103285Sikobsbp_busy_timeout(struct sbp_dev *sdev) 1176103285Sikob{ 1177103285Sikob struct fw_pkt *fp; 1178103285Sikob struct fw_xfer *xfer; 1179103285SikobSBP_DEBUG(0) 1180103285Sikob sbp_show_sdev_info(sdev, 2); 1181103285Sikob printf("sbp_busy_timeout\n"); 1182103285SikobEND_DEBUG 1183103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 1184103285Sikob 1185167632Ssimokawa xfer->hand = sbp_busy_timeout_callback; 1186120660Ssimokawa fp = &xfer->send.hdr; 1187113584Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 1188113584Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; 1189110129Ssimokawa fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf); 1190103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1191103285Sikob} 1192103285Sikob 1193103285Sikobstatic void 1194121185Ssimokawasbp_orb_pointer_callback(struct fw_xfer *xfer) 1195121185Ssimokawa{ 1196121185Ssimokawa struct sbp_dev *sdev; 1197121185Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 1198121185Ssimokawa 1199121185SsimokawaSBP_DEBUG(1) 1200121185Ssimokawa sbp_show_sdev_info(sdev, 2); 1201127468Ssimokawa printf("%s\n", __func__); 1202121185SsimokawaEND_DEBUG 1203121185Ssimokawa if (xfer->resp != 0) { 1204121185Ssimokawa /* XXX */ 1205127468Ssimokawa printf("%s: xfer->resp = %d\n", __func__, xfer->resp); 1206121185Ssimokawa } 1207121185Ssimokawa sbp_xfer_free(xfer); 1208121185Ssimokawa sdev->flags &= ~ORB_POINTER_ACTIVE; 1209121185Ssimokawa 1210121185Ssimokawa if ((sdev->flags & ORB_POINTER_NEED) != 0) { 1211121185Ssimokawa struct sbp_ocb *ocb; 1212121185Ssimokawa 1213121185Ssimokawa sdev->flags &= ~ORB_POINTER_NEED; 1214121185Ssimokawa ocb = STAILQ_FIRST(&sdev->ocbs); 1215121185Ssimokawa if (ocb != NULL) 1216121185Ssimokawa sbp_orb_pointer(sdev, ocb); 1217121185Ssimokawa } 1218121185Ssimokawa return; 1219121185Ssimokawa} 1220121185Ssimokawa 1221121185Ssimokawastatic void 1222103285Sikobsbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) 1223103285Sikob{ 1224103285Sikob struct fw_xfer *xfer; 1225103285Sikob struct fw_pkt *fp; 1226121185SsimokawaSBP_DEBUG(1) 1227103285Sikob sbp_show_sdev_info(sdev, 2); 1228129585Sdfr printf("%s: 0x%08x\n", __func__, (uint32_t)ocb->bus_addr); 1229103285SikobEND_DEBUG 1230103285Sikob 1231121185Ssimokawa if ((sdev->flags & ORB_POINTER_ACTIVE) != 0) { 1232122421SsimokawaSBP_DEBUG(0) 1233127468Ssimokawa printf("%s: orb pointer active\n", __func__); 1234122421SsimokawaEND_DEBUG 1235121185Ssimokawa sdev->flags |= ORB_POINTER_NEED; 1236121185Ssimokawa return; 1237121185Ssimokawa } 1238121185Ssimokawa 1239121185Ssimokawa sdev->flags |= ORB_POINTER_ACTIVE; 1240103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08); 1241103285Sikob if (xfer == NULL) 1242103285Sikob return; 1243167632Ssimokawa xfer->hand = sbp_orb_pointer_callback; 1244103285Sikob 1245120660Ssimokawa fp = &xfer->send.hdr; 1246113584Ssimokawa fp->mode.wreqb.len = 8; 1247103285Sikob fp->mode.wreqb.extcode = 0; 1248120660Ssimokawa xfer->send.payload[0] = 1249103285Sikob htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); 1250129585Sdfr xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr); 1251103285Sikob 1252103285Sikob if(fw_asyreq(xfer->fc, -1, xfer) != 0){ 1253113584Ssimokawa sbp_xfer_free(xfer); 1254103285Sikob ocb->ccb->ccb_h.status = CAM_REQ_INVALID; 1255103285Sikob xpt_done(ocb->ccb); 1256103285Sikob } 1257103285Sikob} 1258103285Sikob 1259103285Sikobstatic void 1260127468Ssimokawasbp_doorbell_callback(struct fw_xfer *xfer) 1261121185Ssimokawa{ 1262121185Ssimokawa struct sbp_dev *sdev; 1263121185Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 1264127468Ssimokawa 1265127468SsimokawaSBP_DEBUG(1) 1266121185Ssimokawa sbp_show_sdev_info(sdev, 2); 1267127468Ssimokawa printf("sbp_doorbell_callback\n"); 1268121185SsimokawaEND_DEBUG 1269121185Ssimokawa if (xfer->resp != 0) { 1270121185Ssimokawa /* XXX */ 1271127468Ssimokawa printf("%s: xfer->resp = %d\n", __func__, xfer->resp); 1272121185Ssimokawa } 1273121185Ssimokawa sbp_xfer_free(xfer); 1274127468Ssimokawa sdev->flags &= ~ORB_DOORBELL_ACTIVE; 1275127468Ssimokawa if ((sdev->flags & ORB_DOORBELL_NEED) != 0) { 1276127468Ssimokawa sdev->flags &= ~ORB_DOORBELL_NEED; 1277127468Ssimokawa sbp_doorbell(sdev); 1278127468Ssimokawa } 1279121185Ssimokawa return; 1280121185Ssimokawa} 1281121185Ssimokawa 1282121185Ssimokawastatic void 1283103285Sikobsbp_doorbell(struct sbp_dev *sdev) 1284103285Sikob{ 1285103285Sikob struct fw_xfer *xfer; 1286103285Sikob struct fw_pkt *fp; 1287103285SikobSBP_DEBUG(1) 1288103285Sikob sbp_show_sdev_info(sdev, 2); 1289103285Sikob printf("sbp_doorbell\n"); 1290103285SikobEND_DEBUG 1291103285Sikob 1292127468Ssimokawa if ((sdev->flags & ORB_DOORBELL_ACTIVE) != 0) { 1293127468Ssimokawa sdev->flags |= ORB_DOORBELL_NEED; 1294127468Ssimokawa return; 1295127468Ssimokawa } 1296127468Ssimokawa sdev->flags |= ORB_DOORBELL_ACTIVE; 1297103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10); 1298103285Sikob if (xfer == NULL) 1299103285Sikob return; 1300167632Ssimokawa xfer->hand = sbp_doorbell_callback; 1301127468Ssimokawa fp = &xfer->send.hdr; 1302103285Sikob fp->mode.wreqq.data = htonl(0xf); 1303103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1304103285Sikob} 1305103285Sikob 1306103285Sikobstatic struct fw_xfer * 1307103285Sikobsbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) 1308103285Sikob{ 1309103285Sikob struct fw_xfer *xfer; 1310103285Sikob struct fw_pkt *fp; 1311113584Ssimokawa struct sbp_target *target; 1312113584Ssimokawa int s, new = 0; 1313103285Sikob 1314113584Ssimokawa target = sdev->target; 1315113584Ssimokawa s = splfw(); 1316113584Ssimokawa xfer = STAILQ_FIRST(&target->xferlist); 1317113584Ssimokawa if (xfer == NULL) { 1318113584Ssimokawa if (target->n_xfer > 5 /* XXX */) { 1319113584Ssimokawa printf("sbp: no more xfer for this target\n"); 1320113584Ssimokawa splx(s); 1321113584Ssimokawa return(NULL); 1322113584Ssimokawa } 1323120660Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 8, 0); 1324113584Ssimokawa if(xfer == NULL){ 1325113584Ssimokawa printf("sbp: fw_xfer_alloc_buf failed\n"); 1326113584Ssimokawa splx(s); 1327113584Ssimokawa return NULL; 1328113584Ssimokawa } 1329113584Ssimokawa target->n_xfer ++; 1330113584Ssimokawa if (debug) 1331113584Ssimokawa printf("sbp: alloc %d xfer\n", target->n_xfer); 1332113584Ssimokawa new = 1; 1333113584Ssimokawa } else { 1334113584Ssimokawa STAILQ_REMOVE_HEAD(&target->xferlist, link); 1335103285Sikob } 1336113584Ssimokawa splx(s); 1337113584Ssimokawa 1338113584Ssimokawa microtime(&xfer->tv); 1339113584Ssimokawa 1340113584Ssimokawa if (new) { 1341120660Ssimokawa xfer->recv.pay_len = 0; 1342120660Ssimokawa xfer->send.spd = min(sdev->target->fwdev->speed, max_speed); 1343113584Ssimokawa xfer->fc = sdev->target->sbp->fd.fc; 1344103285Sikob } 1345120660Ssimokawa 1346120660Ssimokawa if (tcode == FWTCODE_WREQB) 1347120660Ssimokawa xfer->send.pay_len = 8; 1348120660Ssimokawa else 1349120660Ssimokawa xfer->send.pay_len = 0; 1350120660Ssimokawa 1351103285Sikob xfer->sc = (caddr_t)sdev; 1352120660Ssimokawa fp = &xfer->send.hdr; 1353113584Ssimokawa fp->mode.wreqq.dest_hi = sdev->login->cmd_hi; 1354113584Ssimokawa fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset; 1355103285Sikob fp->mode.wreqq.tlrt = 0; 1356103285Sikob fp->mode.wreqq.tcode = tcode; 1357103285Sikob fp->mode.wreqq.pri = 0; 1358120660Ssimokawa fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst; 1359103285Sikob 1360103285Sikob return xfer; 1361103285Sikob 1362103285Sikob} 1363103285Sikob 1364103285Sikobstatic void 1365111615Ssimokawasbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) 1366103285Sikob{ 1367103285Sikob struct fw_xfer *xfer; 1368103285Sikob struct fw_pkt *fp; 1369103285Sikob struct sbp_ocb *ocb; 1370111615Ssimokawa struct sbp_target *target; 1371103285Sikob int s, nid; 1372103285Sikob 1373111615Ssimokawa target = sdev->target; 1374111615Ssimokawa nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; 1375111615Ssimokawa 1376111615Ssimokawa s = splfw(); 1377170374Ssimokawa SBP_LOCK(target->sbp); 1378111615Ssimokawa if (func == ORB_FUN_RUNQUEUE) { 1379111615Ssimokawa ocb = STAILQ_FIRST(&target->mgm_ocb_queue); 1380111615Ssimokawa if (target->mgm_ocb_cur != NULL || ocb == NULL) { 1381170374Ssimokawa SBP_UNLOCK(target->sbp); 1382111615Ssimokawa splx(s); 1383111615Ssimokawa return; 1384111615Ssimokawa } 1385111615Ssimokawa STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); 1386170374Ssimokawa SBP_UNLOCK(target->sbp); 1387111615Ssimokawa goto start; 1388111615Ssimokawa } 1389113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 1390170374Ssimokawa SBP_UNLOCK(target->sbp); 1391103285Sikob splx(s); 1392122528Ssimokawa /* XXX */ 1393103285Sikob return; 1394103285Sikob } 1395170374Ssimokawa SBP_UNLOCK(target->sbp); 1396103285Sikob ocb->flags = OCB_ACT_MGM; 1397103285Sikob ocb->sdev = sdev; 1398103285Sikob 1399120660Ssimokawa bzero((void *)ocb->orb, sizeof(ocb->orb)); 1400103285Sikob ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI); 1401120660Ssimokawa ocb->orb[7] = htonl(SBP_DEV2ADDR(target->target_id, sdev->lun_id)); 1402103285Sikob 1403107653SsimokawaSBP_DEBUG(0) 1404103285Sikob sbp_show_sdev_info(sdev, 2); 1405103285Sikob printf("%s\n", orb_fun_name[(func>>16)&0xf]); 1406107653SsimokawaEND_DEBUG 1407103285Sikob switch (func) { 1408103285Sikob case ORB_FUN_LGI: 1409120660Ssimokawa ocb->orb[0] = ocb->orb[1] = 0; /* password */ 1410103285Sikob ocb->orb[2] = htonl(nid << 16); 1411113584Ssimokawa ocb->orb[3] = htonl(sdev->dma.bus_addr); 1412121792Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | sdev->lun_id); 1413122387Ssimokawa if (ex_login) 1414121792Ssimokawa ocb->orb[4] |= htonl(ORB_EXV); 1415113584Ssimokawa ocb->orb[5] = htonl(SBP_LOGIN_SIZE); 1416113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD); 1417103285Sikob break; 1418110336Ssimokawa case ORB_FUN_ATA: 1419111615Ssimokawa ocb->orb[0] = htonl((0 << 16) | 0); 1420113584Ssimokawa ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff); 1421110336Ssimokawa /* fall through */ 1422103285Sikob case ORB_FUN_RCN: 1423103285Sikob case ORB_FUN_LGO: 1424103285Sikob case ORB_FUN_LUR: 1425103285Sikob case ORB_FUN_RST: 1426103285Sikob case ORB_FUN_ATS: 1427113584Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id); 1428103285Sikob break; 1429103285Sikob } 1430103285Sikob 1431111615Ssimokawa if (target->mgm_ocb_cur != NULL) { 1432111615Ssimokawa /* there is a standing ORB */ 1433170374Ssimokawa SBP_LOCK(target->sbp); 1434111615Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); 1435170374Ssimokawa SBP_UNLOCK(target->sbp); 1436111615Ssimokawa splx(s); 1437111615Ssimokawa return; 1438111615Ssimokawa } 1439111615Ssimokawastart: 1440111615Ssimokawa target->mgm_ocb_cur = ocb; 1441111615Ssimokawa splx(s); 1442111615Ssimokawa 1443111615Ssimokawa callout_reset(&target->mgm_ocb_timeout, 5*hz, 1444114732Ssimokawa sbp_mgm_timeout, (caddr_t)ocb); 1445103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); 1446103285Sikob if(xfer == NULL){ 1447103285Sikob return; 1448103285Sikob } 1449167632Ssimokawa xfer->hand = sbp_mgm_callback; 1450103285Sikob 1451120660Ssimokawa fp = &xfer->send.hdr; 1452113584Ssimokawa fp->mode.wreqb.dest_hi = sdev->target->mgm_hi; 1453113584Ssimokawa fp->mode.wreqb.dest_lo = sdev->target->mgm_lo; 1454113584Ssimokawa fp->mode.wreqb.len = 8; 1455103285Sikob fp->mode.wreqb.extcode = 0; 1456120660Ssimokawa xfer->send.payload[0] = htonl(nid << 16); 1457120660Ssimokawa xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff); 1458120660SsimokawaSBP_DEBUG(0) 1459120660Ssimokawa sbp_show_sdev_info(sdev, 2); 1460129585Sdfr printf("mgm orb: %08x\n", (uint32_t)ocb->bus_addr); 1461120660SsimokawaEND_DEBUG 1462103285Sikob 1463103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1464103285Sikob} 1465103285Sikob 1466103285Sikobstatic void 1467105792Ssimokawasbp_print_scsi_cmd(struct sbp_ocb *ocb) 1468103285Sikob{ 1469103285Sikob struct ccb_scsiio *csio; 1470103285Sikob 1471103285Sikob csio = &ocb->ccb->csio; 1472103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 1473103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 1474103285Sikob ", flags: 0x%02x, " 1475103285Sikob "%db cmd/%db data/%db sense\n", 1476103285Sikob device_get_nameunit(ocb->sdev->target->sbp->fd.dev), 1477103285Sikob ocb->ccb->ccb_h.target_id, ocb->ccb->ccb_h.target_lun, 1478103285Sikob csio->cdb_io.cdb_bytes[0], 1479103285Sikob csio->cdb_io.cdb_bytes[1], 1480103285Sikob csio->cdb_io.cdb_bytes[2], 1481103285Sikob csio->cdb_io.cdb_bytes[3], 1482103285Sikob csio->cdb_io.cdb_bytes[4], 1483103285Sikob csio->cdb_io.cdb_bytes[5], 1484103285Sikob csio->cdb_io.cdb_bytes[6], 1485103285Sikob csio->cdb_io.cdb_bytes[7], 1486103285Sikob csio->cdb_io.cdb_bytes[8], 1487103285Sikob csio->cdb_io.cdb_bytes[9], 1488103285Sikob ocb->ccb->ccb_h.flags & CAM_DIR_MASK, 1489103285Sikob csio->cdb_len, csio->dxfer_len, 1490103285Sikob csio->sense_len); 1491105792Ssimokawa} 1492105792Ssimokawa 1493105792Ssimokawastatic void 1494105792Ssimokawasbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb) 1495105792Ssimokawa{ 1496105792Ssimokawa struct sbp_cmd_status *sbp_cmd_status; 1497105792Ssimokawa struct scsi_sense_data *sense; 1498105792Ssimokawa 1499105792Ssimokawa sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data; 1500105792Ssimokawa sense = &ocb->ccb->csio.sense_data; 1501105792Ssimokawa 1502105792SsimokawaSBP_DEBUG(0) 1503105792Ssimokawa sbp_print_scsi_cmd(ocb); 1504103285Sikob /* XXX need decode status */ 1505103285Sikob sbp_show_sdev_info(ocb->sdev, 2); 1506113584Ssimokawa printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", 1507103285Sikob sbp_cmd_status->status, 1508103285Sikob sbp_cmd_status->sfmt, 1509103285Sikob sbp_cmd_status->valid, 1510103285Sikob sbp_cmd_status->s_key, 1511103285Sikob sbp_cmd_status->s_code, 1512103285Sikob sbp_cmd_status->s_qlfr, 1513103285Sikob sbp_status->len 1514103285Sikob ); 1515103285SikobEND_DEBUG 1516103285Sikob 1517110071Ssimokawa switch (sbp_cmd_status->status) { 1518110071Ssimokawa case SCSI_STATUS_CHECK_COND: 1519110071Ssimokawa case SCSI_STATUS_BUSY: 1520110071Ssimokawa case SCSI_STATUS_CMD_TERMINATED: 1521103285Sikob if(sbp_cmd_status->sfmt == SBP_SFMT_CURR){ 1522103285Sikob sense->error_code = SSD_CURRENT_ERROR; 1523103285Sikob }else{ 1524103285Sikob sense->error_code = SSD_DEFERRED_ERROR; 1525103285Sikob } 1526103285Sikob if(sbp_cmd_status->valid) 1527103285Sikob sense->error_code |= SSD_ERRCODE_VALID; 1528103285Sikob sense->flags = sbp_cmd_status->s_key; 1529103285Sikob if(sbp_cmd_status->mark) 1530103285Sikob sense->flags |= SSD_FILEMARK; 1531103285Sikob if(sbp_cmd_status->eom) 1532103285Sikob sense->flags |= SSD_EOM; 1533103285Sikob if(sbp_cmd_status->ill_len) 1534103285Sikob sense->flags |= SSD_ILI; 1535119556Ssimokawa 1536119556Ssimokawa bcopy(&sbp_cmd_status->info, &sense->info[0], 4); 1537119556Ssimokawa 1538103285Sikob if (sbp_status->len <= 1) 1539103285Sikob /* XXX not scsi status. shouldn't be happened */ 1540103285Sikob sense->extra_len = 0; 1541103285Sikob else if (sbp_status->len <= 4) 1542103285Sikob /* add_sense_code(_qual), info, cmd_spec_info */ 1543103285Sikob sense->extra_len = 6; 1544103285Sikob else 1545103285Sikob /* fru, sense_key_spec */ 1546103285Sikob sense->extra_len = 10; 1547119556Ssimokawa 1548119556Ssimokawa bcopy(&sbp_cmd_status->cdb, &sense->cmd_spec_info[0], 4); 1549119556Ssimokawa 1550103285Sikob sense->add_sense_code = sbp_cmd_status->s_code; 1551103285Sikob sense->add_sense_code_qual = sbp_cmd_status->s_qlfr; 1552103285Sikob sense->fru = sbp_cmd_status->fru; 1553103285Sikob 1554119556Ssimokawa bcopy(&sbp_cmd_status->s_keydep[0], 1555119556Ssimokawa &sense->sense_key_spec[0], 3); 1556119556Ssimokawa 1557103285Sikob ocb->ccb->csio.scsi_status = sbp_cmd_status->status;; 1558103285Sikob ocb->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR 1559103285Sikob | CAM_AUTOSNS_VALID; 1560103285Sikob/* 1561103285Sikob{ 1562129585Sdfr uint8_t j, *tmp; 1563103285Sikob tmp = sense; 1564103285Sikob for( j = 0 ; j < 32 ; j+=8){ 1565103285Sikob printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n", 1566103285Sikob tmp[j], tmp[j+1], tmp[j+2], tmp[j+3], 1567103285Sikob tmp[j+4], tmp[j+5], tmp[j+6], tmp[j+7]); 1568103285Sikob } 1569103285Sikob 1570103285Sikob} 1571103285Sikob*/ 1572110071Ssimokawa break; 1573110071Ssimokawa default: 1574110071Ssimokawa sbp_show_sdev_info(ocb->sdev, 2); 1575110071Ssimokawa printf("sbp_scsi_status: unknown scsi status 0x%x\n", 1576110071Ssimokawa sbp_cmd_status->status); 1577103285Sikob } 1578103285Sikob} 1579103285Sikob 1580103285Sikobstatic void 1581103285Sikobsbp_fix_inq_data(struct sbp_ocb *ocb) 1582103285Sikob{ 1583103285Sikob union ccb *ccb; 1584103285Sikob struct sbp_dev *sdev; 1585103285Sikob struct scsi_inquiry_data *inq; 1586103285Sikob 1587103285Sikob ccb = ocb->ccb; 1588103285Sikob sdev = ocb->sdev; 1589103285Sikob 1590103285Sikob if (ccb->csio.cdb_io.cdb_bytes[1] & SI_EVPD) 1591103285Sikob return; 1592103285SikobSBP_DEBUG(1) 1593103285Sikob sbp_show_sdev_info(sdev, 2); 1594103285Sikob printf("sbp_fix_inq_data\n"); 1595103285SikobEND_DEBUG 1596103285Sikob inq = (struct scsi_inquiry_data *) ccb->csio.data_ptr; 1597103285Sikob switch (SID_TYPE(inq)) { 1598103285Sikob case T_DIRECT: 1599118291Ssimokawa#if 0 1600103285Sikob /* 1601103285Sikob * XXX Convert Direct Access device to RBC. 1602108281Ssimokawa * I've never seen FireWire DA devices which support READ_6. 1603103285Sikob */ 1604103285Sikob if (SID_TYPE(inq) == T_DIRECT) 1605103285Sikob inq->device |= T_RBC; /* T_DIRECT == 0 */ 1606103285Sikob#endif 1607103285Sikob /* fall through */ 1608103285Sikob case T_RBC: 1609103285Sikob /* 1610103285Sikob * Override vendor/product/revision information. 1611103285Sikob * Some devices sometimes return strange strings. 1612103285Sikob */ 1613111615Ssimokawa#if 1 1614103285Sikob bcopy(sdev->vendor, inq->vendor, sizeof(inq->vendor)); 1615103285Sikob bcopy(sdev->product, inq->product, sizeof(inq->product)); 1616103285Sikob bcopy(sdev->revision+2, inq->revision, sizeof(inq->revision)); 1617111615Ssimokawa#endif 1618103285Sikob break; 1619103285Sikob } 1620127468Ssimokawa /* 1621127468Ssimokawa * Force to enable/disable tagged queuing. 1622127468Ssimokawa * XXX CAM also checks SCP_QUEUE_DQUE flag in the control mode page. 1623127468Ssimokawa */ 1624127468Ssimokawa if (sbp_tags > 0) 1625127468Ssimokawa inq->flags |= SID_CmdQue; 1626127468Ssimokawa else if (sbp_tags < 0) 1627127468Ssimokawa inq->flags &= ~SID_CmdQue; 1628127468Ssimokawa 1629103285Sikob} 1630103285Sikob 1631103285Sikobstatic void 1632113584Ssimokawasbp_recv1(struct fw_xfer *xfer) 1633113584Ssimokawa{ 1634103285Sikob struct fw_pkt *rfp; 1635103285Sikob#if NEED_RESPONSE 1636103285Sikob struct fw_pkt *sfp; 1637103285Sikob#endif 1638103285Sikob struct sbp_softc *sbp; 1639103285Sikob struct sbp_dev *sdev; 1640103285Sikob struct sbp_ocb *ocb; 1641103285Sikob struct sbp_login_res *login_res = NULL; 1642103285Sikob struct sbp_status *sbp_status; 1643103285Sikob struct sbp_target *target; 1644111704Ssimokawa int orb_fun, status_valid0, status_valid, t, l, reset_agent = 0; 1645129585Sdfr uint32_t addr; 1646103285Sikob/* 1647129585Sdfr uint32_t *ld; 1648103285Sikob ld = xfer->recv.buf; 1649103285Sikobprintf("sbp %x %d %d %08x %08x %08x %08x\n", 1650103285Sikob xfer->resp, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 1651103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 1652103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11])); 1653103285Sikob*/ 1654113584Ssimokawa sbp = (struct sbp_softc *)xfer->sc; 1655120660Ssimokawa if (xfer->resp != 0){ 1656122529Ssimokawa printf("sbp_recv: xfer->resp = %d\n", xfer->resp); 1657113584Ssimokawa goto done0; 1658103285Sikob } 1659120660Ssimokawa if (xfer->recv.payload == NULL){ 1660120660Ssimokawa printf("sbp_recv: xfer->recv.payload == NULL\n"); 1661113584Ssimokawa goto done0; 1662103285Sikob } 1663120660Ssimokawa rfp = &xfer->recv.hdr; 1664103285Sikob if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){ 1665103285Sikob printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); 1666113584Ssimokawa goto done0; 1667103285Sikob } 1668120660Ssimokawa sbp_status = (struct sbp_status *)xfer->recv.payload; 1669113584Ssimokawa addr = rfp->mode.wreqb.dest_lo; 1670103285SikobSBP_DEBUG(2) 1671103285Sikob printf("received address 0x%x\n", addr); 1672103285SikobEND_DEBUG 1673110189Ssimokawa t = SBP_ADDR2TRG(addr); 1674110189Ssimokawa if (t >= SBP_NUM_TARGETS) { 1675110189Ssimokawa device_printf(sbp->fd.dev, 1676110189Ssimokawa "sbp_recv1: invalid target %d\n", t); 1677113584Ssimokawa goto done0; 1678110189Ssimokawa } 1679110189Ssimokawa target = &sbp->targets[t]; 1680110189Ssimokawa l = SBP_ADDR2LUN(addr); 1681121185Ssimokawa if (l >= target->num_lun || target->luns[l] == NULL) { 1682110189Ssimokawa device_printf(sbp->fd.dev, 1683110189Ssimokawa "sbp_recv1: invalid lun %d (target=%d)\n", l, t); 1684113584Ssimokawa goto done0; 1685110189Ssimokawa } 1686121185Ssimokawa sdev = target->luns[l]; 1687103285Sikob 1688110189Ssimokawa ocb = NULL; 1689110189Ssimokawa switch (sbp_status->src) { 1690110189Ssimokawa case 0: 1691110189Ssimokawa case 1: 1692111615Ssimokawa /* check mgm_ocb_cur first */ 1693111615Ssimokawa ocb = target->mgm_ocb_cur; 1694111615Ssimokawa if (ocb != NULL) { 1695111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 1696111615Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1697111615Ssimokawa target->mgm_ocb_cur = NULL; 1698111615Ssimokawa break; 1699111615Ssimokawa } 1700111615Ssimokawa } 1701111615Ssimokawa ocb = sbp_dequeue_ocb(sdev, sbp_status); 1702110189Ssimokawa if (ocb == NULL) { 1703110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1704127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 1705127468Ssimokawa printf("No ocb(%lx) on the queue\n", 1706127468Ssimokawa#else 1707111819Ssimokawa printf("No ocb(%x) on the queue\n", 1708111858Ssimokawa#endif 1709111819Ssimokawa ntohl(sbp_status->orb_lo)); 1710110189Ssimokawa } 1711110189Ssimokawa break; 1712110189Ssimokawa case 2: 1713110189Ssimokawa /* unsolicit */ 1714110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1715110189Ssimokawa printf("unsolicit status received\n"); 1716110189Ssimokawa break; 1717110189Ssimokawa default: 1718110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1719110189Ssimokawa printf("unknown sbp_status->src\n"); 1720110189Ssimokawa } 1721110189Ssimokawa 1722111615Ssimokawa status_valid0 = (sbp_status->src < 2 1723110189Ssimokawa && sbp_status->resp == ORB_RES_CMPL 1724111615Ssimokawa && sbp_status->dead == 0); 1725111615Ssimokawa status_valid = (status_valid0 && sbp_status->status == 0); 1726103285Sikob 1727121185Ssimokawa if (!status_valid0 || debug > 2){ 1728103285Sikob int status; 1729110129SsimokawaSBP_DEBUG(0) 1730103285Sikob sbp_show_sdev_info(sdev, 2); 1731103285Sikob printf("ORB status src:%x resp:%x dead:%x" 1732127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 1733127468Ssimokawa " len:%x stat:%x orb:%x%08lx\n", 1734127468Ssimokawa#else 1735103285Sikob " len:%x stat:%x orb:%x%08x\n", 1736108712Ssimokawa#endif 1737103285Sikob sbp_status->src, sbp_status->resp, sbp_status->dead, 1738103285Sikob sbp_status->len, sbp_status->status, 1739108280Ssimokawa ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); 1740110129SsimokawaEND_DEBUG 1741103285Sikob sbp_show_sdev_info(sdev, 2); 1742103285Sikob status = sbp_status->status; 1743103285Sikob switch(sbp_status->resp) { 1744103285Sikob case 0: 1745103285Sikob if (status > MAX_ORB_STATUS0) 1746103285Sikob printf("%s\n", orb_status0[MAX_ORB_STATUS0]); 1747110189Ssimokawa else 1748110129Ssimokawa printf("%s\n", orb_status0[status]); 1749103285Sikob break; 1750103285Sikob case 1: 1751110336Ssimokawa printf("Obj: %s, Error: %s\n", 1752103285Sikob orb_status1_object[(status>>6) & 3], 1753103285Sikob orb_status1_serial_bus_error[status & 0xf]); 1754103285Sikob break; 1755110129Ssimokawa case 2: 1756110129Ssimokawa printf("Illegal request\n"); 1757110129Ssimokawa break; 1758110129Ssimokawa case 3: 1759110129Ssimokawa printf("Vendor dependent\n"); 1760110129Ssimokawa break; 1761103285Sikob default: 1762110129Ssimokawa printf("unknown respose code %d\n", sbp_status->resp); 1763103285Sikob } 1764103285Sikob } 1765103285Sikob 1766103285Sikob /* we have to reset the fetch agent if it's dead */ 1767103285Sikob if (sbp_status->dead) { 1768111615Ssimokawa if (sdev->path) { 1769170374Ssimokawa SBP_LOCK(sbp); 1770103285Sikob xpt_freeze_devq(sdev->path, 1); 1771111615Ssimokawa sdev->freeze ++; 1772170374Ssimokawa SBP_UNLOCK(sbp); 1773111615Ssimokawa } 1774111704Ssimokawa reset_agent = 1; 1775103285Sikob } 1776103285Sikob 1777111704Ssimokawa if (ocb == NULL) 1778111704Ssimokawa goto done; 1779103285Sikob 1780103285Sikob switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK){ 1781103285Sikob case ORB_FMT_NOP: 1782103285Sikob break; 1783103285Sikob case ORB_FMT_VED: 1784103285Sikob break; 1785103285Sikob case ORB_FMT_STD: 1786111819Ssimokawa switch(ocb->flags) { 1787103285Sikob case OCB_ACT_MGM: 1788103285Sikob orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK; 1789120842Ssimokawa reset_agent = 0; 1790103285Sikob switch(orb_fun) { 1791103285Sikob case ORB_FUN_LGI: 1792113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD); 1793113584Ssimokawa login_res = sdev->login; 1794103285Sikob login_res->len = ntohs(login_res->len); 1795103285Sikob login_res->id = ntohs(login_res->id); 1796103285Sikob login_res->cmd_hi = ntohs(login_res->cmd_hi); 1797103285Sikob login_res->cmd_lo = ntohl(login_res->cmd_lo); 1798103285Sikob if (status_valid) { 1799103285SikobSBP_DEBUG(0) 1800103285Sikobsbp_show_sdev_info(sdev, 2); 1801103285Sikobprintf("login: len %d, ID %d, cmd %08x%08x, recon_hold %d\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo, ntohs(login_res->recon_hold)); 1802103285SikobEND_DEBUG 1803103285Sikob sbp_busy_timeout(sdev); 1804103285Sikob } else { 1805110336Ssimokawa /* forgot logout? */ 1806110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1807103285Sikob printf("login failed\n"); 1808103285Sikob sdev->status = SBP_DEV_RESET; 1809103285Sikob } 1810103285Sikob break; 1811103285Sikob case ORB_FUN_RCN: 1812113584Ssimokawa login_res = sdev->login; 1813103285Sikob if (status_valid) { 1814103285SikobSBP_DEBUG(0) 1815103285Sikobsbp_show_sdev_info(sdev, 2); 1816103285Sikobprintf("reconnect: len %d, ID %d, cmd %08x%08x\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo); 1817103285SikobEND_DEBUG 1818103285Sikob#if 1 1819111615Ssimokawa if (sdev->status == SBP_DEV_ATTACHED) 1820111615Ssimokawa sbp_scan_dev(sdev); 1821111615Ssimokawa else 1822111615Ssimokawa sbp_agent_reset(sdev); 1823103285Sikob#else 1824110336Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1825111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_ATS, NULL); 1826103285Sikob#endif 1827103285Sikob } else { 1828103285Sikob /* reconnection hold time exceed? */ 1829110336SsimokawaSBP_DEBUG(0) 1830110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1831103285Sikob printf("reconnect failed\n"); 1832110336SsimokawaEND_DEBUG 1833111615Ssimokawa sbp_login(sdev); 1834103285Sikob } 1835103285Sikob break; 1836103285Sikob case ORB_FUN_LGO: 1837103285Sikob sdev->status = SBP_DEV_RESET; 1838103285Sikob break; 1839110336Ssimokawa case ORB_FUN_RST: 1840110336Ssimokawa sbp_busy_timeout(sdev); 1841110336Ssimokawa break; 1842103285Sikob case ORB_FUN_LUR: 1843103285Sikob case ORB_FUN_ATA: 1844103285Sikob case ORB_FUN_ATS: 1845110336Ssimokawa sbp_agent_reset(sdev); 1846103285Sikob break; 1847103285Sikob default: 1848110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1849110336Ssimokawa printf("unknown function %d\n", orb_fun); 1850103285Sikob break; 1851103285Sikob } 1852111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 1853103285Sikob break; 1854103285Sikob case OCB_ACT_CMD: 1855114732Ssimokawa sdev->timeout = 0; 1856103285Sikob if(ocb->ccb != NULL){ 1857103285Sikob union ccb *ccb; 1858103285Sikob/* 1859129585Sdfr uint32_t *ld; 1860103285Sikob ld = ocb->ccb->csio.data_ptr; 1861103285Sikob if(ld != NULL && ocb->ccb->csio.dxfer_len != 0) 1862103285Sikob printf("ptr %08x %08x %08x %08x\n", ld[0], ld[1], ld[2], ld[3]); 1863103285Sikob else 1864103285Sikob printf("ptr NULL\n"); 1865103285Sikobprintf("len %d\n", sbp_status->len); 1866103285Sikob*/ 1867103285Sikob ccb = ocb->ccb; 1868103285Sikob if(sbp_status->len > 1){ 1869103285Sikob sbp_scsi_status(sbp_status, ocb); 1870103285Sikob }else{ 1871103285Sikob if(sbp_status->resp != ORB_RES_CMPL){ 1872103285Sikob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1873103285Sikob }else{ 1874103285Sikob ccb->ccb_h.status = CAM_REQ_CMP; 1875103285Sikob } 1876103285Sikob } 1877103285Sikob /* fix up inq data */ 1878103285Sikob if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY) 1879103285Sikob sbp_fix_inq_data(ocb); 1880170374Ssimokawa SBP_LOCK(sbp); 1881103285Sikob xpt_done(ccb); 1882170374Ssimokawa SBP_UNLOCK(sbp); 1883103285Sikob } 1884103285Sikob break; 1885103285Sikob default: 1886103285Sikob break; 1887103285Sikob } 1888103285Sikob } 1889103285Sikob 1890127468Ssimokawa if (!use_doorbell) 1891127468Ssimokawa sbp_free_ocb(sdev, ocb); 1892111704Ssimokawadone: 1893111704Ssimokawa if (reset_agent) 1894111704Ssimokawa sbp_agent_reset(sdev); 1895103285Sikob 1896113584Ssimokawadone0: 1897120660Ssimokawa xfer->recv.pay_len = SBP_RECV_LEN; 1898103285Sikob/* The received packet is usually small enough to be stored within 1899103285Sikob * the buffer. In that case, the controller return ack_complete and 1900103285Sikob * no respose is necessary. 1901103285Sikob * 1902103285Sikob * XXX fwohci.c and firewire.c should inform event_code such as 1903103285Sikob * ack_complete or ack_pending to upper driver. 1904103285Sikob */ 1905103285Sikob#if NEED_RESPONSE 1906103285Sikob xfer->send.off = 0; 1907103285Sikob sfp = (struct fw_pkt *)xfer->send.buf; 1908103285Sikob sfp->mode.wres.dst = rfp->mode.wreqb.src; 1909113584Ssimokawa xfer->dst = sfp->mode.wres.dst; 1910103285Sikob xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1911167632Ssimokawa xfer->hand = sbp_loginres_callback; 1912103285Sikob 1913103285Sikob sfp->mode.wres.tlrt = rfp->mode.wreqb.tlrt; 1914103285Sikob sfp->mode.wres.tcode = FWTCODE_WRES; 1915103285Sikob sfp->mode.wres.rtcode = 0; 1916103285Sikob sfp->mode.wres.pri = 0; 1917103285Sikob 1918103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1919103285Sikob#else 1920113584Ssimokawa /* recycle */ 1921113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1922103285Sikob#endif 1923103285Sikob 1924103285Sikob return; 1925103285Sikob 1926103285Sikob} 1927103285Sikob 1928103285Sikobstatic void 1929103285Sikobsbp_recv(struct fw_xfer *xfer) 1930103285Sikob{ 1931103285Sikob int s; 1932103285Sikob 1933103285Sikob s = splcam(); 1934103285Sikob sbp_recv1(xfer); 1935103285Sikob splx(s); 1936103285Sikob} 1937103285Sikob/* 1938103285Sikob * sbp_attach() 1939103285Sikob */ 1940103285Sikobstatic int 1941103285Sikobsbp_attach(device_t dev) 1942103285Sikob{ 1943103285Sikob struct sbp_softc *sbp; 1944103285Sikob struct cam_devq *devq; 1945170374Ssimokawa struct firewire_comm *fc; 1946103285Sikob int i, s, error; 1947103285Sikob 1948167624Ssimokawa if (DFLTPHYS > SBP_MAXPHYS) 1949167624Ssimokawa device_printf(dev, "Warning, DFLTPHYS(%dKB) is larger than " 1950167624Ssimokawa "SBP_MAXPHYS(%dKB).\n", DFLTPHYS / 1024, 1951167624Ssimokawa SBP_MAXPHYS / 1024); 1952167624Ssimokawa 1953170400Ssimokawa if (!firewire_phydma_enable) 1954170400Ssimokawa device_printf(dev, "Warning, hw.firewire.phydma_enable must be 1 " 1955170400Ssimokawa "for SBP over FireWire.\n"); 1956103285SikobSBP_DEBUG(0) 1957111199Ssimokawa printf("sbp_attach (cold=%d)\n", cold); 1958103285SikobEND_DEBUG 1959103285Sikob 1960111199Ssimokawa if (cold) 1961111199Ssimokawa sbp_cold ++; 1962103285Sikob sbp = ((struct sbp_softc *)device_get_softc(dev)); 1963103285Sikob bzero(sbp, sizeof(struct sbp_softc)); 1964103285Sikob sbp->fd.dev = dev; 1965170374Ssimokawa sbp->fd.fc = fc = device_get_ivars(dev); 1966170374Ssimokawa mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF); 1967124251Ssimokawa 1968124251Ssimokawa if (max_speed < 0) 1969170374Ssimokawa max_speed = fc->speed; 1970124251Ssimokawa 1971170374Ssimokawa error = bus_dma_tag_create(/*parent*/fc->dmat, 1972113584Ssimokawa /* XXX shoud be 4 for sane backend? */ 1973113584Ssimokawa /*alignment*/1, 1974103285Sikob /*boundary*/0, 1975103285Sikob /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1976103285Sikob /*highaddr*/BUS_SPACE_MAXADDR, 1977103285Sikob /*filter*/NULL, /*filterarg*/NULL, 1978103285Sikob /*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX, 1979113474Ssimokawa /*maxsegsz*/SBP_SEG_MAX, 1980103285Sikob /*flags*/BUS_DMA_ALLOCNOW, 1981127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 1982117126Sscottl /*lockfunc*/busdma_lock_mutex, 1983170374Ssimokawa /*lockarg*/&sbp->mtx, 1984117228Ssimokawa#endif 1985117228Ssimokawa &sbp->dmat); 1986103285Sikob if (error != 0) { 1987103285Sikob printf("sbp_attach: Could not allocate DMA tag " 1988103285Sikob "- error %d\n", error); 1989103285Sikob return (ENOMEM); 1990103285Sikob } 1991103285Sikob 1992103285Sikob devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB); 1993103285Sikob if (devq == NULL) 1994103285Sikob return (ENXIO); 1995103285Sikob 1996103285Sikob for( i = 0 ; i < SBP_NUM_TARGETS ; i++){ 1997103285Sikob sbp->targets[i].fwdev = NULL; 1998103285Sikob sbp->targets[i].luns = NULL; 1999103285Sikob } 2000103285Sikob 2001103285Sikob sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp, 2002103285Sikob device_get_unit(dev), 2003170374Ssimokawa &sbp->mtx, 2004111615Ssimokawa /*untagged*/ 1, 2005122528Ssimokawa /*tagged*/ SBP_QUEUE_LEN - 1, 2006111615Ssimokawa devq); 2007103285Sikob 2008103285Sikob if (sbp->sim == NULL) { 2009103285Sikob cam_simq_free(devq); 2010103285Sikob return (ENXIO); 2011103285Sikob } 2012103285Sikob 2013170374Ssimokawa SBP_LOCK(sbp); 2014111615Ssimokawa if (xpt_bus_register(sbp->sim, /*bus*/0) != CAM_SUCCESS) 2015111615Ssimokawa goto fail; 2016103285Sikob 2017111615Ssimokawa if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim), 2018120660Ssimokawa CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2019120660Ssimokawa xpt_bus_deregister(cam_sim_path(sbp->sim)); 2020111615Ssimokawa goto fail; 2021120660Ssimokawa } 2022170374Ssimokawa SBP_UNLOCK(sbp); 2023111615Ssimokawa 2024103285Sikob /* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */ 2025120660Ssimokawa sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0); 2026120660Ssimokawa sbp->fwb.end = sbp->fwb.start + 0xffff; 2027113584Ssimokawa /* pre-allocate xfer */ 2028113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 2029169130Ssimokawa fw_xferlist_add(&sbp->fwb.xferlist, M_SBP, 2030169130Ssimokawa /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB/2, 2031170374Ssimokawa fc, (void *)sbp, sbp_recv); 2032103285Sikob 2033170374Ssimokawa fw_bindadd(fc, &sbp->fwb); 2034170374Ssimokawa 2035113584Ssimokawa sbp->fd.post_busreset = sbp_post_busreset; 2036103285Sikob sbp->fd.post_explore = sbp_post_explore; 2037103285Sikob 2038170374Ssimokawa if (fc->status != -1) { 2039111199Ssimokawa s = splfw(); 2040122387Ssimokawa sbp_post_busreset((void *)sbp); 2041111199Ssimokawa sbp_post_explore((void *)sbp); 2042111199Ssimokawa splx(s); 2043111199Ssimokawa } 2044170374Ssimokawa SBP_LOCK(sbp); 2045122387Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 2046170374Ssimokawa SBP_UNLOCK(sbp); 2047111199Ssimokawa 2048103285Sikob return (0); 2049111615Ssimokawafail: 2050170374Ssimokawa SBP_UNLOCK(sbp); 2051111615Ssimokawa cam_sim_free(sbp->sim, /*free_devq*/TRUE); 2052111615Ssimokawa return (ENXIO); 2053103285Sikob} 2054103285Sikob 2055103285Sikobstatic int 2056110145Ssimokawasbp_logout_all(struct sbp_softc *sbp) 2057110145Ssimokawa{ 2058110145Ssimokawa struct sbp_target *target; 2059110145Ssimokawa struct sbp_dev *sdev; 2060110145Ssimokawa int i, j; 2061110145Ssimokawa 2062110145SsimokawaSBP_DEBUG(0) 2063110145Ssimokawa printf("sbp_logout_all\n"); 2064110145SsimokawaEND_DEBUG 2065110145Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) { 2066110145Ssimokawa target = &sbp->targets[i]; 2067110145Ssimokawa if (target->luns == NULL) 2068110145Ssimokawa continue; 2069110145Ssimokawa for (j = 0; j < target->num_lun; j++) { 2070121185Ssimokawa sdev = target->luns[j]; 2071121185Ssimokawa if (sdev == NULL) 2072121185Ssimokawa continue; 2073113584Ssimokawa callout_stop(&sdev->login_callout); 2074110336Ssimokawa if (sdev->status >= SBP_DEV_TOATTACH && 2075110336Ssimokawa sdev->status <= SBP_DEV_ATTACHED) 2076111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); 2077110145Ssimokawa } 2078110145Ssimokawa } 2079113584Ssimokawa 2080110145Ssimokawa return 0; 2081110145Ssimokawa} 2082110145Ssimokawa 2083110145Ssimokawastatic int 2084110145Ssimokawasbp_shutdown(device_t dev) 2085110145Ssimokawa{ 2086110145Ssimokawa struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 2087110145Ssimokawa 2088110145Ssimokawa sbp_logout_all(sbp); 2089110145Ssimokawa return (0); 2090110145Ssimokawa} 2091110145Ssimokawa 2092121185Ssimokawastatic void 2093121185Ssimokawasbp_free_sdev(struct sbp_dev *sdev) 2094121185Ssimokawa{ 2095121185Ssimokawa int i; 2096121185Ssimokawa 2097121185Ssimokawa if (sdev == NULL) 2098121185Ssimokawa return; 2099121185Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) 2100121185Ssimokawa bus_dmamap_destroy(sdev->target->sbp->dmat, 2101121185Ssimokawa sdev->ocb[i].dmamap); 2102121185Ssimokawa fwdma_free(sdev->target->sbp->fd.fc, &sdev->dma); 2103121185Ssimokawa free(sdev, M_SBP); 2104121185Ssimokawa} 2105121185Ssimokawa 2106121185Ssimokawastatic void 2107121185Ssimokawasbp_free_target(struct sbp_target *target) 2108121185Ssimokawa{ 2109121185Ssimokawa struct sbp_softc *sbp; 2110121185Ssimokawa struct fw_xfer *xfer, *next; 2111121185Ssimokawa int i; 2112121185Ssimokawa 2113121185Ssimokawa if (target->luns == NULL) 2114121185Ssimokawa return; 2115121185Ssimokawa callout_stop(&target->mgm_ocb_timeout); 2116121185Ssimokawa sbp = target->sbp; 2117121185Ssimokawa for (i = 0; i < target->num_lun; i++) 2118121185Ssimokawa sbp_free_sdev(target->luns[i]); 2119121185Ssimokawa 2120121185Ssimokawa for (xfer = STAILQ_FIRST(&target->xferlist); 2121121185Ssimokawa xfer != NULL; xfer = next) { 2122121185Ssimokawa next = STAILQ_NEXT(xfer, link); 2123121185Ssimokawa fw_xfer_free_buf(xfer); 2124121185Ssimokawa } 2125121185Ssimokawa STAILQ_INIT(&target->xferlist); 2126121185Ssimokawa free(target->luns, M_SBP); 2127121185Ssimokawa target->num_lun = 0;; 2128121185Ssimokawa target->luns = NULL; 2129121185Ssimokawa target->fwdev = NULL; 2130121185Ssimokawa} 2131121185Ssimokawa 2132110145Ssimokawastatic int 2133103285Sikobsbp_detach(device_t dev) 2134103285Sikob{ 2135103285Sikob struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 2136103285Sikob struct firewire_comm *fc = sbp->fd.fc; 2137121185Ssimokawa int i; 2138103285Sikob 2139103285SikobSBP_DEBUG(0) 2140103285Sikob printf("sbp_detach\n"); 2141103285SikobEND_DEBUG 2142113584Ssimokawa 2143103285Sikob for (i = 0; i < SBP_NUM_TARGETS; i ++) 2144110145Ssimokawa sbp_cam_detach_target(&sbp->targets[i]); 2145170374Ssimokawa 2146170374Ssimokawa SBP_LOCK(sbp); 2147120660Ssimokawa xpt_async(AC_LOST_DEVICE, sbp->path, NULL); 2148111615Ssimokawa xpt_free_path(sbp->path); 2149103285Sikob xpt_bus_deregister(cam_sim_path(sbp->sim)); 2150170378Sgallatin cam_sim_free(sbp->sim, /*free_devq*/ TRUE); 2151170374Ssimokawa SBP_UNLOCK(sbp); 2152110145Ssimokawa 2153110145Ssimokawa sbp_logout_all(sbp); 2154113584Ssimokawa 2155110145Ssimokawa /* XXX wait for logout completion */ 2156167086Sjhb pause("sbpdtc", hz/2); 2157110145Ssimokawa 2158121185Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) 2159121185Ssimokawa sbp_free_target(&sbp->targets[i]); 2160113584Ssimokawa 2161110145Ssimokawa fw_bindremove(fc, &sbp->fwb); 2162169130Ssimokawa fw_xferlist_remove(&sbp->fwb.xferlist); 2163113584Ssimokawa 2164103285Sikob bus_dma_tag_destroy(sbp->dmat); 2165170374Ssimokawa mtx_destroy(&sbp->mtx); 2166110145Ssimokawa 2167103285Sikob return (0); 2168103285Sikob} 2169103285Sikob 2170103285Sikobstatic void 2171121185Ssimokawasbp_cam_detach_sdev(struct sbp_dev *sdev) 2172121185Ssimokawa{ 2173121185Ssimokawa if (sdev == NULL) 2174121185Ssimokawa return; 2175121185Ssimokawa if (sdev->status == SBP_DEV_DEAD) 2176121185Ssimokawa return; 2177121185Ssimokawa if (sdev->status == SBP_DEV_RESET) 2178121185Ssimokawa return; 2179170374Ssimokawa sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE); 2180121185Ssimokawa if (sdev->path) { 2181170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2182121185Ssimokawa xpt_release_devq(sdev->path, 2183121185Ssimokawa sdev->freeze, TRUE); 2184121185Ssimokawa sdev->freeze = 0; 2185121185Ssimokawa xpt_async(AC_LOST_DEVICE, sdev->path, NULL); 2186121185Ssimokawa xpt_free_path(sdev->path); 2187121185Ssimokawa sdev->path = NULL; 2188170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2189121185Ssimokawa } 2190121185Ssimokawa} 2191121185Ssimokawa 2192121185Ssimokawastatic void 2193110145Ssimokawasbp_cam_detach_target(struct sbp_target *target) 2194103285Sikob{ 2195103285Sikob int i; 2196103285Sikob 2197103285Sikob if (target->luns != NULL) { 2198108529SsimokawaSBP_DEBUG(0) 2199103285Sikob printf("sbp_detach_target %d\n", target->target_id); 2200108529SsimokawaEND_DEBUG 2201111615Ssimokawa callout_stop(&target->scan_callout); 2202121185Ssimokawa for (i = 0; i < target->num_lun; i++) 2203121185Ssimokawa sbp_cam_detach_sdev(target->luns[i]); 2204103285Sikob } 2205103285Sikob} 2206103285Sikob 2207103285Sikobstatic void 2208114732Ssimokawasbp_target_reset(struct sbp_dev *sdev, int method) 2209114732Ssimokawa{ 2210114732Ssimokawa int i; 2211114732Ssimokawa struct sbp_target *target = sdev->target; 2212114732Ssimokawa struct sbp_dev *tsdev; 2213114732Ssimokawa 2214114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 2215121185Ssimokawa tsdev = target->luns[i]; 2216121185Ssimokawa if (tsdev == NULL) 2217121185Ssimokawa continue; 2218114732Ssimokawa if (tsdev->status == SBP_DEV_DEAD) 2219114732Ssimokawa continue; 2220114732Ssimokawa if (tsdev->status == SBP_DEV_RESET) 2221114732Ssimokawa continue; 2222170374Ssimokawa SBP_LOCK(target->sbp); 2223114732Ssimokawa xpt_freeze_devq(tsdev->path, 1); 2224114732Ssimokawa tsdev->freeze ++; 2225170374Ssimokawa SBP_UNLOCK(target->sbp); 2226114732Ssimokawa sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT); 2227114732Ssimokawa if (method == 2) 2228114732Ssimokawa tsdev->status = SBP_DEV_LOGIN; 2229114732Ssimokawa } 2230114732Ssimokawa switch(method) { 2231114732Ssimokawa case 1: 2232114732Ssimokawa printf("target reset\n"); 2233114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); 2234114732Ssimokawa break; 2235114732Ssimokawa case 2: 2236114732Ssimokawa printf("reset start\n"); 2237114732Ssimokawa sbp_reset_start(sdev); 2238114732Ssimokawa break; 2239114732Ssimokawa } 2240114732Ssimokawa 2241114732Ssimokawa} 2242114732Ssimokawa 2243114732Ssimokawastatic void 2244114732Ssimokawasbp_mgm_timeout(void *arg) 2245114732Ssimokawa{ 2246114732Ssimokawa struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2247114732Ssimokawa struct sbp_dev *sdev = ocb->sdev; 2248114732Ssimokawa struct sbp_target *target = sdev->target; 2249114732Ssimokawa 2250114732Ssimokawa sbp_show_sdev_info(sdev, 2); 2251120842Ssimokawa printf("request timeout(mgm orb:0x%08x) ... ", 2252129585Sdfr (uint32_t)ocb->bus_addr); 2253114732Ssimokawa target->mgm_ocb_cur = NULL; 2254114732Ssimokawa sbp_free_ocb(sdev, ocb); 2255114732Ssimokawa#if 0 2256114732Ssimokawa /* XXX */ 2257121185Ssimokawa printf("run next request\n"); 2258114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 2259114732Ssimokawa#endif 2260121185Ssimokawa#if 1 2261121185Ssimokawa printf("reset start\n"); 2262114732Ssimokawa sbp_reset_start(sdev); 2263114732Ssimokawa#endif 2264114732Ssimokawa} 2265114732Ssimokawa 2266114732Ssimokawastatic void 2267103285Sikobsbp_timeout(void *arg) 2268103285Sikob{ 2269103285Sikob struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2270103285Sikob struct sbp_dev *sdev = ocb->sdev; 2271103285Sikob 2272103285Sikob sbp_show_sdev_info(sdev, 2); 2273120842Ssimokawa printf("request timeout(cmd orb:0x%08x) ... ", 2274129585Sdfr (uint32_t)ocb->bus_addr); 2275103285Sikob 2276114732Ssimokawa sdev->timeout ++; 2277114732Ssimokawa switch(sdev->timeout) { 2278114732Ssimokawa case 1: 2279110336Ssimokawa printf("agent reset\n"); 2280170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2281114732Ssimokawa xpt_freeze_devq(sdev->path, 1); 2282114732Ssimokawa sdev->freeze ++; 2283170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2284114732Ssimokawa sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); 2285110336Ssimokawa sbp_agent_reset(sdev); 2286114732Ssimokawa break; 2287114732Ssimokawa case 2: 2288114732Ssimokawa case 3: 2289114732Ssimokawa sbp_target_reset(sdev, sdev->timeout - 1); 2290114732Ssimokawa break; 2291114732Ssimokawa#if 0 2292114732Ssimokawa default: 2293114732Ssimokawa /* XXX give up */ 2294114732Ssimokawa sbp_cam_detach_target(target); 2295114732Ssimokawa if (target->luns != NULL) 2296114732Ssimokawa free(target->luns, M_SBP); 2297114732Ssimokawa target->num_lun = 0;; 2298114732Ssimokawa target->luns = NULL; 2299114732Ssimokawa target->fwdev = NULL; 2300114732Ssimokawa#endif 2301110336Ssimokawa } 2302103285Sikob} 2303103285Sikob 2304103285Sikobstatic void 2305103285Sikobsbp_action1(struct cam_sim *sim, union ccb *ccb) 2306103285Sikob{ 2307103285Sikob 2308103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)sim->softc; 2309103285Sikob struct sbp_target *target = NULL; 2310103285Sikob struct sbp_dev *sdev = NULL; 2311103285Sikob 2312103285Sikob /* target:lun -> sdev mapping */ 2313103285Sikob if (sbp != NULL 2314103285Sikob && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD 2315103285Sikob && ccb->ccb_h.target_id < SBP_NUM_TARGETS) { 2316103285Sikob target = &sbp->targets[ccb->ccb_h.target_id]; 2317103285Sikob if (target->fwdev != NULL 2318103285Sikob && ccb->ccb_h.target_lun != CAM_LUN_WILDCARD 2319103285Sikob && ccb->ccb_h.target_lun < target->num_lun) { 2320121185Ssimokawa sdev = target->luns[ccb->ccb_h.target_lun]; 2321121185Ssimokawa if (sdev != NULL && sdev->status != SBP_DEV_ATTACHED && 2322103285Sikob sdev->status != SBP_DEV_PROBE) 2323103285Sikob sdev = NULL; 2324103285Sikob } 2325103285Sikob } 2326103285Sikob 2327103285SikobSBP_DEBUG(1) 2328103285Sikob if (sdev == NULL) 2329103285Sikob printf("invalid target %d lun %d\n", 2330103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2331103285SikobEND_DEBUG 2332103285Sikob 2333103285Sikob switch (ccb->ccb_h.func_code) { 2334103285Sikob case XPT_SCSI_IO: 2335103285Sikob case XPT_RESET_DEV: 2336103285Sikob case XPT_GET_TRAN_SETTINGS: 2337103285Sikob case XPT_SET_TRAN_SETTINGS: 2338103285Sikob case XPT_CALC_GEOMETRY: 2339103285Sikob if (sdev == NULL) { 2340103285SikobSBP_DEBUG(1) 2341103285Sikob printf("%s:%d:%d:func_code 0x%04x: " 2342103285Sikob "Invalid target (target needed)\n", 2343103285Sikob device_get_nameunit(sbp->fd.dev), 2344103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2345103285Sikob ccb->ccb_h.func_code); 2346103285SikobEND_DEBUG 2347103285Sikob 2348108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2349103285Sikob xpt_done(ccb); 2350103285Sikob return; 2351103285Sikob } 2352103285Sikob break; 2353103285Sikob case XPT_PATH_INQ: 2354103285Sikob case XPT_NOOP: 2355103285Sikob /* The opcodes sometimes aimed at a target (sc is valid), 2356103285Sikob * sometimes aimed at the SIM (sc is invalid and target is 2357103285Sikob * CAM_TARGET_WILDCARD) 2358103285Sikob */ 2359103285Sikob if (sbp == NULL && 2360103285Sikob ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 2361103285SikobSBP_DEBUG(0) 2362103285Sikob printf("%s:%d:%d func_code 0x%04x: " 2363103285Sikob "Invalid target (no wildcard)\n", 2364103285Sikob device_get_nameunit(sbp->fd.dev), 2365103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2366103285Sikob ccb->ccb_h.func_code); 2367103285SikobEND_DEBUG 2368108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2369103285Sikob xpt_done(ccb); 2370103285Sikob return; 2371103285Sikob } 2372103285Sikob break; 2373103285Sikob default: 2374103285Sikob /* XXX Hm, we should check the input parameters */ 2375103285Sikob break; 2376103285Sikob } 2377103285Sikob 2378103285Sikob switch (ccb->ccb_h.func_code) { 2379103285Sikob case XPT_SCSI_IO: 2380103285Sikob { 2381103285Sikob struct ccb_scsiio *csio; 2382103285Sikob struct sbp_ocb *ocb; 2383113584Ssimokawa int speed; 2384106506Ssimokawa void *cdb; 2385103285Sikob 2386103285Sikob csio = &ccb->csio; 2387170374Ssimokawa mtx_assert(sim->mtx, MA_OWNED); 2388103285Sikob 2389121185SsimokawaSBP_DEBUG(2) 2390103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 2391103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 2392103285Sikob ", flags: 0x%02x, " 2393103285Sikob "%db cmd/%db data/%db sense\n", 2394103285Sikob device_get_nameunit(sbp->fd.dev), 2395103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2396103285Sikob csio->cdb_io.cdb_bytes[0], 2397103285Sikob csio->cdb_io.cdb_bytes[1], 2398103285Sikob csio->cdb_io.cdb_bytes[2], 2399103285Sikob csio->cdb_io.cdb_bytes[3], 2400103285Sikob csio->cdb_io.cdb_bytes[4], 2401103285Sikob csio->cdb_io.cdb_bytes[5], 2402103285Sikob csio->cdb_io.cdb_bytes[6], 2403103285Sikob csio->cdb_io.cdb_bytes[7], 2404103285Sikob csio->cdb_io.cdb_bytes[8], 2405103285Sikob csio->cdb_io.cdb_bytes[9], 2406103285Sikob ccb->ccb_h.flags & CAM_DIR_MASK, 2407103285Sikob csio->cdb_len, csio->dxfer_len, 2408103285Sikob csio->sense_len); 2409103285SikobEND_DEBUG 2410103285Sikob if(sdev == NULL){ 2411103285Sikob ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2412103285Sikob xpt_done(ccb); 2413103285Sikob return; 2414103285Sikob } 2415103285Sikob#if 0 2416103285Sikob /* if we are in probe stage, pass only probe commands */ 2417103285Sikob if (sdev->status == SBP_DEV_PROBE) { 2418103285Sikob char *name; 2419103285Sikob name = xpt_path_periph(ccb->ccb_h.path)->periph_name; 2420103285Sikob printf("probe stage, periph name: %s\n", name); 2421103285Sikob if (strcmp(name, "probe") != 0) { 2422103285Sikob ccb->ccb_h.status = CAM_REQUEUE_REQ; 2423103285Sikob xpt_done(ccb); 2424103285Sikob return; 2425103285Sikob } 2426103285Sikob } 2427103285Sikob#endif 2428122528Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 2429122528Ssimokawa ccb->ccb_h.status = CAM_REQUEUE_REQ; 2430127468Ssimokawa if (sdev->freeze == 0) { 2431170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2432127468Ssimokawa xpt_freeze_devq(sdev->path, 1); 2433127468Ssimokawa sdev->freeze ++; 2434170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2435127468Ssimokawa } 2436122528Ssimokawa xpt_done(ccb); 2437103285Sikob return; 2438122528Ssimokawa } 2439113584Ssimokawa 2440103285Sikob ocb->flags = OCB_ACT_CMD; 2441103285Sikob ocb->sdev = sdev; 2442103285Sikob ocb->ccb = ccb; 2443103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 2444103285Sikob ocb->orb[0] = htonl(1 << 31); 2445103285Sikob ocb->orb[1] = 0; 2446103285Sikob ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS )<< 16) ); 2447113584Ssimokawa ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); 2448103285Sikob speed = min(target->fwdev->speed, max_speed); 2449103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) 2450103285Sikob | ORB_CMD_MAXP(speed + 7)); 2451103285Sikob if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN){ 2452103285Sikob ocb->orb[4] |= htonl(ORB_CMD_IN); 2453103285Sikob } 2454103285Sikob 2455103285Sikob if (csio->ccb_h.flags & CAM_SCATTER_VALID) 2456103285Sikob printf("sbp: CAM_SCATTER_VALID\n"); 2457103285Sikob if (csio->ccb_h.flags & CAM_DATA_PHYS) 2458103285Sikob printf("sbp: CAM_DATA_PHYS\n"); 2459103285Sikob 2460106506Ssimokawa if (csio->ccb_h.flags & CAM_CDB_POINTER) 2461106506Ssimokawa cdb = (void *)csio->cdb_io.cdb_ptr; 2462106506Ssimokawa else 2463106506Ssimokawa cdb = (void *)&csio->cdb_io.cdb_bytes; 2464120660Ssimokawa bcopy(cdb, (void *)&ocb->orb[5], csio->cdb_len); 2465103285Sikob/* 2466103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3])); 2467103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); 2468103285Sikob*/ 2469103285Sikob if (ccb->csio.dxfer_len > 0) { 2470113584Ssimokawa int s, error; 2471103285Sikob 2472103285Sikob s = splsoftvm(); 2473113584Ssimokawa error = bus_dmamap_load(/*dma tag*/sbp->dmat, 2474103285Sikob /*dma map*/ocb->dmamap, 2475103285Sikob ccb->csio.data_ptr, 2476103285Sikob ccb->csio.dxfer_len, 2477103285Sikob sbp_execute_ocb, 2478103285Sikob ocb, 2479103285Sikob /*flags*/0); 2480103285Sikob splx(s); 2481113584Ssimokawa if (error) 2482113584Ssimokawa printf("sbp: bus_dmamap_load error %d\n", error); 2483103285Sikob } else 2484103285Sikob sbp_execute_ocb(ocb, NULL, 0, 0); 2485103285Sikob break; 2486103285Sikob } 2487103285Sikob case XPT_CALC_GEOMETRY: 2488103285Sikob { 2489103285Sikob struct ccb_calc_geometry *ccg; 2490127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 501100 2491129585Sdfr uint32_t size_mb; 2492129585Sdfr uint32_t secs_per_cylinder; 2493116429Ssimokawa int extended = 1; 2494116429Ssimokawa#endif 2495116351Snjl 2496103285Sikob ccg = &ccb->ccg; 2497103285Sikob if (ccg->block_size == 0) { 2498103285Sikob printf("sbp_action1: block_size is 0.\n"); 2499103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2500103285Sikob xpt_done(ccb); 2501103285Sikob break; 2502103285Sikob } 2503103285SikobSBP_DEBUG(1) 2504103285Sikob printf("%s:%d:%d:%d:XPT_CALC_GEOMETRY: " 2505127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2506127468Ssimokawa "Volume size = %d\n", 2507127468Ssimokawa#else 2508114540Sjake "Volume size = %jd\n", 2509114927Ssimokawa#endif 2510114927Ssimokawa device_get_nameunit(sbp->fd.dev), 2511114927Ssimokawa cam_sim_path(sbp->sim), 2512103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2513127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 2514114927Ssimokawa (uintmax_t) 2515114927Ssimokawa#endif 2516114927Ssimokawa ccg->volume_size); 2517103285SikobEND_DEBUG 2518103285Sikob 2519127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 501100 2520116429Ssimokawa size_mb = ccg->volume_size 2521116429Ssimokawa / ((1024L * 1024L) / ccg->block_size); 2522116429Ssimokawa 2523116429Ssimokawa if (size_mb > 1024 && extended) { 2524116429Ssimokawa ccg->heads = 255; 2525116429Ssimokawa ccg->secs_per_track = 63; 2526116429Ssimokawa } else { 2527116429Ssimokawa ccg->heads = 64; 2528116429Ssimokawa ccg->secs_per_track = 32; 2529116429Ssimokawa } 2530116429Ssimokawa secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2531116429Ssimokawa ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2532116429Ssimokawa ccb->ccb_h.status = CAM_REQ_CMP; 2533116429Ssimokawa#else 2534116351Snjl cam_calc_geometry(ccg, /*extended*/1); 2535116429Ssimokawa#endif 2536103285Sikob xpt_done(ccb); 2537103285Sikob break; 2538103285Sikob } 2539103285Sikob case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2540103285Sikob { 2541103285Sikob 2542103285SikobSBP_DEBUG(1) 2543103285Sikob printf("%s:%d:XPT_RESET_BUS: \n", 2544103285Sikob device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); 2545103285SikobEND_DEBUG 2546103285Sikob 2547103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2548103285Sikob xpt_done(ccb); 2549103285Sikob break; 2550103285Sikob } 2551103285Sikob case XPT_PATH_INQ: /* Path routing inquiry */ 2552103285Sikob { 2553103285Sikob struct ccb_pathinq *cpi = &ccb->cpi; 2554103285Sikob 2555103285SikobSBP_DEBUG(1) 2556103285Sikob printf("%s:%d:%d XPT_PATH_INQ:.\n", 2557103285Sikob device_get_nameunit(sbp->fd.dev), 2558103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2559103285SikobEND_DEBUG 2560103285Sikob cpi->version_num = 1; /* XXX??? */ 2561111615Ssimokawa cpi->hba_inquiry = PI_TAG_ABLE; 2562103285Sikob cpi->target_sprt = 0; 2563118105Snjl cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE; 2564103285Sikob cpi->hba_eng_cnt = 0; 2565103285Sikob cpi->max_target = SBP_NUM_TARGETS - 1; 2566103285Sikob cpi->max_lun = SBP_NUM_LUNS - 1; 2567103285Sikob cpi->initiator_id = SBP_INITIATOR; 2568103285Sikob cpi->bus_id = sim->bus_id; 2569103285Sikob cpi->base_transfer_speed = 400 * 1000 / 8; 2570103285Sikob strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2571103285Sikob strncpy(cpi->hba_vid, "SBP", HBA_IDLEN); 2572103285Sikob strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); 2573103285Sikob cpi->unit_number = sim->unit_number; 2574163816Smjacob cpi->transport = XPORT_SPI; /* XX should have a FireWire */ 2575163816Smjacob cpi->transport_version = 2; 2576163816Smjacob cpi->protocol = PROTO_SCSI; 2577163816Smjacob cpi->protocol_version = SCSI_REV_2; 2578103285Sikob 2579103285Sikob cpi->ccb_h.status = CAM_REQ_CMP; 2580103285Sikob xpt_done(ccb); 2581103285Sikob break; 2582103285Sikob } 2583103285Sikob case XPT_GET_TRAN_SETTINGS: 2584103285Sikob { 2585103285Sikob struct ccb_trans_settings *cts = &ccb->cts; 2586163816Smjacob struct ccb_trans_settings_scsi *scsi = 2587163816Smjacob &cts->proto_specific.scsi; 2588163816Smjacob struct ccb_trans_settings_spi *spi = 2589163816Smjacob &cts->xport_specific.spi; 2590163816Smjacob 2591163816Smjacob cts->protocol = PROTO_SCSI; 2592163816Smjacob cts->protocol_version = SCSI_REV_2; 2593163816Smjacob cts->transport = XPORT_SPI; /* should have a FireWire */ 2594163816Smjacob cts->transport_version = 2; 2595163816Smjacob spi->valid = CTS_SPI_VALID_DISC; 2596163816Smjacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2597163816Smjacob scsi->valid = CTS_SCSI_VALID_TQ; 2598163816Smjacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2599103285SikobSBP_DEBUG(1) 2600103285Sikob printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", 2601103285Sikob device_get_nameunit(sbp->fd.dev), 2602103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2603103285SikobEND_DEBUG 2604103285Sikob cts->ccb_h.status = CAM_REQ_CMP; 2605103285Sikob xpt_done(ccb); 2606103285Sikob break; 2607103285Sikob } 2608103285Sikob case XPT_ABORT: 2609103285Sikob ccb->ccb_h.status = CAM_UA_ABORT; 2610103285Sikob xpt_done(ccb); 2611103285Sikob break; 2612111615Ssimokawa case XPT_SET_TRAN_SETTINGS: 2613111615Ssimokawa /* XXX */ 2614103285Sikob default: 2615103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2616103285Sikob xpt_done(ccb); 2617103285Sikob break; 2618103285Sikob } 2619103285Sikob return; 2620103285Sikob} 2621103285Sikob 2622103285Sikobstatic void 2623103285Sikobsbp_action(struct cam_sim *sim, union ccb *ccb) 2624103285Sikob{ 2625103285Sikob int s; 2626103285Sikob 2627103285Sikob s = splfw(); 2628103285Sikob sbp_action1(sim, ccb); 2629103285Sikob splx(s); 2630103285Sikob} 2631103285Sikob 2632103285Sikobstatic void 2633103285Sikobsbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error) 2634103285Sikob{ 2635103285Sikob int i; 2636103285Sikob struct sbp_ocb *ocb; 2637103285Sikob struct sbp_ocb *prev; 2638105633Ssimokawa bus_dma_segment_t *s; 2639103285Sikob 2640103285Sikob if (error) 2641103285Sikob printf("sbp_execute_ocb: error=%d\n", error); 2642103285Sikob 2643103285Sikob ocb = (struct sbp_ocb *)arg; 2644113584Ssimokawa 2645121185SsimokawaSBP_DEBUG(2) 2646113584Ssimokawa printf("sbp_execute_ocb: seg %d", seg); 2647113584Ssimokawa for (i = 0; i < seg; i++) 2648127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2649127468Ssimokawa printf(", %x:%d", segments[i].ds_addr, segments[i].ds_len); 2650127468Ssimokawa#else 2651113972Ssimokawa printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr, 2652113972Ssimokawa (uintmax_t)segments[i].ds_len); 2653113584Ssimokawa#endif 2654113584Ssimokawa printf("\n"); 2655113584SsimokawaEND_DEBUG 2656113584Ssimokawa 2657103285Sikob if (seg == 1) { 2658103285Sikob /* direct pointer */ 2659113474Ssimokawa s = &segments[0]; 2660113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2661113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2662113474Ssimokawa ocb->orb[3] = htonl(s->ds_addr); 2663113474Ssimokawa ocb->orb[4] |= htonl(s->ds_len); 2664103285Sikob } else if(seg > 1) { 2665103285Sikob /* page table */ 2666103285Sikob for (i = 0; i < seg; i++) { 2667105633Ssimokawa s = &segments[i]; 2668108877SsimokawaSBP_DEBUG(0) 2669108877Ssimokawa /* XXX LSI Logic "< 16 byte" bug might be hit */ 2670105633Ssimokawa if (s->ds_len < 16) 2671105633Ssimokawa printf("sbp_execute_ocb: warning, " 2672127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2673127468Ssimokawa "segment length(%d) is less than 16." 2674127468Ssimokawa#else 2675106543Ssimokawa "segment length(%zd) is less than 16." 2676108877Ssimokawa#endif 2677105633Ssimokawa "(seg=%d/%d)\n", s->ds_len, i+1, seg); 2678108877SsimokawaEND_DEBUG 2679113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2680113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2681105633Ssimokawa ocb->ind_ptr[i].hi = htonl(s->ds_len << 16); 2682105633Ssimokawa ocb->ind_ptr[i].lo = htonl(s->ds_addr); 2683103285Sikob } 2684103285Sikob ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg); 2685103285Sikob } 2686103285Sikob 2687113584Ssimokawa if (seg > 0) 2688113584Ssimokawa bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap, 2689113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2690113584Ssimokawa BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 2691103285Sikob prev = sbp_enqueue_ocb(ocb->sdev, ocb); 2692113584Ssimokawa fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE); 2693127468Ssimokawa if (use_doorbell) { 2694127468Ssimokawa if (prev == NULL) { 2695127468Ssimokawa if (ocb->sdev->last_ocb != NULL) 2696127468Ssimokawa sbp_doorbell(ocb->sdev); 2697127468Ssimokawa else 2698127468Ssimokawa sbp_orb_pointer(ocb->sdev, ocb); 2699127468Ssimokawa } 2700127468Ssimokawa } else { 2701127468Ssimokawa if (prev == NULL || (ocb->sdev->flags & ORB_LINK_DEAD) != 0) { 2702127468Ssimokawa ocb->sdev->flags &= ~ORB_LINK_DEAD; 2703127468Ssimokawa sbp_orb_pointer(ocb->sdev, ocb); 2704127468Ssimokawa } 2705120842Ssimokawa } 2706103285Sikob} 2707103285Sikob 2708103285Sikobstatic void 2709103285Sikobsbp_poll(struct cam_sim *sim) 2710103285Sikob{ 2711120847Ssimokawa struct sbp_softc *sbp; 2712120847Ssimokawa struct firewire_comm *fc; 2713120847Ssimokawa 2714120847Ssimokawa sbp = (struct sbp_softc *)sim->softc; 2715120847Ssimokawa fc = sbp->fd.fc; 2716120847Ssimokawa 2717120847Ssimokawa fc->poll(fc, 0, -1); 2718120847Ssimokawa 2719103285Sikob return; 2720103285Sikob} 2721120847Ssimokawa 2722103285Sikobstatic struct sbp_ocb * 2723111615Ssimokawasbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status) 2724103285Sikob{ 2725103285Sikob struct sbp_ocb *ocb; 2726103285Sikob struct sbp_ocb *next; 2727103285Sikob int s = splfw(), order = 0; 2728103285Sikob int flags; 2729103285Sikob 2730103285SikobSBP_DEBUG(1) 2731121185Ssimokawa sbp_show_sdev_info(sdev, 2); 2732127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2733127468Ssimokawa printf("%s: 0x%08lx src %d\n", 2734127468Ssimokawa#else 2735121185Ssimokawa printf("%s: 0x%08x src %d\n", 2736108712Ssimokawa#endif 2737127468Ssimokawa __func__, ntohl(sbp_status->orb_lo), sbp_status->src); 2738103285SikobEND_DEBUG 2739170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2740121185Ssimokawa for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) { 2741121185Ssimokawa next = STAILQ_NEXT(ocb, ocb); 2742121185Ssimokawa flags = ocb->flags; 2743111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 2744103285Sikob /* found */ 2745111819Ssimokawa STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); 2746103285Sikob if (ocb->ccb != NULL) 2747103285Sikob untimeout(sbp_timeout, (caddr_t)ocb, 2748103285Sikob ocb->ccb->ccb_h.timeout_ch); 2749113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2750113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, 2751113584Ssimokawa ocb->dmamap, 2752113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2753113584Ssimokawa BUS_DMASYNC_POSTREAD : 2754113584Ssimokawa BUS_DMASYNC_POSTWRITE); 2755113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, 2756113584Ssimokawa ocb->dmamap); 2757103285Sikob } 2758127468Ssimokawa if (!use_doorbell) { 2759127468Ssimokawa if (sbp_status->src == SRC_NO_NEXT) { 2760127468Ssimokawa if (next != NULL) 2761127468Ssimokawa sbp_orb_pointer(sdev, next); 2762127468Ssimokawa else if (order > 0) { 2763127468Ssimokawa /* 2764127468Ssimokawa * Unordered execution 2765127468Ssimokawa * We need to send pointer for 2766127468Ssimokawa * next ORB 2767127468Ssimokawa */ 2768127468Ssimokawa sdev->flags |= ORB_LINK_DEAD; 2769127468Ssimokawa } 2770120842Ssimokawa } 2771127468Ssimokawa } else { 2772127468Ssimokawa /* 2773127468Ssimokawa * XXX this is not correct for unordered 2774127468Ssimokawa * execution. 2775127468Ssimokawa */ 2776127468Ssimokawa if (sdev->last_ocb != NULL) 2777127468Ssimokawa sbp_free_ocb(sdev, sdev->last_ocb); 2778127468Ssimokawa sdev->last_ocb = ocb; 2779127468Ssimokawa if (next != NULL && 2780127468Ssimokawa sbp_status->src == SRC_NO_NEXT) 2781127468Ssimokawa sbp_doorbell(sdev); 2782120842Ssimokawa } 2783103285Sikob break; 2784111819Ssimokawa } else 2785111819Ssimokawa order ++; 2786103285Sikob } 2787170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2788103285Sikob splx(s); 2789103285SikobSBP_DEBUG(0) 2790103285Sikob if (ocb && order > 0) { 2791103285Sikob sbp_show_sdev_info(sdev, 2); 2792103285Sikob printf("unordered execution order:%d\n", order); 2793103285Sikob } 2794103285SikobEND_DEBUG 2795103285Sikob return (ocb); 2796103285Sikob} 2797103285Sikob 2798103285Sikobstatic struct sbp_ocb * 2799103285Sikobsbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2800103285Sikob{ 2801103285Sikob int s = splfw(); 2802127468Ssimokawa struct sbp_ocb *prev, *prev2; 2803103285Sikob 2804121185SsimokawaSBP_DEBUG(1) 2805103285Sikob sbp_show_sdev_info(sdev, 2); 2806127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2807127468Ssimokawa printf("%s: 0x%08x\n", __func__, ocb->bus_addr); 2808108712Ssimokawa#else 2809127468Ssimokawa printf("%s: 0x%08jx\n", __func__, (uintmax_t)ocb->bus_addr); 2810108712Ssimokawa#endif 2811103285SikobEND_DEBUG 2812127468Ssimokawa prev2 = prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb); 2813103285Sikob STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb); 2814103285Sikob 2815103285Sikob if (ocb->ccb != NULL) 2816103285Sikob ocb->ccb->ccb_h.timeout_ch = timeout(sbp_timeout, (caddr_t)ocb, 2817103285Sikob (ocb->ccb->ccb_h.timeout * hz) / 1000); 2818103285Sikob 2819127468Ssimokawa if (use_doorbell && prev == NULL) 2820127468Ssimokawa prev2 = sdev->last_ocb; 2821127468Ssimokawa 2822127468Ssimokawa if (prev2 != NULL) { 2823121185SsimokawaSBP_DEBUG(2) 2824127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2825127468Ssimokawa printf("linking chain 0x%x -> 0x%x\n", 2826127468Ssimokawa prev2->bus_addr, ocb->bus_addr); 2827127468Ssimokawa#else 2828120842Ssimokawa printf("linking chain 0x%jx -> 0x%jx\n", 2829127468Ssimokawa (uintmax_t)prev2->bus_addr, (uintmax_t)ocb->bus_addr); 2830108712Ssimokawa#endif 2831103285SikobEND_DEBUG 2832170724Ssimokawa /* 2833170724Ssimokawa * Suppress compiler optimization so that orb[1] must be written first. 2834170724Ssimokawa * XXX We may need an explicit memory barrier for other architectures 2835170724Ssimokawa * other than i386/amd64. 2836170724Ssimokawa */ 2837170724Ssimokawa *(volatile uint32_t *)&prev2->orb[1] = htonl(ocb->bus_addr); 2838170724Ssimokawa *(volatile uint32_t *)&prev2->orb[0] = 0; 2839103285Sikob } 2840103285Sikob splx(s); 2841103285Sikob 2842103285Sikob return prev; 2843103285Sikob} 2844103285Sikob 2845103285Sikobstatic struct sbp_ocb * 2846113584Ssimokawasbp_get_ocb(struct sbp_dev *sdev) 2847103285Sikob{ 2848103285Sikob struct sbp_ocb *ocb; 2849103285Sikob int s = splfw(); 2850170374Ssimokawa 2851170374Ssimokawa mtx_assert(&sdev->target->sbp->mtx, MA_OWNED); 2852113584Ssimokawa ocb = STAILQ_FIRST(&sdev->free_ocbs); 2853103285Sikob if (ocb == NULL) { 2854127468Ssimokawa sdev->flags |= ORB_SHORTAGE; 2855103285Sikob printf("ocb shortage!!!\n"); 2856134868Ssimokawa splx(s); 2857103285Sikob return NULL; 2858103285Sikob } 2859113584Ssimokawa STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb); 2860103285Sikob splx(s); 2861103285Sikob ocb->ccb = NULL; 2862103285Sikob return (ocb); 2863103285Sikob} 2864103285Sikob 2865103285Sikobstatic void 2866113584Ssimokawasbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2867103285Sikob{ 2868103285Sikob ocb->flags = 0; 2869103285Sikob ocb->ccb = NULL; 2870170374Ssimokawa 2871170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2872113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); 2873127468Ssimokawa if ((sdev->flags & ORB_SHORTAGE) != 0) { 2874127468Ssimokawa int count; 2875127468Ssimokawa 2876127468Ssimokawa sdev->flags &= ~ORB_SHORTAGE; 2877127468Ssimokawa count = sdev->freeze; 2878127468Ssimokawa sdev->freeze = 0; 2879127468Ssimokawa xpt_release_devq(sdev->path, count, TRUE); 2880127468Ssimokawa } 2881170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2882103285Sikob} 2883103285Sikob 2884103285Sikobstatic void 2885103285Sikobsbp_abort_ocb(struct sbp_ocb *ocb, int status) 2886103285Sikob{ 2887103285Sikob struct sbp_dev *sdev; 2888103285Sikob 2889103285Sikob sdev = ocb->sdev; 2890113584SsimokawaSBP_DEBUG(0) 2891103285Sikob sbp_show_sdev_info(sdev, 2); 2892127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 2893127468Ssimokawa printf("sbp_abort_ocb 0x%x\n", ocb->bus_addr); 2894127468Ssimokawa#else 2895113972Ssimokawa printf("sbp_abort_ocb 0x%jx\n", (uintmax_t)ocb->bus_addr); 2896111819Ssimokawa#endif 2897113584SsimokawaEND_DEBUG 2898113584SsimokawaSBP_DEBUG(1) 2899105792Ssimokawa if (ocb->ccb != NULL) 2900105792Ssimokawa sbp_print_scsi_cmd(ocb); 2901103285SikobEND_DEBUG 2902113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2903113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap, 2904113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2905113584Ssimokawa BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 2906113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap); 2907113584Ssimokawa } 2908111819Ssimokawa if (ocb->ccb != NULL) { 2909110336Ssimokawa untimeout(sbp_timeout, (caddr_t)ocb, 2910110336Ssimokawa ocb->ccb->ccb_h.timeout_ch); 2911103285Sikob ocb->ccb->ccb_h.status = status; 2912170374Ssimokawa SBP_LOCK(sdev->target->sbp); 2913103285Sikob xpt_done(ocb->ccb); 2914170374Ssimokawa SBP_UNLOCK(sdev->target->sbp); 2915103285Sikob } 2916113584Ssimokawa sbp_free_ocb(sdev, ocb); 2917103285Sikob} 2918103285Sikob 2919103285Sikobstatic void 2920103285Sikobsbp_abort_all_ocbs(struct sbp_dev *sdev, int status) 2921103285Sikob{ 2922103285Sikob int s; 2923105792Ssimokawa struct sbp_ocb *ocb, *next; 2924105792Ssimokawa STAILQ_HEAD(, sbp_ocb) temp; 2925103285Sikob 2926103285Sikob s = splfw(); 2927105792Ssimokawa 2928105792Ssimokawa bcopy(&sdev->ocbs, &temp, sizeof(temp)); 2929105792Ssimokawa STAILQ_INIT(&sdev->ocbs); 2930105792Ssimokawa for (ocb = STAILQ_FIRST(&temp); ocb != NULL; ocb = next) { 2931105792Ssimokawa next = STAILQ_NEXT(ocb, ocb); 2932103285Sikob sbp_abort_ocb(ocb, status); 2933103285Sikob } 2934127468Ssimokawa if (sdev->last_ocb != NULL) { 2935127468Ssimokawa sbp_free_ocb(sdev, sdev->last_ocb); 2936127468Ssimokawa sdev->last_ocb = NULL; 2937127468Ssimokawa } 2938105792Ssimokawa 2939103285Sikob splx(s); 2940103285Sikob} 2941103285Sikob 2942103285Sikobstatic devclass_t sbp_devclass; 2943103285Sikob 2944103285Sikobstatic device_method_t sbp_methods[] = { 2945103285Sikob /* device interface */ 2946103285Sikob DEVMETHOD(device_identify, sbp_identify), 2947103285Sikob DEVMETHOD(device_probe, sbp_probe), 2948103285Sikob DEVMETHOD(device_attach, sbp_attach), 2949103285Sikob DEVMETHOD(device_detach, sbp_detach), 2950110145Ssimokawa DEVMETHOD(device_shutdown, sbp_shutdown), 2951103285Sikob 2952103285Sikob { 0, 0 } 2953103285Sikob}; 2954103285Sikob 2955103285Sikobstatic driver_t sbp_driver = { 2956103285Sikob "sbp", 2957103285Sikob sbp_methods, 2958103285Sikob sizeof(struct sbp_softc), 2959103285Sikob}; 2960127468Ssimokawa#ifdef __DragonFly__ 2961127468SsimokawaDECLARE_DUMMY_MODULE(sbp); 2962127468Ssimokawa#endif 2963103285SikobDRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0); 2964103285SikobMODULE_VERSION(sbp, 1); 2965103285SikobMODULE_DEPEND(sbp, firewire, 1, 1, 1); 2966103285SikobMODULE_DEPEND(sbp, cam, 1, 1, 1); 2967