sbp.c revision 116429
1103285Sikob/* 2113584Ssimokawa * Copyright (c) 2003 Hidetosh Shimokawa 3113584Ssimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetosh 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 116429 2003-06-16 03:44:36Z simokawa $ 35103285Sikob * 36103285Sikob */ 37103285Sikob 38103285Sikob#include <sys/param.h> 39103285Sikob#include <sys/systm.h> 40103285Sikob#include <sys/module.h> 41103285Sikob#include <sys/bus.h> 42103285Sikob#include <sys/mbuf.h> 43103285Sikob#include <sys/sysctl.h> 44103285Sikob#include <machine/bus.h> 45103285Sikob#include <sys/malloc.h> 46103285Sikob 47112136Ssimokawa#if __FreeBSD_version < 500106 48112136Ssimokawa#include <sys/devicestat.h> /* for struct devstat */ 49112136Ssimokawa#endif 50103285Sikob 51103285Sikob#include <cam/cam.h> 52103285Sikob#include <cam/cam_ccb.h> 53103285Sikob#include <cam/cam_sim.h> 54103285Sikob#include <cam/cam_xpt_sim.h> 55103285Sikob#include <cam/cam_debug.h> 56103285Sikob#include <cam/cam_periph.h> 57103285Sikob 58103285Sikob#include <cam/scsi/scsi_all.h> 59103285Sikob#include <cam/scsi/scsi_message.h> 60103285Sikob#include <cam/scsi/scsi_da.h> 61103285Sikob 62103285Sikob#include <sys/kernel.h> 63103285Sikob 64103285Sikob#include <dev/firewire/firewire.h> 65103285Sikob#include <dev/firewire/firewirereg.h> 66113584Ssimokawa#include <dev/firewire/fwdma.h> 67103285Sikob#include <dev/firewire/iec13213.h> 68103285Sikob 69103285Sikob#define ccb_sdev_ptr spriv_ptr0 70103285Sikob#define ccb_sbp_ptr spriv_ptr1 71103285Sikob 72111615Ssimokawa#define SBP_NUM_TARGETS 8 /* MAX 64 */ 73103285Sikob#define SBP_NUM_LUNS 8 /* limited by CAM_SCSI2_MAXLUN in cam_xpt.c */ 74113584Ssimokawa#define SBP_DMA_SIZE PAGE_SIZE 75113584Ssimokawa#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res) 76113584Ssimokawa#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb)) 77103285Sikob#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) 78113584Ssimokawa 79103285Sikob#define SBP_INITIATOR 7 80111615Ssimokawa 81111615Ssimokawa#define LOGIN_DELAY 2 82111615Ssimokawa 83111615Ssimokawa/* 84111615Ssimokawa * STATUS FIFO addressing 85111615Ssimokawa * bit 86111615Ssimokawa * ----------------------- 87111615Ssimokawa * 0- 1( 2): 0 (alingment) 88111615Ssimokawa * 2- 7( 6): target 89111615Ssimokawa * 8-15( 8): lun 90111615Ssimokawa * 16-23( 8): unit 91111615Ssimokawa * 24-31( 8): reserved 92111615Ssimokawa * 32-47(16): SBP_BIND_HI 93111615Ssimokawa * 48-64(16): bus_id, node_id 94111615Ssimokawa */ 95103285Sikob#define SBP_BIND_HI 0x1 96111615Ssimokawa#define SBP_DEV2ADDR(u, t, l) \ 97103285Sikob ((((u) & 0xff) << 16) | (((l) & 0xff) << 8) | (((t) & 0x3f) << 2)) 98103285Sikob#define SBP_ADDR2TRG(a) (((a) >> 2) & 0x3f) 99103285Sikob#define SBP_ADDR2LUN(a) (((a) >> 8) & 0xff) 100103285Sikob 101103285Sikob#define ORB_NOTIFY (1 << 31) 102103285Sikob#define ORB_FMT_STD (0 << 29) 103103285Sikob#define ORB_FMT_VED (2 << 29) 104103285Sikob#define ORB_FMT_NOP (3 << 29) 105103285Sikob#define ORB_FMT_MSK (3 << 29) 106103285Sikob#define ORB_EXV (1 << 28) 107103285Sikob/* */ 108103285Sikob#define ORB_CMD_IN (1 << 27) 109103285Sikob/* */ 110103285Sikob#define ORB_CMD_SPD(x) ((x) << 24) 111103285Sikob#define ORB_CMD_MAXP(x) ((x) << 20) 112103285Sikob#define ORB_RCN_TMO(x) ((x) << 20) 113103285Sikob#define ORB_CMD_PTBL (1 << 19) 114103285Sikob#define ORB_CMD_PSZ(x) ((x) << 16) 115103285Sikob 116103285Sikob#define ORB_FUN_LGI (0 << 16) 117103285Sikob#define ORB_FUN_QLG (1 << 16) 118103285Sikob#define ORB_FUN_RCN (3 << 16) 119103285Sikob#define ORB_FUN_LGO (7 << 16) 120103285Sikob#define ORB_FUN_ATA (0xb << 16) 121103285Sikob#define ORB_FUN_ATS (0xc << 16) 122103285Sikob#define ORB_FUN_LUR (0xe << 16) 123103285Sikob#define ORB_FUN_RST (0xf << 16) 124103285Sikob#define ORB_FUN_MSK (0xf << 16) 125111615Ssimokawa#define ORB_FUN_RUNQUEUE 0xffff 126103285Sikob 127103285Sikobstatic char *orb_fun_name[] = { 128103285Sikob /* 0 */ "LOGIN", 129103285Sikob /* 1 */ "QUERY LOGINS", 130103285Sikob /* 2 */ "Reserved", 131103285Sikob /* 3 */ "RECONNECT", 132103285Sikob /* 4 */ "SET PASSWORD", 133103285Sikob /* 5 */ "Reserved", 134103285Sikob /* 6 */ "Reserved", 135103285Sikob /* 7 */ "LOGOUT", 136103285Sikob /* 8 */ "Reserved", 137103285Sikob /* 9 */ "Reserved", 138103285Sikob /* A */ "Reserved", 139103285Sikob /* B */ "ABORT TASK", 140103285Sikob /* C */ "ABORT TASK SET", 141103285Sikob /* D */ "Reserved", 142103285Sikob /* E */ "LOGICAL UNIT RESET", 143103285Sikob /* F */ "TARGET RESET" 144103285Sikob}; 145103285Sikob 146103285Sikob#define ORB_RES_CMPL 0 147103285Sikob#define ORB_RES_FAIL 1 148103285Sikob#define ORB_RES_ILLE 2 149103285Sikob#define ORB_RES_VEND 3 150103285Sikob 151111203Ssimokawastatic int debug = 0; 152103285Sikobstatic int auto_login = 1; 153103285Sikobstatic int max_speed = 2; 154111199Ssimokawastatic int sbp_cold = 1; 155103285Sikob 156103285SikobSYSCTL_DECL(_hw_firewire); 157103285SikobSYSCTL_NODE(_hw_firewire, OID_AUTO, sbp, CTLFLAG_RD, 0, "SBP-II Subsystem"); 158103285SikobSYSCTL_INT(_debug, OID_AUTO, sbp_debug, CTLFLAG_RW, &debug, 0, 159103285Sikob "SBP debug flag"); 160103285SikobSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RW, &auto_login, 0, 161103285Sikob "SBP perform login automatically"); 162103285SikobSYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0, 163103285Sikob "SBP transfer max speed"); 164103285Sikob 165103285Sikob#define SBP_DEBUG(x) if (debug > x) { 166103285Sikob#define END_DEBUG } 167103285Sikob 168103285Sikob#define NEED_RESPONSE 0 169103285Sikob 170103285Sikobstruct ind_ptr { 171103285Sikob u_int32_t hi,lo; 172103285Sikob}; 173113584Ssimokawa#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE) 174113584Ssimokawa#ifdef __sparc64__ /* iommu */ 175113584Ssimokawa#define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX) 176113584Ssimokawa#else 177113584Ssimokawa#define SBP_IND_MAX howmany(MAXPHYS, PAGE_SIZE) 178113584Ssimokawa#endif 179103285Sikobstruct sbp_ocb { 180103285Sikob STAILQ_ENTRY(sbp_ocb) ocb; 181103285Sikob union ccb *ccb; 182113584Ssimokawa bus_addr_t bus_addr; 183103285Sikob volatile u_int32_t orb[8]; 184113584Ssimokawa#define IND_PTR_OFFSET (8*sizeof(u_int32_t)) 185103285Sikob volatile struct ind_ptr ind_ptr[SBP_IND_MAX]; 186103285Sikob struct sbp_dev *sdev; 187113584Ssimokawa int flags; /* XXX should be removed */ 188103285Sikob bus_dmamap_t dmamap; 189103285Sikob}; 190113584Ssimokawa 191103285Sikob#define OCB_ACT_MGM 0 192103285Sikob#define OCB_ACT_CMD 1 193113584Ssimokawa#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo)) 194103285Sikob 195113584Ssimokawa#define SBP_RECV_LEN (16 + 32) /* header + payload */ 196103285Sikob 197103285Sikobstruct sbp_login_res{ 198103285Sikob u_int16_t len; 199103285Sikob u_int16_t id; 200103285Sikob u_int16_t res0; 201103285Sikob u_int16_t cmd_hi; 202103285Sikob u_int32_t cmd_lo; 203103285Sikob u_int16_t res1; 204103285Sikob u_int16_t recon_hold; 205103285Sikob}; 206103285Sikobstruct sbp_status{ 207113584Ssimokawa#if BYTE_ORDER == BIG_ENDIAN 208113584Ssimokawa u_int8_t src:2, 209113584Ssimokawa resp:2, 210113584Ssimokawa dead:1, 211113584Ssimokawa len:3; 212113584Ssimokawa#else 213103285Sikob u_int8_t len:3, 214103285Sikob dead:1, 215103285Sikob resp:2, 216103285Sikob src:2; 217113584Ssimokawa#endif 218113584Ssimokawa u_int8_t status; 219103285Sikob u_int16_t orb_hi; 220103285Sikob u_int32_t orb_lo; 221103285Sikob u_int32_t data[6]; 222103285Sikob}; 223103285Sikobstruct sbp_cmd_status{ 224103285Sikob#define SBP_SFMT_CURR 0 225103285Sikob#define SBP_SFMT_DEFER 1 226113584Ssimokawa#if BYTE_ORDER == BIG_ENDIAN 227113584Ssimokawa u_int8_t sfmt:2, 228113584Ssimokawa status:6; 229113584Ssimokawa u_int8_t valid:1, 230113584Ssimokawa mark:1, 231113584Ssimokawa eom:1, 232113584Ssimokawa ill_len:1, 233113584Ssimokawa s_key:4; 234113584Ssimokawa#else 235103285Sikob u_int8_t status:6, 236103285Sikob sfmt:2; 237103285Sikob u_int8_t s_key:4, 238103285Sikob ill_len:1, 239103285Sikob eom:1, 240103285Sikob mark:1, 241103285Sikob valid:1; 242113584Ssimokawa#endif 243103285Sikob u_int8_t s_code; 244103285Sikob u_int8_t s_qlfr; 245103285Sikob u_int32_t info; 246103285Sikob u_int32_t cdb; 247113584Ssimokawa 248113584Ssimokawa#if BYTE_ORDER == BIG_ENDIAN 249113584Ssimokawa u_int32_t s_keydep:24, 250113584Ssimokawa fru:8; 251113584Ssimokawa#else 252103285Sikob u_int32_t fru:8, 253103285Sikob s_keydep:24; 254113584Ssimokawa#endif 255103285Sikob u_int32_t vend[2]; 256113584Ssimokawa 257103285Sikob}; 258103285Sikob 259103285Sikobstruct sbp_dev{ 260103285Sikob#define SBP_DEV_RESET 0 /* accept login */ 261114732Ssimokawa#define SBP_DEV_LOGIN 1 /* to login */ 262110336Ssimokawa#if 0 263103285Sikob#define SBP_DEV_RECONN 2 /* to reconnect */ 264110336Ssimokawa#endif 265103285Sikob#define SBP_DEV_TOATTACH 3 /* to attach */ 266103285Sikob#define SBP_DEV_PROBE 4 /* scan lun */ 267103285Sikob#define SBP_DEV_ATTACHED 5 /* in operation */ 268103285Sikob#define SBP_DEV_DEAD 6 /* unavailable unit */ 269103285Sikob#define SBP_DEV_RETRY 7 /* unavailable unit */ 270110336Ssimokawa u_int8_t status:4, 271114732Ssimokawa timeout:4; 272108503Ssimokawa u_int8_t type; 273108503Ssimokawa u_int16_t lun_id; 274111615Ssimokawa int freeze; 275103285Sikob struct cam_path *path; 276103285Sikob struct sbp_target *target; 277113584Ssimokawa struct fwdma_alloc dma; 278113584Ssimokawa struct sbp_login_res *login; 279111615Ssimokawa struct callout login_callout; 280113584Ssimokawa struct sbp_ocb *ocb; 281103285Sikob STAILQ_HEAD(, sbp_ocb) ocbs; 282113584Ssimokawa STAILQ_HEAD(, sbp_ocb) free_ocbs; 283103285Sikob char vendor[32]; 284103285Sikob char product[32]; 285103285Sikob char revision[10]; 286103285Sikob}; 287103285Sikob 288103285Sikobstruct sbp_target { 289103285Sikob int target_id; 290103285Sikob int num_lun; 291103285Sikob struct sbp_dev *luns; 292103285Sikob struct sbp_softc *sbp; 293103285Sikob struct fw_device *fwdev; 294103285Sikob u_int32_t mgm_hi, mgm_lo; 295111615Ssimokawa struct sbp_ocb *mgm_ocb_cur; 296111615Ssimokawa STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; 297111615Ssimokawa struct callout mgm_ocb_timeout; 298111615Ssimokawa#define SCAN_DELAY 2 299111615Ssimokawa struct callout scan_callout; 300113584Ssimokawa STAILQ_HEAD(, fw_xfer) xferlist; 301113584Ssimokawa int n_xfer; 302103285Sikob}; 303103285Sikob 304103285Sikobstruct sbp_softc { 305103285Sikob struct firewire_dev_comm fd; 306103285Sikob struct cam_sim *sim; 307111615Ssimokawa struct cam_path *path; 308103285Sikob struct sbp_target targets[SBP_NUM_TARGETS]; 309103285Sikob struct fw_bind fwb; 310103285Sikob bus_dma_tag_t dmat; 311111615Ssimokawa#define SBP_RESOURCE_SHORTAGE 0x10 312111615Ssimokawa unsigned char flags; 313103285Sikob}; 314103285Sikobstatic void sbp_post_explore __P((void *)); 315103285Sikobstatic void sbp_recv __P((struct fw_xfer *)); 316114732Ssimokawastatic void sbp_mgm_callback __P((struct fw_xfer *)); 317103285Sikobstatic void sbp_cmd_callback __P((struct fw_xfer *)); 318103285Sikobstatic void sbp_orb_pointer __P((struct sbp_dev *, struct sbp_ocb *)); 319103285Sikobstatic void sbp_execute_ocb __P((void *, bus_dma_segment_t *, int, int)); 320113584Ssimokawastatic void sbp_free_ocb __P((struct sbp_dev *, struct sbp_ocb *)); 321103285Sikobstatic void sbp_abort_ocb __P((struct sbp_ocb *, int)); 322103285Sikobstatic void sbp_abort_all_ocbs __P((struct sbp_dev *, int)); 323103285Sikobstatic struct fw_xfer * sbp_write_cmd __P((struct sbp_dev *, int, int)); 324113584Ssimokawastatic struct sbp_ocb * sbp_get_ocb __P((struct sbp_dev *)); 325103285Sikobstatic struct sbp_ocb * sbp_enqueue_ocb __P((struct sbp_dev *, struct sbp_ocb *)); 326111615Ssimokawastatic struct sbp_ocb * sbp_dequeue_ocb __P((struct sbp_dev *, struct sbp_status *)); 327110145Ssimokawastatic void sbp_cam_detach_target __P((struct sbp_target *)); 328114732Ssimokawastatic void sbp_mgm_timeout __P((void *arg)); 329103285Sikobstatic void sbp_timeout __P((void *arg)); 330111615Ssimokawastatic void sbp_mgm_orb __P((struct sbp_dev *, int, struct sbp_ocb *)); 331111615Ssimokawa#define sbp_login(sdev) \ 332111615Ssimokawa callout_reset(&(sdev)->login_callout, LOGIN_DELAY * hz, \ 333111615Ssimokawa sbp_login_callout, (void *)(sdev)); 334103285Sikob 335108281SsimokawaMALLOC_DEFINE(M_SBP, "sbp", "SBP-II/FireWire"); 336103285Sikob 337103285Sikob/* cam related functions */ 338103285Sikobstatic void sbp_action(struct cam_sim *sim, union ccb *ccb); 339103285Sikobstatic void sbp_poll(struct cam_sim *sim); 340111615Ssimokawastatic void sbp_cam_scan_lun(struct cam_periph *, union ccb *); 341111615Ssimokawastatic void sbp_cam_scan_target(void *arg); 342103285Sikob 343103285Sikobstatic char *orb_status0[] = { 344103285Sikob /* 0 */ "No additional information to report", 345103285Sikob /* 1 */ "Request type not supported", 346103285Sikob /* 2 */ "Speed not supported", 347103285Sikob /* 3 */ "Page size not supported", 348103285Sikob /* 4 */ "Access denied", 349103285Sikob /* 5 */ "Logical unit not supported", 350103285Sikob /* 6 */ "Maximum payload too small", 351103285Sikob /* 7 */ "Reserved for future standardization", 352103285Sikob /* 8 */ "Resources unavailable", 353103285Sikob /* 9 */ "Function rejected", 354103285Sikob /* A */ "Login ID not recognized", 355103285Sikob /* B */ "Dummy ORB completed", 356103285Sikob /* C */ "Request aborted", 357103285Sikob /* FF */ "Unspecified error" 358103285Sikob#define MAX_ORB_STATUS0 0xd 359103285Sikob}; 360103285Sikob 361103285Sikobstatic char *orb_status1_object[] = { 362103285Sikob /* 0 */ "Operation request block (ORB)", 363103285Sikob /* 1 */ "Data buffer", 364103285Sikob /* 2 */ "Page table", 365103285Sikob /* 3 */ "Unable to specify" 366103285Sikob}; 367103285Sikob 368103285Sikobstatic char *orb_status1_serial_bus_error[] = { 369103285Sikob /* 0 */ "Missing acknowledge", 370103285Sikob /* 1 */ "Reserved; not to be used", 371103285Sikob /* 2 */ "Time-out error", 372103285Sikob /* 3 */ "Reserved; not to be used", 373103285Sikob /* 4 */ "Busy retry limit exceeded(X)", 374103285Sikob /* 5 */ "Busy retry limit exceeded(A)", 375103285Sikob /* 6 */ "Busy retry limit exceeded(B)", 376103285Sikob /* 7 */ "Reserved for future standardization", 377103285Sikob /* 8 */ "Reserved for future standardization", 378103285Sikob /* 9 */ "Reserved for future standardization", 379103285Sikob /* A */ "Reserved for future standardization", 380103285Sikob /* B */ "Tardy retry limit exceeded", 381103285Sikob /* C */ "Conflict error", 382103285Sikob /* D */ "Data error", 383103285Sikob /* E */ "Type error", 384103285Sikob /* F */ "Address error" 385103285Sikob}; 386103285Sikob 387103285Sikobstatic void 388103285Sikobsbp_identify(driver_t *driver, device_t parent) 389103285Sikob{ 390103285Sikob device_t child; 391103285SikobSBP_DEBUG(0) 392103285Sikob printf("sbp_identify\n"); 393103285SikobEND_DEBUG 394103285Sikob 395103285Sikob child = BUS_ADD_CHILD(parent, 0, "sbp", device_get_unit(parent)); 396103285Sikob} 397103285Sikob 398103285Sikob/* 399103285Sikob * sbp_probe() 400103285Sikob */ 401103285Sikobstatic int 402103285Sikobsbp_probe(device_t dev) 403103285Sikob{ 404103285Sikob device_t pa; 405103285Sikob 406103285SikobSBP_DEBUG(0) 407103285Sikob printf("sbp_probe\n"); 408103285SikobEND_DEBUG 409103285Sikob 410103285Sikob pa = device_get_parent(dev); 411103285Sikob if(device_get_unit(dev) != device_get_unit(pa)){ 412103285Sikob return(ENXIO); 413103285Sikob } 414103285Sikob 415103285Sikob device_set_desc(dev, "SBP2/SCSI over firewire"); 416111615Ssimokawa 417111615Ssimokawa if (bootverbose) 418111615Ssimokawa debug = bootverbose; 419103285Sikob return (0); 420103285Sikob} 421103285Sikob 422103285Sikobstatic void 423103285Sikobsbp_show_sdev_info(struct sbp_dev *sdev, int new) 424103285Sikob{ 425103285Sikob struct fw_device *fwdev; 426103285Sikob 427103285Sikob printf("%s:%d:%d ", 428103285Sikob device_get_nameunit(sdev->target->sbp->fd.dev), 429103285Sikob sdev->target->target_id, 430103285Sikob sdev->lun_id 431103285Sikob ); 432103285Sikob if (new == 2) { 433103285Sikob return; 434103285Sikob } 435103285Sikob fwdev = sdev->target->fwdev; 436103285Sikob printf("ordered:%d type:%d EUI:%08x%08x node:%d " 437103285Sikob "speed:%d maxrec:%d", 438108503Ssimokawa (sdev->type & 0x40) >> 6, 439108503Ssimokawa (sdev->type & 0x1f), 440103285Sikob fwdev->eui.hi, 441103285Sikob fwdev->eui.lo, 442103285Sikob fwdev->dst, 443103285Sikob fwdev->speed, 444103285Sikob fwdev->maxrec 445103285Sikob ); 446103285Sikob if (new) 447103285Sikob printf(" new!\n"); 448103285Sikob else 449103285Sikob printf("\n"); 450103285Sikob sbp_show_sdev_info(sdev, 2); 451103285Sikob printf("'%s' '%s' '%s'\n", sdev->vendor, sdev->product, sdev->revision); 452103285Sikob} 453103285Sikob 454110184Ssimokawastatic struct { 455110184Ssimokawa int bus; 456110184Ssimokawa int target; 457110184Ssimokawa struct fw_eui64 eui; 458110184Ssimokawa} wired[] = { 459110184Ssimokawa /* Bus Target EUI64 */ 460110184Ssimokawa#if 0 461110184Ssimokawa {0, 2, {0x00018ea0, 0x01fd0154}}, /* Logitec HDD */ 462110184Ssimokawa {0, 0, {0x00018ea6, 0x00100682}}, /* Logitec DVD */ 463110184Ssimokawa {0, 1, {0x00d03200, 0xa412006a}}, /* Yano HDD */ 464110184Ssimokawa#endif 465110184Ssimokawa {-1, -1, {0,0}} 466110184Ssimokawa}; 467110184Ssimokawa 468110184Ssimokawastatic int 469110184Ssimokawasbp_new_target(struct sbp_softc *sbp, struct fw_device *fwdev) 470110184Ssimokawa{ 471110184Ssimokawa int bus, i, target=-1; 472110184Ssimokawa char w[SBP_NUM_TARGETS]; 473110184Ssimokawa 474110184Ssimokawa bzero(w, sizeof(w)); 475110184Ssimokawa bus = device_get_unit(sbp->fd.dev); 476110184Ssimokawa 477110184Ssimokawa /* XXX wired-down configuration should be gotten from 478110184Ssimokawa tunable or device hint */ 479110184Ssimokawa for (i = 0; wired[i].bus >= 0; i ++) { 480110184Ssimokawa if (wired[i].bus == bus) { 481110184Ssimokawa w[wired[i].target] = 1; 482110184Ssimokawa if (wired[i].eui.hi == fwdev->eui.hi && 483110184Ssimokawa wired[i].eui.lo == fwdev->eui.lo) 484110184Ssimokawa target = wired[i].target; 485110184Ssimokawa } 486110184Ssimokawa } 487110184Ssimokawa if (target >= 0) { 488110184Ssimokawa if(target < SBP_NUM_TARGETS && 489110184Ssimokawa sbp->targets[target].fwdev == NULL) 490110184Ssimokawa return(target); 491110184Ssimokawa device_printf(sbp->fd.dev, 492110184Ssimokawa "target %d is not free for %08x:%08x\n", 493110184Ssimokawa target, fwdev->eui.hi, fwdev->eui.lo); 494110184Ssimokawa target = -1; 495110184Ssimokawa } 496110184Ssimokawa /* non-wired target */ 497110184Ssimokawa for (i = 0; i < SBP_NUM_TARGETS; i ++) 498110184Ssimokawa if (sbp->targets[i].fwdev == NULL && w[i] == 0) { 499110184Ssimokawa target = i; 500110184Ssimokawa break; 501110184Ssimokawa } 502110184Ssimokawa 503110184Ssimokawa return target; 504110184Ssimokawa} 505110184Ssimokawa 506103285Sikobstatic struct sbp_target * 507103285Sikobsbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev) 508103285Sikob{ 509108503Ssimokawa int i, maxlun, lun; 510103285Sikob struct sbp_target *target; 511103285Sikob struct sbp_dev *sdev; 512108503Ssimokawa struct crom_context cc; 513108503Ssimokawa struct csrreg *reg; 514103285Sikob 515103285SikobSBP_DEBUG(1) 516103285Sikob printf("sbp_alloc_target\n"); 517103285SikobEND_DEBUG 518110184Ssimokawa i = sbp_new_target(sbp, fwdev); 519110184Ssimokawa if (i < 0) { 520110184Ssimokawa device_printf(sbp->fd.dev, "increase SBP_NUM_TARGETS!\n"); 521103285Sikob return NULL; 522103285Sikob } 523103285Sikob /* new target */ 524103285Sikob target = &sbp->targets[i]; 525103285Sikob target->sbp = sbp; 526103285Sikob target->fwdev = fwdev; 527103285Sikob target->target_id = i; 528111704Ssimokawa /* XXX we may want to reload mgm port after each bus reset */ 529114069Ssimokawa /* XXX there might be multiple management agents */ 530114069Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 531114069Ssimokawa reg = crom_search_key(&cc, CROM_MGM); 532114069Ssimokawa if (reg == NULL || reg->val == 0) { 533103285Sikob printf("NULL management address\n"); 534103285Sikob target->fwdev = NULL; 535103285Sikob return NULL; 536103285Sikob } 537103285Sikob target->mgm_hi = 0xffff; 538114069Ssimokawa target->mgm_lo = 0xf0000000 | (reg->val << 2); 539111615Ssimokawa target->mgm_ocb_cur = NULL; 540111704SsimokawaSBP_DEBUG(1) 541111704Ssimokawa printf("target:%d mgm_port: %x\n", i, target->mgm_lo); 542111704SsimokawaEND_DEBUG 543113584Ssimokawa STAILQ_INIT(&target->xferlist); 544113584Ssimokawa target->n_xfer = 0; 545111615Ssimokawa STAILQ_INIT(&target->mgm_ocb_queue); 546111615Ssimokawa CALLOUT_INIT(&target->mgm_ocb_timeout); 547111615Ssimokawa CALLOUT_INIT(&target->scan_callout); 548111615Ssimokawa 549103285Sikob /* XXX num_lun may be changed. realloc luns? */ 550108503Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 551108503Ssimokawa /* XXX shoud parse appropriate unit directories only */ 552108503Ssimokawa maxlun = -1; 553108503Ssimokawa while (cc.depth >= 0) { 554108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 555108503Ssimokawa if (reg == NULL) 556108503Ssimokawa break; 557110839Ssimokawa lun = reg->val & 0xffff; 558108642SsimokawaSBP_DEBUG(0) 559108642Ssimokawa printf("target %d lun %d found\n", target->target_id, lun); 560108642SsimokawaEND_DEBUG 561108503Ssimokawa if (maxlun < lun) 562108503Ssimokawa maxlun = lun; 563108503Ssimokawa crom_next(&cc); 564108503Ssimokawa } 565110839Ssimokawa if (maxlun < 0) 566110839Ssimokawa printf("no lun found!\n"); 567110839Ssimokawa if (maxlun >= SBP_NUM_LUNS) 568110839Ssimokawa maxlun = SBP_NUM_LUNS; 569108503Ssimokawa target->num_lun = maxlun + 1; 570103285Sikob target->luns = (struct sbp_dev *) malloc( 571103285Sikob sizeof(struct sbp_dev) * target->num_lun, 572103285Sikob M_SBP, M_NOWAIT | M_ZERO); 573103285Sikob for (i = 0; i < target->num_lun; i++) { 574103285Sikob sdev = &target->luns[i]; 575103285Sikob sdev->lun_id = i; 576103285Sikob sdev->target = target; 577103285Sikob STAILQ_INIT(&sdev->ocbs); 578111615Ssimokawa CALLOUT_INIT(&sdev->login_callout); 579108503Ssimokawa sdev->status = SBP_DEV_DEAD; 580103285Sikob } 581108503Ssimokawa crom_init_context(&cc, target->fwdev->csrrom); 582108503Ssimokawa while (cc.depth >= 0) { 583108503Ssimokawa reg = crom_search_key(&cc, CROM_LUN); 584108503Ssimokawa if (reg == NULL) 585108503Ssimokawa break; 586110839Ssimokawa lun = reg->val & 0xffff; 587110839Ssimokawa if (lun >= SBP_NUM_LUNS) { 588110839Ssimokawa printf("too large lun %d\n", lun); 589110839Ssimokawa continue; 590110839Ssimokawa } 591113584Ssimokawa sdev = &target->luns[lun]; 592113584Ssimokawa sdev->status = SBP_DEV_RESET; 593113584Ssimokawa sdev->type = (reg->val & 0xf0000) >> 16; 594113584Ssimokawa 595113584Ssimokawa fwdma_malloc(sbp->fd.fc, 596113584Ssimokawa /* alignment */ sizeof(u_int32_t), 597113584Ssimokawa SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT); 598113584Ssimokawa if (sdev->dma.v_addr == NULL) { 599113584Ssimokawa printf("%s: dma space allocation failed\n", 600113584Ssimokawa __FUNCTION__); 601113584Ssimokawa return (NULL); 602113584Ssimokawa } 603113584Ssimokawa sdev->login = (struct sbp_login_res *) sdev->dma.v_addr; 604113584Ssimokawa sdev->ocb = (struct sbp_ocb *) 605113584Ssimokawa ((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE); 606113584Ssimokawa bzero((char *)sdev->ocb, 607113584Ssimokawa sizeof (struct sbp_ocb) * SBP_QUEUE_LEN); 608113584Ssimokawa 609113584Ssimokawa STAILQ_INIT(&sdev->free_ocbs); 610113584Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) { 611113584Ssimokawa struct sbp_ocb *ocb; 612113584Ssimokawa ocb = &sdev->ocb[i]; 613113584Ssimokawa ocb->bus_addr = sdev->dma.bus_addr 614113584Ssimokawa + SBP_LOGIN_SIZE 615113584Ssimokawa + sizeof(struct sbp_ocb) * i 616113584Ssimokawa + offsetof(struct sbp_ocb, orb[0]); 617113584Ssimokawa if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) { 618113584Ssimokawa printf("sbp_attach: cannot create dmamap\n"); 619113584Ssimokawa return (NULL); 620113584Ssimokawa } 621113584Ssimokawa sbp_free_ocb(sdev, ocb); 622113584Ssimokawa } 623108503Ssimokawa crom_next(&cc); 624103285Sikob } 625114069Ssimokawa return target; 626103285Sikob} 627103285Sikob 628103285Sikobstatic void 629103285Sikobsbp_probe_lun(struct sbp_dev *sdev) 630103285Sikob{ 631103285Sikob struct fw_device *fwdev; 632114069Ssimokawa struct crom_context c, *cc = &c; 633114069Ssimokawa struct csrreg *reg; 634103285Sikob 635103285Sikob bzero(sdev->vendor, sizeof(sdev->vendor)); 636103285Sikob bzero(sdev->product, sizeof(sdev->product)); 637114069Ssimokawa 638114069Ssimokawa fwdev = sdev->target->fwdev; 639114069Ssimokawa crom_init_context(cc, fwdev->csrrom); 640114069Ssimokawa /* get vendor string */ 641114069Ssimokawa crom_search_key(cc, CSRKEY_VENDOR); 642114069Ssimokawa crom_next(cc); 643114069Ssimokawa crom_parse_text(cc, sdev->vendor, sizeof(sdev->vendor)); 644114223Ssimokawa /* skip to the unit directory for SBP-2 */ 645114260Ssimokawa while ((reg = crom_search_key(cc, CSRKEY_VER)) != NULL) { 646114223Ssimokawa if (reg->val == CSRVAL_T10SBP2) 647114223Ssimokawa break; 648114260Ssimokawa crom_next(cc); 649114260Ssimokawa } 650114069Ssimokawa /* get firmware revision */ 651114069Ssimokawa reg = crom_search_key(cc, CSRKEY_FIRM_VER); 652114069Ssimokawa if (reg != NULL) 653114069Ssimokawa snprintf(sdev->revision, sizeof(sdev->revision), 654114069Ssimokawa "%06x", reg->val); 655114069Ssimokawa /* get product string */ 656114069Ssimokawa crom_search_key(cc, CSRKEY_MODEL); 657114069Ssimokawa crom_next(cc); 658114069Ssimokawa crom_parse_text(cc, sdev->product, sizeof(sdev->product)); 659103285Sikob} 660111615Ssimokawa 661103285Sikobstatic void 662111615Ssimokawasbp_login_callout(void *arg) 663103285Sikob{ 664111615Ssimokawa struct sbp_dev *sdev = (struct sbp_dev *)arg; 665111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL); 666111615Ssimokawa} 667111615Ssimokawa 668114069Ssimokawa#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ 669114069Ssimokawa && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) 670111615Ssimokawa 671111615Ssimokawastatic void 672111615Ssimokawasbp_probe_target(void *arg) 673111615Ssimokawa{ 674111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 675103285Sikob struct sbp_softc *sbp; 676103285Sikob struct sbp_dev *sdev; 677103285Sikob struct firewire_comm *fc; 678111615Ssimokawa int i, alive; 679103285Sikob 680111615Ssimokawa alive = SBP_FWDEV_ALIVE(target->fwdev); 681103285SikobSBP_DEBUG(1) 682103285Sikob printf("sbp_probe_target %d\n", target->target_id); 683103285Sikob if (!alive) 684103285Sikob printf("not alive\n"); 685103285SikobEND_DEBUG 686103285Sikob 687103285Sikob sbp = target->sbp; 688103285Sikob fc = target->sbp->fd.fc; 689111615Ssimokawa /* XXX untimeout mgm_ocb and dequeue */ 690103285Sikob for (i=0; i < target->num_lun; i++) { 691103285Sikob sdev = &target->luns[i]; 692103285Sikob if (alive && (sdev->status != SBP_DEV_DEAD)) { 693103285Sikob if (sdev->path != NULL) { 694103285Sikob xpt_freeze_devq(sdev->path, 1); 695111615Ssimokawa sdev->freeze ++; 696103285Sikob } 697111615Ssimokawa sbp_probe_lun(sdev); 698111615SsimokawaSBP_DEBUG(0) 699111615Ssimokawa sbp_show_sdev_info(sdev, 700111615Ssimokawa (sdev->status == SBP_DEV_RESET)); 701111615SsimokawaEND_DEBUG 702111615Ssimokawa 703111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 704103285Sikob switch (sdev->status) { 705110336Ssimokawa case SBP_DEV_RESET: 706103285Sikob /* new or revived target */ 707113584Ssimokawa if (auto_login) 708111615Ssimokawa sbp_login(sdev); 709103285Sikob break; 710111615Ssimokawa case SBP_DEV_TOATTACH: 711111615Ssimokawa case SBP_DEV_PROBE: 712111615Ssimokawa case SBP_DEV_ATTACHED: 713110336Ssimokawa case SBP_DEV_RETRY: 714110336Ssimokawa default: 715111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); 716110336Ssimokawa break; 717103285Sikob } 718103285Sikob } else { 719103285Sikob switch (sdev->status) { 720103285Sikob case SBP_DEV_ATTACHED: 721103285SikobSBP_DEBUG(0) 722103285Sikob /* the device has gone */ 723103285Sikob sbp_show_sdev_info(sdev, 2); 724103285Sikob printf("lost target\n"); 725103285SikobEND_DEBUG 726111615Ssimokawa if (sdev->path) { 727103285Sikob xpt_freeze_devq(sdev->path, 1); 728111615Ssimokawa sdev->freeze ++; 729111615Ssimokawa } 730103285Sikob sdev->status = SBP_DEV_RETRY; 731111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 732103285Sikob break; 733103285Sikob case SBP_DEV_PROBE: 734103285Sikob case SBP_DEV_TOATTACH: 735103285Sikob sdev->status = SBP_DEV_RESET; 736103285Sikob break; 737103285Sikob case SBP_DEV_RETRY: 738103285Sikob case SBP_DEV_RESET: 739103285Sikob case SBP_DEV_DEAD: 740103285Sikob break; 741103285Sikob } 742103285Sikob } 743103285Sikob } 744103285Sikob} 745103285Sikob 746103285Sikobstatic void 747113584Ssimokawasbp_post_busreset(void *arg) 748113584Ssimokawa{ 749113584Ssimokawa struct sbp_softc *sbp; 750113584Ssimokawa 751113584Ssimokawa sbp = (struct sbp_softc *)arg; 752113584SsimokawaSBP_DEBUG(0) 753113584Ssimokawa printf("sbp_post_busreset\n"); 754113584SsimokawaEND_DEBUG 755113584Ssimokawa} 756113584Ssimokawa 757113584Ssimokawastatic void 758103285Sikobsbp_post_explore(void *arg) 759103285Sikob{ 760103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)arg; 761103285Sikob struct sbp_target *target; 762103285Sikob struct fw_device *fwdev; 763103285Sikob int i, alive; 764103285Sikob 765111199SsimokawaSBP_DEBUG(0) 766111199Ssimokawa printf("sbp_post_explore (sbp_cold=%d)\n", sbp_cold); 767103285SikobEND_DEBUG 768111615Ssimokawa#if 0 /* 769111615Ssimokawa * XXX don't let CAM the bus rest. CAM tries to do something with 770111615Ssimokawa * freezed (DEV_RETRY) devices 771111615Ssimokawa */ 772111615Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 773103285Sikob#endif 774111199Ssimokawa if (sbp_cold > 0) 775111199Ssimokawa sbp_cold --; 776111615Ssimokawa 777103285Sikob /* Gabage Collection */ 778103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 779103285Sikob target = &sbp->targets[i]; 780110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) 781110193Ssimokawa if (target->fwdev == NULL || target->fwdev == fwdev) 782110193Ssimokawa break; 783103285Sikob if(fwdev == NULL){ 784103285Sikob /* device has removed in lower driver */ 785110145Ssimokawa sbp_cam_detach_target(target); 786110145Ssimokawa if (target->luns != NULL) 787110145Ssimokawa free(target->luns, M_SBP); 788110145Ssimokawa target->num_lun = 0;; 789110145Ssimokawa target->luns = NULL; 790110145Ssimokawa target->fwdev = NULL; 791103285Sikob } 792103285Sikob } 793103285Sikob /* traverse device list */ 794110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) { 795103285SikobSBP_DEBUG(0) 796103285Sikob printf("sbp_post_explore: EUI:%08x%08x ", 797103285Sikob fwdev->eui.hi, fwdev->eui.lo); 798114069Ssimokawa if (fwdev->status != FWDEVATTACHED) 799103285Sikob printf("not attached, state=%d.\n", fwdev->status); 800114069Ssimokawa else 801114069Ssimokawa printf("attached\n"); 802103285SikobEND_DEBUG 803111615Ssimokawa alive = SBP_FWDEV_ALIVE(fwdev); 804103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 805103285Sikob target = &sbp->targets[i]; 806103285Sikob if(target->fwdev == fwdev ) { 807103285Sikob /* known target */ 808103285Sikob break; 809103285Sikob } 810103285Sikob } 811103285Sikob if(i == SBP_NUM_TARGETS){ 812103285Sikob if (alive) { 813103285Sikob /* new target */ 814103285Sikob target = sbp_alloc_target(sbp, fwdev); 815103285Sikob if (target == NULL) 816103285Sikob continue; 817103285Sikob } else { 818103285Sikob continue; 819103285Sikob } 820103285Sikob } 821111615Ssimokawa sbp_probe_target((void *)target); 822103285Sikob } 823103285Sikob} 824103285Sikob 825103285Sikob#if NEED_RESPONSE 826103285Sikobstatic void 827103285Sikobsbp_loginres_callback(struct fw_xfer *xfer){ 828113584Ssimokawa int s; 829103285Sikob struct sbp_dev *sdev; 830103285Sikob sdev = (struct sbp_dev *)xfer->sc; 831113584SsimokawaSBP_DEBUG(1) 832103285Sikob sbp_show_sdev_info(sdev, 2); 833103285Sikob printf("sbp_loginres_callback\n"); 834103285SikobEND_DEBUG 835113584Ssimokawa /* recycle */ 836113584Ssimokawa s = splfw(); 837113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link); 838113584Ssimokawa splx(s); 839103285Sikob return; 840103285Sikob} 841103285Sikob#endif 842103285Sikob 843113584Ssimokawastatic __inline void 844113584Ssimokawasbp_xfer_free(struct fw_xfer *xfer) 845113584Ssimokawa{ 846113584Ssimokawa struct sbp_dev *sdev; 847113584Ssimokawa int s; 848113584Ssimokawa 849113584Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 850113584Ssimokawa fw_xfer_unload(xfer); 851113584Ssimokawa s = splfw(); 852113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); 853113584Ssimokawa splx(s); 854113584Ssimokawa} 855113584Ssimokawa 856103285Sikobstatic void 857114732Ssimokawasbp_reset_start_callback(struct fw_xfer *xfer) 858103285Sikob{ 859114732Ssimokawa struct sbp_dev *tsdev, *sdev = (struct sbp_dev *)xfer->sc; 860114732Ssimokawa struct sbp_target *target = sdev->target; 861114732Ssimokawa int i; 862114732Ssimokawa 863114732Ssimokawa if (xfer->resp != 0) { 864114732Ssimokawa sbp_show_sdev_info(sdev, 2); 865114732Ssimokawa printf("sbp_reset_start failed: resp=%d\n", xfer->resp); 866114732Ssimokawa } 867114732Ssimokawa 868114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 869114732Ssimokawa tsdev = &target->luns[i]; 870114732Ssimokawa if (tsdev->status == SBP_DEV_LOGIN) 871114732Ssimokawa sbp_login(sdev); 872114732Ssimokawa } 873114732Ssimokawa} 874114732Ssimokawa 875114732Ssimokawastatic void 876114732Ssimokawasbp_reset_start(struct sbp_dev *sdev) 877114732Ssimokawa{ 878114732Ssimokawa struct fw_xfer *xfer; 879114732Ssimokawa struct fw_pkt *fp; 880114732Ssimokawa 881114732SsimokawaSBP_DEBUG(0) 882114732Ssimokawa sbp_show_sdev_info(sdev, 2); 883114732Ssimokawa printf("sbp_reset_start\n"); 884114732SsimokawaEND_DEBUG 885114732Ssimokawa 886114732Ssimokawa xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 887114732Ssimokawa xfer->act.hand = sbp_reset_start_callback; 888114732Ssimokawa fp = (struct fw_pkt *)xfer->send.buf; 889114732Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 890114732Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 891114732Ssimokawa fp->mode.wreqq.data = htonl(0xf); 892114732Ssimokawa fw_asyreq(xfer->fc, -1, xfer); 893114732Ssimokawa} 894114732Ssimokawa 895114732Ssimokawastatic void 896114732Ssimokawasbp_mgm_callback(struct fw_xfer *xfer) 897114732Ssimokawa{ 898103285Sikob struct sbp_dev *sdev; 899114732Ssimokawa int resp; 900114732Ssimokawa 901103285Sikob sdev = (struct sbp_dev *)xfer->sc; 902114732Ssimokawa 903114732SsimokawaSBP_DEBUG(1) 904103285Sikob sbp_show_sdev_info(sdev, 2); 905114732Ssimokawa printf("sbp_mgm_callback\n"); 906103285SikobEND_DEBUG 907114732Ssimokawa resp = xfer->resp; 908113584Ssimokawa sbp_xfer_free(xfer); 909114732Ssimokawa#if 0 910114732Ssimokawa if (resp != 0) { 911114732Ssimokawa sbp_show_sdev_info(sdev, 2); 912114732Ssimokawa printf("management ORB failed(%d) ... RESET_START\n", resp); 913114732Ssimokawa sbp_reset_start(sdev); 914114732Ssimokawa } 915114732Ssimokawa#endif 916103285Sikob return; 917103285Sikob} 918103285Sikob 919103285Sikobstatic void 920103285Sikobsbp_cmd_callback(struct fw_xfer *xfer) 921103285Sikob{ 922103285SikobSBP_DEBUG(2) 923103285Sikob struct sbp_dev *sdev; 924103285Sikob sdev = (struct sbp_dev *)xfer->sc; 925103285Sikob sbp_show_sdev_info(sdev, 2); 926103285Sikob printf("sbp_cmd_callback\n"); 927103285SikobEND_DEBUG 928113584Ssimokawa sbp_xfer_free(xfer); 929103285Sikob return; 930103285Sikob} 931103285Sikob 932111615Ssimokawastatic struct sbp_dev * 933111615Ssimokawasbp_next_dev(struct sbp_target *target, int lun) 934111615Ssimokawa{ 935111615Ssimokawa struct sbp_dev *sdev; 936111615Ssimokawa int i; 937111615Ssimokawa 938111615Ssimokawa for (i = lun, sdev = &target->luns[lun]; 939111615Ssimokawa i < target->num_lun; i++, sdev++) { 940111615Ssimokawa if (sdev->status == SBP_DEV_PROBE) 941111615Ssimokawa break; 942111615Ssimokawa } 943111615Ssimokawa if (i >= target->num_lun) 944111615Ssimokawa return(NULL); 945111615Ssimokawa return(sdev); 946111615Ssimokawa} 947111615Ssimokawa 948111615Ssimokawa#define SCAN_PRI 1 949103285Sikobstatic void 950111615Ssimokawasbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb) 951103285Sikob{ 952111615Ssimokawa struct sbp_target *target; 953103285Sikob struct sbp_dev *sdev; 954111615Ssimokawa 955103285Sikob sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr; 956111615Ssimokawa target = sdev->target; 957110269SsimokawaSBP_DEBUG(0) 958103285Sikob sbp_show_sdev_info(sdev, 2); 959111615Ssimokawa printf("sbp_cam_scan_lun\n"); 960103285SikobEND_DEBUG 961111615Ssimokawa if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 962111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 963111615Ssimokawa } else { 964111615Ssimokawa sbp_show_sdev_info(sdev, 2); 965111615Ssimokawa printf("scan failed\n"); 966111615Ssimokawa } 967111615Ssimokawa sdev = sbp_next_dev(target, sdev->lun_id + 1); 968111615Ssimokawa if (sdev == NULL) { 969111615Ssimokawa free(ccb, M_SBP); 970111615Ssimokawa return; 971111615Ssimokawa } 972111615Ssimokawa /* reuse ccb */ 973111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 974111615Ssimokawa ccb->ccb_h.ccb_sdev_ptr = sdev; 975111615Ssimokawa xpt_action(ccb); 976111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 977111615Ssimokawa sdev->freeze = 1; 978103285Sikob} 979103285Sikob 980103285Sikobstatic void 981111615Ssimokawasbp_cam_scan_target(void *arg) 982103285Sikob{ 983111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 984111615Ssimokawa struct sbp_dev *sdev; 985110798Ssimokawa union ccb *ccb; 986103285Sikob 987111615Ssimokawa sdev = sbp_next_dev(target, 0); 988111615Ssimokawa if (sdev == NULL) { 989111615Ssimokawa printf("sbp_cam_scan_target: nothing to do for target%d\n", 990111615Ssimokawa target->target_id); 991110798Ssimokawa return; 992110798Ssimokawa } 993103285SikobSBP_DEBUG(0) 994103285Sikob sbp_show_sdev_info(sdev, 2); 995111615Ssimokawa printf("sbp_cam_scan_target\n"); 996103285SikobEND_DEBUG 997111615Ssimokawa ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO); 998111615Ssimokawa if (ccb == NULL) { 999111615Ssimokawa printf("sbp_cam_scan_target: malloc failed\n"); 1000111615Ssimokawa return; 1001111615Ssimokawa } 1002111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 1003103285Sikob ccb->ccb_h.func_code = XPT_SCAN_LUN; 1004111615Ssimokawa ccb->ccb_h.cbfcnp = sbp_cam_scan_lun; 1005111615Ssimokawa ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 1006103285Sikob ccb->crcn.flags = CAM_FLAG_NONE; 1007103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 1008103285Sikob 1009103285Sikob /* The scan is in progress now. */ 1010111040Ssimokawa xpt_action(ccb); 1011111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1012111615Ssimokawa sdev->freeze = 1; 1013103285Sikob} 1014103285Sikob 1015111615Ssimokawastatic __inline void 1016111615Ssimokawasbp_scan_dev(struct sbp_dev *sdev) 1017111615Ssimokawa{ 1018111040Ssimokawa sdev->status = SBP_DEV_PROBE; 1019111615Ssimokawa callout_reset(&sdev->target->scan_callout, SCAN_DELAY * hz, 1020111615Ssimokawa sbp_cam_scan_target, (void *)sdev->target); 1021103285Sikob} 1022103285Sikob 1023103285Sikobstatic void 1024103285Sikobsbp_do_attach(struct fw_xfer *xfer) 1025103285Sikob{ 1026103285Sikob struct sbp_dev *sdev; 1027111615Ssimokawa struct sbp_target *target; 1028111615Ssimokawa struct sbp_softc *sbp; 1029103285Sikob 1030103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1031111615Ssimokawa target = sdev->target; 1032111615Ssimokawa sbp = target->sbp; 1033103285SikobSBP_DEBUG(0) 1034103285Sikob sbp_show_sdev_info(sdev, 2); 1035103285Sikob printf("sbp_do_attach\n"); 1036103285SikobEND_DEBUG 1037113584Ssimokawa sbp_xfer_free(xfer); 1038111199Ssimokawa 1039103285Sikob if (sdev->path == NULL) 1040103285Sikob xpt_create_path(&sdev->path, xpt_periph, 1041111615Ssimokawa cam_sim_path(target->sbp->sim), 1042111615Ssimokawa target->target_id, sdev->lun_id); 1043103285Sikob 1044111199Ssimokawa /* 1045111199Ssimokawa * Let CAM scan the bus if we are in the boot process. 1046111199Ssimokawa * XXX xpt_scan_bus cannot detect LUN larger than 0 1047111199Ssimokawa * if LUN 0 doesn't exists. 1048111199Ssimokawa */ 1049111199Ssimokawa if (sbp_cold > 0) { 1050111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1051111199Ssimokawa return; 1052111199Ssimokawa } 1053111199Ssimokawa 1054111615Ssimokawa sbp_scan_dev(sdev); 1055103285Sikob return; 1056103285Sikob} 1057103285Sikob 1058103285Sikobstatic void 1059103285Sikobsbp_agent_reset_callback(struct fw_xfer *xfer) 1060103285Sikob{ 1061103285Sikob struct sbp_dev *sdev; 1062103285Sikob 1063103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1064103285SikobSBP_DEBUG(1) 1065103285Sikob sbp_show_sdev_info(sdev, 2); 1066103285Sikob printf("sbp_cmd_callback\n"); 1067103285SikobEND_DEBUG 1068114732Ssimokawa if (xfer->resp != 0) { 1069114732Ssimokawa sbp_show_sdev_info(sdev, 2); 1070114732Ssimokawa printf("sbp_cmd_callback resp=%d\n", xfer->resp); 1071114732Ssimokawa } 1072114732Ssimokawa 1073113584Ssimokawa sbp_xfer_free(xfer); 1074111615Ssimokawa if (sdev->path) { 1075111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1076111615Ssimokawa sdev->freeze = 0; 1077111615Ssimokawa } 1078103285Sikob} 1079103285Sikob 1080103285Sikobstatic void 1081110336Ssimokawasbp_agent_reset(struct sbp_dev *sdev) 1082103285Sikob{ 1083103285Sikob struct fw_xfer *xfer; 1084103285Sikob struct fw_pkt *fp; 1085103285Sikob 1086103285SikobSBP_DEBUG(0) 1087103285Sikob sbp_show_sdev_info(sdev, 2); 1088103285Sikob printf("sbp_agent_reset\n"); 1089103285SikobEND_DEBUG 1090103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04); 1091103285Sikob if (xfer == NULL) 1092103285Sikob return; 1093115788Ssimokawa if (sdev->status == SBP_DEV_ATTACHED || sdev->status == SBP_DEV_PROBE) 1094110336Ssimokawa xfer->act.hand = sbp_agent_reset_callback; 1095110336Ssimokawa else 1096103285Sikob xfer->act.hand = sbp_do_attach; 1097103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1098103285Sikob fp->mode.wreqq.data = htonl(0xf); 1099103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1100111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_BDR_SENT); 1101103285Sikob} 1102103285Sikob 1103103285Sikobstatic void 1104103285Sikobsbp_busy_timeout_callback(struct fw_xfer *xfer) 1105103285Sikob{ 1106103285Sikob struct sbp_dev *sdev; 1107103285Sikob 1108103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1109103285SikobSBP_DEBUG(1) 1110103285Sikob sbp_show_sdev_info(sdev, 2); 1111110336Ssimokawa printf("sbp_busy_timeout_callback\n"); 1112103285SikobEND_DEBUG 1113113584Ssimokawa sbp_xfer_free(xfer); 1114110336Ssimokawa sbp_agent_reset(sdev); 1115103285Sikob} 1116103285Sikob 1117103285Sikobstatic void 1118103285Sikobsbp_busy_timeout(struct sbp_dev *sdev) 1119103285Sikob{ 1120103285Sikob struct fw_pkt *fp; 1121103285Sikob struct fw_xfer *xfer; 1122103285SikobSBP_DEBUG(0) 1123103285Sikob sbp_show_sdev_info(sdev, 2); 1124103285Sikob printf("sbp_busy_timeout\n"); 1125103285SikobEND_DEBUG 1126103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 1127103285Sikob 1128103285Sikob xfer->act.hand = sbp_busy_timeout_callback; 1129103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1130113584Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 1131113584Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; 1132110129Ssimokawa fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf); 1133103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1134103285Sikob} 1135103285Sikob 1136103285Sikobstatic void 1137103285Sikobsbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) 1138103285Sikob{ 1139103285Sikob struct fw_xfer *xfer; 1140103285Sikob struct fw_pkt *fp; 1141103285SikobSBP_DEBUG(2) 1142103285Sikob sbp_show_sdev_info(sdev, 2); 1143103285Sikob printf("sbp_orb_pointer\n"); 1144103285SikobEND_DEBUG 1145103285Sikob 1146103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08); 1147103285Sikob if (xfer == NULL) 1148103285Sikob return; 1149103285Sikob xfer->act.hand = sbp_cmd_callback; 1150103285Sikob 1151103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1152113584Ssimokawa fp->mode.wreqb.len = 8; 1153103285Sikob fp->mode.wreqb.extcode = 0; 1154103285Sikob fp->mode.wreqb.payload[0] = 1155103285Sikob htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); 1156113584Ssimokawa fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr); 1157103285Sikob 1158103285Sikob if(fw_asyreq(xfer->fc, -1, xfer) != 0){ 1159113584Ssimokawa sbp_xfer_free(xfer); 1160103285Sikob ocb->ccb->ccb_h.status = CAM_REQ_INVALID; 1161103285Sikob xpt_done(ocb->ccb); 1162103285Sikob } 1163103285Sikob} 1164103285Sikob 1165111819Ssimokawa#if 0 1166103285Sikobstatic void 1167103285Sikobsbp_doorbell(struct sbp_dev *sdev) 1168103285Sikob{ 1169103285Sikob struct fw_xfer *xfer; 1170103285Sikob struct fw_pkt *fp; 1171103285SikobSBP_DEBUG(1) 1172103285Sikob sbp_show_sdev_info(sdev, 2); 1173103285Sikob printf("sbp_doorbell\n"); 1174103285SikobEND_DEBUG 1175103285Sikob 1176103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10); 1177103285Sikob if (xfer == NULL) 1178103285Sikob return; 1179103285Sikob xfer->act.hand = sbp_cmd_callback; 1180103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1181103285Sikob fp->mode.wreqq.data = htonl(0xf); 1182103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1183103285Sikob} 1184111819Ssimokawa#endif 1185103285Sikob 1186103285Sikobstatic struct fw_xfer * 1187103285Sikobsbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) 1188103285Sikob{ 1189103285Sikob struct fw_xfer *xfer; 1190103285Sikob struct fw_pkt *fp; 1191113584Ssimokawa struct sbp_target *target; 1192113584Ssimokawa int s, new = 0; 1193103285Sikob 1194113584Ssimokawa target = sdev->target; 1195113584Ssimokawa s = splfw(); 1196113584Ssimokawa xfer = STAILQ_FIRST(&target->xferlist); 1197113584Ssimokawa if (xfer == NULL) { 1198113584Ssimokawa if (target->n_xfer > 5 /* XXX */) { 1199113584Ssimokawa printf("sbp: no more xfer for this target\n"); 1200113584Ssimokawa splx(s); 1201113584Ssimokawa return(NULL); 1202113584Ssimokawa } 1203113584Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 24, 12); 1204113584Ssimokawa if(xfer == NULL){ 1205113584Ssimokawa printf("sbp: fw_xfer_alloc_buf failed\n"); 1206113584Ssimokawa splx(s); 1207113584Ssimokawa return NULL; 1208113584Ssimokawa } 1209113584Ssimokawa target->n_xfer ++; 1210113584Ssimokawa if (debug) 1211113584Ssimokawa printf("sbp: alloc %d xfer\n", target->n_xfer); 1212113584Ssimokawa new = 1; 1213113584Ssimokawa } else { 1214113584Ssimokawa STAILQ_REMOVE_HEAD(&target->xferlist, link); 1215103285Sikob } 1216113584Ssimokawa splx(s); 1217113584Ssimokawa 1218113584Ssimokawa microtime(&xfer->tv); 1219113584Ssimokawa 1220103285Sikob if (tcode == FWTCODE_WREQQ) 1221103285Sikob xfer->send.len = 16; 1222103285Sikob else 1223103285Sikob xfer->send.len = 24; 1224113584Ssimokawa xfer->recv.len = 12; 1225103285Sikob 1226113584Ssimokawa if (new) { 1227113584Ssimokawa xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1228113584Ssimokawa xfer->fc = sdev->target->sbp->fd.fc; 1229113584Ssimokawa xfer->retry_req = fw_asybusy; 1230103285Sikob } 1231103285Sikob xfer->sc = (caddr_t)sdev; 1232103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1233113584Ssimokawa fp->mode.wreqq.dest_hi = sdev->login->cmd_hi; 1234113584Ssimokawa fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset; 1235103285Sikob fp->mode.wreqq.tlrt = 0; 1236103285Sikob fp->mode.wreqq.tcode = tcode; 1237103285Sikob fp->mode.wreqq.pri = 0; 1238103285Sikob xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst; 1239113584Ssimokawa fp->mode.wreqq.dst = xfer->dst; 1240103285Sikob 1241103285Sikob return xfer; 1242103285Sikob 1243103285Sikob} 1244103285Sikob 1245103285Sikobstatic void 1246111615Ssimokawasbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) 1247103285Sikob{ 1248103285Sikob struct fw_xfer *xfer; 1249103285Sikob struct fw_pkt *fp; 1250103285Sikob struct sbp_ocb *ocb; 1251111615Ssimokawa struct sbp_target *target; 1252103285Sikob int s, nid; 1253103285Sikob 1254111615Ssimokawa target = sdev->target; 1255111615Ssimokawa nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; 1256111615Ssimokawa 1257111615Ssimokawa s = splfw(); 1258111615Ssimokawa if (func == ORB_FUN_RUNQUEUE) { 1259111615Ssimokawa ocb = STAILQ_FIRST(&target->mgm_ocb_queue); 1260111615Ssimokawa if (target->mgm_ocb_cur != NULL || ocb == NULL) { 1261111615Ssimokawa splx(s); 1262111615Ssimokawa return; 1263111615Ssimokawa } 1264111615Ssimokawa STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); 1265111615Ssimokawa goto start; 1266111615Ssimokawa } 1267113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 1268103285Sikob splx(s); 1269103285Sikob return; 1270103285Sikob } 1271103285Sikob ocb->flags = OCB_ACT_MGM; 1272103285Sikob ocb->sdev = sdev; 1273103285Sikob 1274103285Sikob bzero((void *)(uintptr_t)(volatile void *)ocb->orb, sizeof(ocb->orb)); 1275103285Sikob ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI); 1276103285Sikob ocb->orb[7] = htonl(SBP_DEV2ADDR( 1277111615Ssimokawa device_get_unit(target->sbp->fd.dev), 1278111615Ssimokawa target->target_id, 1279103285Sikob sdev->lun_id)); 1280103285Sikob 1281107653SsimokawaSBP_DEBUG(0) 1282103285Sikob sbp_show_sdev_info(sdev, 2); 1283103285Sikob printf("%s\n", orb_fun_name[(func>>16)&0xf]); 1284107653SsimokawaEND_DEBUG 1285103285Sikob switch (func) { 1286103285Sikob case ORB_FUN_LGI: 1287103285Sikob ocb->orb[2] = htonl(nid << 16); 1288113584Ssimokawa ocb->orb[3] = htonl(sdev->dma.bus_addr); 1289103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id); 1290113584Ssimokawa ocb->orb[5] = htonl(SBP_LOGIN_SIZE); 1291113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD); 1292103285Sikob break; 1293110336Ssimokawa case ORB_FUN_ATA: 1294111615Ssimokawa ocb->orb[0] = htonl((0 << 16) | 0); 1295113584Ssimokawa ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff); 1296110336Ssimokawa /* fall through */ 1297103285Sikob case ORB_FUN_RCN: 1298103285Sikob case ORB_FUN_LGO: 1299103285Sikob case ORB_FUN_LUR: 1300103285Sikob case ORB_FUN_RST: 1301103285Sikob case ORB_FUN_ATS: 1302113584Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id); 1303103285Sikob break; 1304103285Sikob } 1305103285Sikob 1306111615Ssimokawa if (target->mgm_ocb_cur != NULL) { 1307111615Ssimokawa /* there is a standing ORB */ 1308111615Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); 1309111615Ssimokawa splx(s); 1310111615Ssimokawa return; 1311111615Ssimokawa } 1312111615Ssimokawastart: 1313111615Ssimokawa target->mgm_ocb_cur = ocb; 1314111615Ssimokawa splx(s); 1315111615Ssimokawa 1316111615Ssimokawa callout_reset(&target->mgm_ocb_timeout, 5*hz, 1317114732Ssimokawa sbp_mgm_timeout, (caddr_t)ocb); 1318103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); 1319103285Sikob if(xfer == NULL){ 1320103285Sikob return; 1321103285Sikob } 1322114732Ssimokawa xfer->act.hand = sbp_mgm_callback; 1323103285Sikob 1324103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1325113584Ssimokawa fp->mode.wreqb.dest_hi = sdev->target->mgm_hi; 1326113584Ssimokawa fp->mode.wreqb.dest_lo = sdev->target->mgm_lo; 1327113584Ssimokawa fp->mode.wreqb.len = 8; 1328103285Sikob fp->mode.wreqb.extcode = 0; 1329108503Ssimokawa fp->mode.wreqb.payload[0] = htonl(nid << 16); 1330113584Ssimokawa fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr); 1331103285Sikob 1332103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1333103285Sikob} 1334103285Sikob 1335103285Sikobstatic void 1336105792Ssimokawasbp_print_scsi_cmd(struct sbp_ocb *ocb) 1337103285Sikob{ 1338103285Sikob struct ccb_scsiio *csio; 1339103285Sikob 1340103285Sikob csio = &ocb->ccb->csio; 1341103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 1342103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 1343103285Sikob ", flags: 0x%02x, " 1344103285Sikob "%db cmd/%db data/%db sense\n", 1345103285Sikob device_get_nameunit(ocb->sdev->target->sbp->fd.dev), 1346103285Sikob ocb->ccb->ccb_h.target_id, ocb->ccb->ccb_h.target_lun, 1347103285Sikob csio->cdb_io.cdb_bytes[0], 1348103285Sikob csio->cdb_io.cdb_bytes[1], 1349103285Sikob csio->cdb_io.cdb_bytes[2], 1350103285Sikob csio->cdb_io.cdb_bytes[3], 1351103285Sikob csio->cdb_io.cdb_bytes[4], 1352103285Sikob csio->cdb_io.cdb_bytes[5], 1353103285Sikob csio->cdb_io.cdb_bytes[6], 1354103285Sikob csio->cdb_io.cdb_bytes[7], 1355103285Sikob csio->cdb_io.cdb_bytes[8], 1356103285Sikob csio->cdb_io.cdb_bytes[9], 1357103285Sikob ocb->ccb->ccb_h.flags & CAM_DIR_MASK, 1358103285Sikob csio->cdb_len, csio->dxfer_len, 1359103285Sikob csio->sense_len); 1360105792Ssimokawa} 1361105792Ssimokawa 1362105792Ssimokawastatic void 1363105792Ssimokawasbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb) 1364105792Ssimokawa{ 1365105792Ssimokawa struct sbp_cmd_status *sbp_cmd_status; 1366105792Ssimokawa struct scsi_sense_data *sense; 1367105792Ssimokawa 1368105792Ssimokawa sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data; 1369105792Ssimokawa sense = &ocb->ccb->csio.sense_data; 1370105792Ssimokawa 1371105792SsimokawaSBP_DEBUG(0) 1372105792Ssimokawa sbp_print_scsi_cmd(ocb); 1373103285Sikob /* XXX need decode status */ 1374103285Sikob sbp_show_sdev_info(ocb->sdev, 2); 1375113584Ssimokawa printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", 1376103285Sikob sbp_cmd_status->status, 1377103285Sikob sbp_cmd_status->sfmt, 1378103285Sikob sbp_cmd_status->valid, 1379103285Sikob sbp_cmd_status->s_key, 1380103285Sikob sbp_cmd_status->s_code, 1381103285Sikob sbp_cmd_status->s_qlfr, 1382103285Sikob sbp_status->len 1383103285Sikob ); 1384103285SikobEND_DEBUG 1385103285Sikob 1386110071Ssimokawa switch (sbp_cmd_status->status) { 1387110071Ssimokawa case SCSI_STATUS_CHECK_COND: 1388110071Ssimokawa case SCSI_STATUS_BUSY: 1389110071Ssimokawa case SCSI_STATUS_CMD_TERMINATED: 1390103285Sikob if(sbp_cmd_status->sfmt == SBP_SFMT_CURR){ 1391103285Sikob sense->error_code = SSD_CURRENT_ERROR; 1392103285Sikob }else{ 1393103285Sikob sense->error_code = SSD_DEFERRED_ERROR; 1394103285Sikob } 1395103285Sikob if(sbp_cmd_status->valid) 1396103285Sikob sense->error_code |= SSD_ERRCODE_VALID; 1397103285Sikob sense->flags = sbp_cmd_status->s_key; 1398103285Sikob if(sbp_cmd_status->mark) 1399103285Sikob sense->flags |= SSD_FILEMARK; 1400103285Sikob if(sbp_cmd_status->eom) 1401103285Sikob sense->flags |= SSD_EOM; 1402103285Sikob if(sbp_cmd_status->ill_len) 1403103285Sikob sense->flags |= SSD_ILI; 1404103285Sikob sense->info[0] = ntohl(sbp_cmd_status->info) & 0xff; 1405103285Sikob sense->info[1] =(ntohl(sbp_cmd_status->info) >> 8) & 0xff; 1406103285Sikob sense->info[2] =(ntohl(sbp_cmd_status->info) >> 16) & 0xff; 1407103285Sikob sense->info[3] =(ntohl(sbp_cmd_status->info) >> 24) & 0xff; 1408103285Sikob if (sbp_status->len <= 1) 1409103285Sikob /* XXX not scsi status. shouldn't be happened */ 1410103285Sikob sense->extra_len = 0; 1411103285Sikob else if (sbp_status->len <= 4) 1412103285Sikob /* add_sense_code(_qual), info, cmd_spec_info */ 1413103285Sikob sense->extra_len = 6; 1414103285Sikob else 1415103285Sikob /* fru, sense_key_spec */ 1416103285Sikob sense->extra_len = 10; 1417103285Sikob sense->cmd_spec_info[0] = ntohl(sbp_cmd_status->cdb) & 0xff; 1418103285Sikob sense->cmd_spec_info[1] = (ntohl(sbp_cmd_status->cdb) >> 8) & 0xff; 1419103285Sikob sense->cmd_spec_info[2] = (ntohl(sbp_cmd_status->cdb) >> 16) & 0xff; 1420103285Sikob sense->cmd_spec_info[3] = (ntohl(sbp_cmd_status->cdb) >> 24) & 0xff; 1421103285Sikob sense->add_sense_code = sbp_cmd_status->s_code; 1422103285Sikob sense->add_sense_code_qual = sbp_cmd_status->s_qlfr; 1423103285Sikob sense->fru = sbp_cmd_status->fru; 1424103285Sikob sense->sense_key_spec[0] = ntohl(sbp_cmd_status->s_keydep) & 0xff; 1425103285Sikob sense->sense_key_spec[1] = (ntohl(sbp_cmd_status->s_keydep) >>8) & 0xff; 1426103285Sikob sense->sense_key_spec[2] = (ntohl(sbp_cmd_status->s_keydep) >>16) & 0xff; 1427103285Sikob 1428103285Sikob ocb->ccb->csio.scsi_status = sbp_cmd_status->status;; 1429103285Sikob ocb->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR 1430103285Sikob | CAM_AUTOSNS_VALID; 1431103285Sikob/* 1432103285Sikob{ 1433103285Sikob u_int8_t j, *tmp; 1434103285Sikob tmp = sense; 1435103285Sikob for( j = 0 ; j < 32 ; j+=8){ 1436103285Sikob printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n", 1437103285Sikob tmp[j], tmp[j+1], tmp[j+2], tmp[j+3], 1438103285Sikob tmp[j+4], tmp[j+5], tmp[j+6], tmp[j+7]); 1439103285Sikob } 1440103285Sikob 1441103285Sikob} 1442103285Sikob*/ 1443110071Ssimokawa break; 1444110071Ssimokawa default: 1445110071Ssimokawa sbp_show_sdev_info(ocb->sdev, 2); 1446110071Ssimokawa printf("sbp_scsi_status: unknown scsi status 0x%x\n", 1447110071Ssimokawa sbp_cmd_status->status); 1448103285Sikob } 1449103285Sikob} 1450103285Sikob 1451103285Sikobstatic void 1452103285Sikobsbp_fix_inq_data(struct sbp_ocb *ocb) 1453103285Sikob{ 1454103285Sikob union ccb *ccb; 1455103285Sikob struct sbp_dev *sdev; 1456103285Sikob struct scsi_inquiry_data *inq; 1457103285Sikob 1458103285Sikob ccb = ocb->ccb; 1459103285Sikob sdev = ocb->sdev; 1460103285Sikob 1461103285Sikob if (ccb->csio.cdb_io.cdb_bytes[1] & SI_EVPD) 1462103285Sikob return; 1463103285SikobSBP_DEBUG(1) 1464103285Sikob sbp_show_sdev_info(sdev, 2); 1465103285Sikob printf("sbp_fix_inq_data\n"); 1466103285SikobEND_DEBUG 1467103285Sikob inq = (struct scsi_inquiry_data *) ccb->csio.data_ptr; 1468103285Sikob switch (SID_TYPE(inq)) { 1469103285Sikob case T_DIRECT: 1470103285Sikob /* 1471103285Sikob * XXX Convert Direct Access device to RBC. 1472108281Ssimokawa * I've never seen FireWire DA devices which support READ_6. 1473103285Sikob */ 1474103285Sikob#if 1 1475103285Sikob if (SID_TYPE(inq) == T_DIRECT) 1476103285Sikob inq->device |= T_RBC; /* T_DIRECT == 0 */ 1477103285Sikob#endif 1478103285Sikob /* fall through */ 1479103285Sikob case T_RBC: 1480111615Ssimokawa /* enable tag queuing */ 1481111615Ssimokawa#if 1 1482111615Ssimokawa inq->flags |= SID_CmdQue; 1483111615Ssimokawa#endif 1484103285Sikob /* 1485103285Sikob * Override vendor/product/revision information. 1486103285Sikob * Some devices sometimes return strange strings. 1487103285Sikob */ 1488111615Ssimokawa#if 1 1489103285Sikob bcopy(sdev->vendor, inq->vendor, sizeof(inq->vendor)); 1490103285Sikob bcopy(sdev->product, inq->product, sizeof(inq->product)); 1491103285Sikob bcopy(sdev->revision+2, inq->revision, sizeof(inq->revision)); 1492111615Ssimokawa#endif 1493103285Sikob break; 1494103285Sikob } 1495103285Sikob} 1496103285Sikob 1497103285Sikobstatic void 1498113584Ssimokawasbp_recv1(struct fw_xfer *xfer) 1499113584Ssimokawa{ 1500103285Sikob struct fw_pkt *rfp; 1501103285Sikob#if NEED_RESPONSE 1502103285Sikob struct fw_pkt *sfp; 1503103285Sikob#endif 1504103285Sikob struct sbp_softc *sbp; 1505103285Sikob struct sbp_dev *sdev; 1506103285Sikob struct sbp_ocb *ocb; 1507103285Sikob struct sbp_login_res *login_res = NULL; 1508103285Sikob struct sbp_status *sbp_status; 1509103285Sikob struct sbp_target *target; 1510111704Ssimokawa int orb_fun, status_valid0, status_valid, t, l, reset_agent = 0; 1511103285Sikob u_int32_t addr; 1512103285Sikob/* 1513103285Sikob u_int32_t *ld; 1514103285Sikob ld = xfer->recv.buf; 1515103285Sikobprintf("sbp %x %d %d %08x %08x %08x %08x\n", 1516103285Sikob xfer->resp, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 1517103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 1518103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11])); 1519103285Sikob*/ 1520113584Ssimokawa 1521113584Ssimokawa sbp = (struct sbp_softc *)xfer->sc; 1522103285Sikob if(xfer->resp != 0){ 1523103285Sikob printf("sbp_recv: xfer->resp != 0\n"); 1524113584Ssimokawa goto done0; 1525103285Sikob } 1526103285Sikob if(xfer->recv.buf == NULL){ 1527103285Sikob printf("sbp_recv: xfer->recv.buf == NULL\n"); 1528113584Ssimokawa goto done0; 1529103285Sikob } 1530103285Sikob sbp = (struct sbp_softc *)xfer->sc; 1531103285Sikob rfp = (struct fw_pkt *)xfer->recv.buf; 1532103285Sikob if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){ 1533103285Sikob printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); 1534113584Ssimokawa goto done0; 1535103285Sikob } 1536103285Sikob sbp_status = (struct sbp_status *)rfp->mode.wreqb.payload; 1537113584Ssimokawa addr = rfp->mode.wreqb.dest_lo; 1538103285SikobSBP_DEBUG(2) 1539103285Sikob printf("received address 0x%x\n", addr); 1540103285SikobEND_DEBUG 1541110189Ssimokawa t = SBP_ADDR2TRG(addr); 1542110189Ssimokawa if (t >= SBP_NUM_TARGETS) { 1543110189Ssimokawa device_printf(sbp->fd.dev, 1544110189Ssimokawa "sbp_recv1: invalid target %d\n", t); 1545113584Ssimokawa goto done0; 1546110189Ssimokawa } 1547110189Ssimokawa target = &sbp->targets[t]; 1548110189Ssimokawa l = SBP_ADDR2LUN(addr); 1549110189Ssimokawa if (l >= target->num_lun) { 1550110189Ssimokawa device_printf(sbp->fd.dev, 1551110189Ssimokawa "sbp_recv1: invalid lun %d (target=%d)\n", l, t); 1552113584Ssimokawa goto done0; 1553110189Ssimokawa } 1554110189Ssimokawa sdev = &target->luns[l]; 1555103285Sikob 1556110189Ssimokawa ocb = NULL; 1557110189Ssimokawa switch (sbp_status->src) { 1558110189Ssimokawa case 0: 1559110189Ssimokawa case 1: 1560111615Ssimokawa /* check mgm_ocb_cur first */ 1561111615Ssimokawa ocb = target->mgm_ocb_cur; 1562111615Ssimokawa if (ocb != NULL) { 1563111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 1564111615Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1565111615Ssimokawa target->mgm_ocb_cur = NULL; 1566111615Ssimokawa break; 1567111615Ssimokawa } 1568111615Ssimokawa } 1569111615Ssimokawa ocb = sbp_dequeue_ocb(sdev, sbp_status); 1570110189Ssimokawa if (ocb == NULL) { 1571110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1572111858Ssimokawa#if __FreeBSD_version >= 500000 1573111819Ssimokawa printf("No ocb(%x) on the queue\n", 1574111858Ssimokawa#else 1575111858Ssimokawa printf("No ocb(%lx) on the queue\n", 1576111858Ssimokawa#endif 1577111819Ssimokawa ntohl(sbp_status->orb_lo)); 1578110189Ssimokawa } 1579110189Ssimokawa break; 1580110189Ssimokawa case 2: 1581110189Ssimokawa /* unsolicit */ 1582110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1583110189Ssimokawa printf("unsolicit status received\n"); 1584110189Ssimokawa break; 1585110189Ssimokawa default: 1586110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1587110189Ssimokawa printf("unknown sbp_status->src\n"); 1588110189Ssimokawa } 1589110189Ssimokawa 1590111615Ssimokawa status_valid0 = (sbp_status->src < 2 1591110189Ssimokawa && sbp_status->resp == ORB_RES_CMPL 1592111615Ssimokawa && sbp_status->dead == 0); 1593111615Ssimokawa status_valid = (status_valid0 && sbp_status->status == 0); 1594103285Sikob 1595111615Ssimokawa if (!status_valid0 || debug > 1){ 1596103285Sikob int status; 1597110129SsimokawaSBP_DEBUG(0) 1598103285Sikob sbp_show_sdev_info(sdev, 2); 1599103285Sikob printf("ORB status src:%x resp:%x dead:%x" 1600108712Ssimokawa#if __FreeBSD_version >= 500000 1601103285Sikob " len:%x stat:%x orb:%x%08x\n", 1602108712Ssimokawa#else 1603108712Ssimokawa " len:%x stat:%x orb:%x%08lx\n", 1604108712Ssimokawa#endif 1605103285Sikob sbp_status->src, sbp_status->resp, sbp_status->dead, 1606103285Sikob sbp_status->len, sbp_status->status, 1607108280Ssimokawa ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); 1608110129SsimokawaEND_DEBUG 1609103285Sikob sbp_show_sdev_info(sdev, 2); 1610103285Sikob status = sbp_status->status; 1611103285Sikob switch(sbp_status->resp) { 1612103285Sikob case 0: 1613103285Sikob if (status > MAX_ORB_STATUS0) 1614103285Sikob printf("%s\n", orb_status0[MAX_ORB_STATUS0]); 1615110189Ssimokawa else 1616110129Ssimokawa printf("%s\n", orb_status0[status]); 1617103285Sikob break; 1618103285Sikob case 1: 1619110336Ssimokawa printf("Obj: %s, Error: %s\n", 1620103285Sikob orb_status1_object[(status>>6) & 3], 1621103285Sikob orb_status1_serial_bus_error[status & 0xf]); 1622103285Sikob break; 1623110129Ssimokawa case 2: 1624110129Ssimokawa printf("Illegal request\n"); 1625110129Ssimokawa break; 1626110129Ssimokawa case 3: 1627110129Ssimokawa printf("Vendor dependent\n"); 1628110129Ssimokawa break; 1629103285Sikob default: 1630110129Ssimokawa printf("unknown respose code %d\n", sbp_status->resp); 1631103285Sikob } 1632103285Sikob } 1633103285Sikob 1634103285Sikob /* we have to reset the fetch agent if it's dead */ 1635103285Sikob if (sbp_status->dead) { 1636111615Ssimokawa if (sdev->path) { 1637103285Sikob xpt_freeze_devq(sdev->path, 1); 1638111615Ssimokawa sdev->freeze ++; 1639111615Ssimokawa } 1640111704Ssimokawa reset_agent = 1; 1641103285Sikob } 1642103285Sikob 1643111704Ssimokawa if (ocb == NULL) 1644111704Ssimokawa goto done; 1645103285Sikob 1646103285Sikob switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK){ 1647103285Sikob case ORB_FMT_NOP: 1648103285Sikob break; 1649103285Sikob case ORB_FMT_VED: 1650103285Sikob break; 1651103285Sikob case ORB_FMT_STD: 1652111819Ssimokawa switch(ocb->flags) { 1653103285Sikob case OCB_ACT_MGM: 1654103285Sikob orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK; 1655103285Sikob switch(orb_fun) { 1656103285Sikob case ORB_FUN_LGI: 1657113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD); 1658113584Ssimokawa login_res = sdev->login; 1659103285Sikob login_res->len = ntohs(login_res->len); 1660103285Sikob login_res->id = ntohs(login_res->id); 1661103285Sikob login_res->cmd_hi = ntohs(login_res->cmd_hi); 1662103285Sikob login_res->cmd_lo = ntohl(login_res->cmd_lo); 1663103285Sikob if (status_valid) { 1664103285SikobSBP_DEBUG(0) 1665103285Sikobsbp_show_sdev_info(sdev, 2); 1666103285Sikobprintf("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)); 1667103285SikobEND_DEBUG 1668103285Sikob sbp_busy_timeout(sdev); 1669103285Sikob } else { 1670110336Ssimokawa /* forgot logout? */ 1671110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1672103285Sikob printf("login failed\n"); 1673103285Sikob sdev->status = SBP_DEV_RESET; 1674103285Sikob } 1675103285Sikob break; 1676103285Sikob case ORB_FUN_RCN: 1677113584Ssimokawa login_res = sdev->login; 1678103285Sikob if (status_valid) { 1679103285SikobSBP_DEBUG(0) 1680103285Sikobsbp_show_sdev_info(sdev, 2); 1681103285Sikobprintf("reconnect: len %d, ID %d, cmd %08x%08x\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo); 1682103285SikobEND_DEBUG 1683103285Sikob#if 1 1684111615Ssimokawa if (sdev->status == SBP_DEV_ATTACHED) 1685111615Ssimokawa sbp_scan_dev(sdev); 1686111615Ssimokawa else 1687111615Ssimokawa sbp_agent_reset(sdev); 1688103285Sikob#else 1689110336Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1690111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_ATS, NULL); 1691103285Sikob#endif 1692103285Sikob } else { 1693103285Sikob /* reconnection hold time exceed? */ 1694110336SsimokawaSBP_DEBUG(0) 1695110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1696103285Sikob printf("reconnect failed\n"); 1697110336SsimokawaEND_DEBUG 1698111615Ssimokawa sbp_login(sdev); 1699103285Sikob } 1700103285Sikob break; 1701103285Sikob case ORB_FUN_LGO: 1702103285Sikob sdev->status = SBP_DEV_RESET; 1703103285Sikob break; 1704110336Ssimokawa case ORB_FUN_RST: 1705110336Ssimokawa sbp_busy_timeout(sdev); 1706110336Ssimokawa break; 1707103285Sikob case ORB_FUN_LUR: 1708103285Sikob case ORB_FUN_ATA: 1709103285Sikob case ORB_FUN_ATS: 1710110336Ssimokawa sbp_agent_reset(sdev); 1711103285Sikob break; 1712103285Sikob default: 1713110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1714110336Ssimokawa printf("unknown function %d\n", orb_fun); 1715103285Sikob break; 1716103285Sikob } 1717111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 1718103285Sikob break; 1719103285Sikob case OCB_ACT_CMD: 1720114732Ssimokawa sdev->timeout = 0; 1721103285Sikob if(ocb->ccb != NULL){ 1722103285Sikob union ccb *ccb; 1723103285Sikob/* 1724103285Sikob u_int32_t *ld; 1725103285Sikob ld = ocb->ccb->csio.data_ptr; 1726103285Sikob if(ld != NULL && ocb->ccb->csio.dxfer_len != 0) 1727103285Sikob printf("ptr %08x %08x %08x %08x\n", ld[0], ld[1], ld[2], ld[3]); 1728103285Sikob else 1729103285Sikob printf("ptr NULL\n"); 1730103285Sikobprintf("len %d\n", sbp_status->len); 1731103285Sikob*/ 1732103285Sikob ccb = ocb->ccb; 1733103285Sikob if(sbp_status->len > 1){ 1734103285Sikob sbp_scsi_status(sbp_status, ocb); 1735103285Sikob }else{ 1736103285Sikob if(sbp_status->resp != ORB_RES_CMPL){ 1737103285Sikob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1738103285Sikob }else{ 1739103285Sikob ccb->ccb_h.status = CAM_REQ_CMP; 1740103285Sikob } 1741103285Sikob } 1742103285Sikob /* fix up inq data */ 1743103285Sikob if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY) 1744103285Sikob sbp_fix_inq_data(ocb); 1745103285Sikob xpt_done(ccb); 1746103285Sikob } 1747103285Sikob break; 1748103285Sikob default: 1749103285Sikob break; 1750103285Sikob } 1751103285Sikob } 1752103285Sikob 1753113584Ssimokawa sbp_free_ocb(sdev, ocb); 1754111704Ssimokawadone: 1755111704Ssimokawa if (reset_agent) 1756111704Ssimokawa sbp_agent_reset(sdev); 1757103285Sikob 1758113584Ssimokawadone0: 1759103285Sikob/* The received packet is usually small enough to be stored within 1760103285Sikob * the buffer. In that case, the controller return ack_complete and 1761103285Sikob * no respose is necessary. 1762103285Sikob * 1763103285Sikob * XXX fwohci.c and firewire.c should inform event_code such as 1764103285Sikob * ack_complete or ack_pending to upper driver. 1765103285Sikob */ 1766103285Sikob#if NEED_RESPONSE 1767103285Sikob xfer->send.off = 0; 1768103285Sikob sfp = (struct fw_pkt *)xfer->send.buf; 1769103285Sikob sfp->mode.wres.dst = rfp->mode.wreqb.src; 1770113584Ssimokawa xfer->dst = sfp->mode.wres.dst; 1771103285Sikob xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1772103285Sikob xfer->act.hand = sbp_loginres_callback; 1773103285Sikob xfer->retry_req = fw_asybusy; 1774103285Sikob 1775103285Sikob sfp->mode.wres.tlrt = rfp->mode.wreqb.tlrt; 1776103285Sikob sfp->mode.wres.tcode = FWTCODE_WRES; 1777103285Sikob sfp->mode.wres.rtcode = 0; 1778103285Sikob sfp->mode.wres.pri = 0; 1779103285Sikob 1780103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1781103285Sikob#else 1782113584Ssimokawa /* recycle */ 1783113584Ssimokawa xfer->recv.len = SBP_RECV_LEN; 1784113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1785103285Sikob#endif 1786103285Sikob 1787103285Sikob return; 1788103285Sikob 1789103285Sikob} 1790103285Sikob 1791103285Sikobstatic void 1792103285Sikobsbp_recv(struct fw_xfer *xfer) 1793103285Sikob{ 1794103285Sikob int s; 1795103285Sikob 1796103285Sikob s = splcam(); 1797103285Sikob sbp_recv1(xfer); 1798103285Sikob splx(s); 1799103285Sikob} 1800103285Sikob/* 1801103285Sikob * sbp_attach() 1802103285Sikob */ 1803103285Sikobstatic int 1804103285Sikobsbp_attach(device_t dev) 1805103285Sikob{ 1806103285Sikob struct sbp_softc *sbp; 1807103285Sikob struct cam_devq *devq; 1808103285Sikob struct fw_xfer *xfer; 1809103285Sikob int i, s, error; 1810103285Sikob 1811103285SikobSBP_DEBUG(0) 1812111199Ssimokawa printf("sbp_attach (cold=%d)\n", cold); 1813103285SikobEND_DEBUG 1814103285Sikob 1815111199Ssimokawa if (cold) 1816111199Ssimokawa sbp_cold ++; 1817103285Sikob sbp = ((struct sbp_softc *)device_get_softc(dev)); 1818103285Sikob bzero(sbp, sizeof(struct sbp_softc)); 1819103285Sikob sbp->fd.dev = dev; 1820103285Sikob sbp->fd.fc = device_get_ivars(dev); 1821113584Ssimokawa error = bus_dma_tag_create(/*parent*/sbp->fd.fc->dmat, 1822113584Ssimokawa /* XXX shoud be 4 for sane backend? */ 1823113584Ssimokawa /*alignment*/1, 1824103285Sikob /*boundary*/0, 1825103285Sikob /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1826103285Sikob /*highaddr*/BUS_SPACE_MAXADDR, 1827103285Sikob /*filter*/NULL, /*filterarg*/NULL, 1828103285Sikob /*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX, 1829113474Ssimokawa /*maxsegsz*/SBP_SEG_MAX, 1830103285Sikob /*flags*/BUS_DMA_ALLOCNOW, 1831103285Sikob &sbp->dmat); 1832103285Sikob if (error != 0) { 1833103285Sikob printf("sbp_attach: Could not allocate DMA tag " 1834103285Sikob "- error %d\n", error); 1835103285Sikob return (ENOMEM); 1836103285Sikob } 1837103285Sikob 1838103285Sikob devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB); 1839103285Sikob if (devq == NULL) 1840103285Sikob return (ENXIO); 1841103285Sikob 1842103285Sikob for( i = 0 ; i < SBP_NUM_TARGETS ; i++){ 1843103285Sikob sbp->targets[i].fwdev = NULL; 1844103285Sikob sbp->targets[i].luns = NULL; 1845103285Sikob } 1846103285Sikob 1847103285Sikob sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp, 1848103285Sikob device_get_unit(dev), 1849111615Ssimokawa /*untagged*/ 1, 1850111615Ssimokawa /*tagged*/ SBP_QUEUE_LEN, 1851111615Ssimokawa devq); 1852103285Sikob 1853103285Sikob if (sbp->sim == NULL) { 1854103285Sikob cam_simq_free(devq); 1855103285Sikob return (ENXIO); 1856103285Sikob } 1857103285Sikob 1858103285Sikob 1859111615Ssimokawa if (xpt_bus_register(sbp->sim, /*bus*/0) != CAM_SUCCESS) 1860111615Ssimokawa goto fail; 1861103285Sikob 1862111615Ssimokawa if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim), 1863111615Ssimokawa CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1864111615Ssimokawa goto fail; 1865111615Ssimokawa 1866103285Sikob sbp->fwb.start_hi = SBP_BIND_HI; 1867103285Sikob sbp->fwb.start_lo = SBP_DEV2ADDR(device_get_unit(sbp->fd.dev), 0, 0); 1868103285Sikob /* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */ 1869103285Sikob sbp->fwb.addrlen = 0xffff; 1870113584Ssimokawa sbp->fwb.act_type = FWACT_XFER; 1871113584Ssimokawa /* pre-allocate xfer */ 1872113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 1873113584Ssimokawa for (i = 0; i < SBP_NUM_OCB/2; i ++) { 1874113584Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 1875113584Ssimokawa#if NEED_RESPONSE 1876113584Ssimokawa /* send */12, 1877113584Ssimokawa#else 1878113584Ssimokawa /* send */0, 1879113584Ssimokawa#endif 1880113584Ssimokawa /* recv */SBP_RECV_LEN); 1881113584Ssimokawa xfer->act.hand = sbp_recv; 1882113584Ssimokawa#if NEED_RESPONSE 1883113584Ssimokawa xfer->fc = sbp->fd.fc; 1884113584Ssimokawa#endif 1885113584Ssimokawa xfer->sc = (caddr_t)sbp; 1886113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1887113584Ssimokawa } 1888103285Sikob fw_bindadd(sbp->fd.fc, &sbp->fwb); 1889103285Sikob 1890113584Ssimokawa sbp->fd.post_busreset = sbp_post_busreset; 1891103285Sikob sbp->fd.post_explore = sbp_post_explore; 1892103285Sikob 1893111199Ssimokawa if (sbp->fd.fc->status != -1) { 1894111199Ssimokawa s = splfw(); 1895111199Ssimokawa sbp_post_explore((void *)sbp); 1896111199Ssimokawa splx(s); 1897111199Ssimokawa } 1898111199Ssimokawa 1899103285Sikob return (0); 1900111615Ssimokawafail: 1901111615Ssimokawa cam_sim_free(sbp->sim, /*free_devq*/TRUE); 1902111615Ssimokawa return (ENXIO); 1903103285Sikob} 1904103285Sikob 1905103285Sikobstatic int 1906110145Ssimokawasbp_logout_all(struct sbp_softc *sbp) 1907110145Ssimokawa{ 1908110145Ssimokawa struct sbp_target *target; 1909110145Ssimokawa struct sbp_dev *sdev; 1910110145Ssimokawa int i, j; 1911110145Ssimokawa 1912110145SsimokawaSBP_DEBUG(0) 1913110145Ssimokawa printf("sbp_logout_all\n"); 1914110145SsimokawaEND_DEBUG 1915110145Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) { 1916110145Ssimokawa target = &sbp->targets[i]; 1917110145Ssimokawa if (target->luns == NULL) 1918110145Ssimokawa continue; 1919110145Ssimokawa for (j = 0; j < target->num_lun; j++) { 1920110145Ssimokawa sdev = &target->luns[j]; 1921113584Ssimokawa callout_stop(&sdev->login_callout); 1922110336Ssimokawa if (sdev->status >= SBP_DEV_TOATTACH && 1923110336Ssimokawa sdev->status <= SBP_DEV_ATTACHED) 1924111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); 1925110145Ssimokawa } 1926110145Ssimokawa } 1927113584Ssimokawa 1928110145Ssimokawa return 0; 1929110145Ssimokawa} 1930110145Ssimokawa 1931110145Ssimokawastatic int 1932110145Ssimokawasbp_shutdown(device_t dev) 1933110145Ssimokawa{ 1934110145Ssimokawa struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 1935110145Ssimokawa 1936110145Ssimokawa sbp_logout_all(sbp); 1937110145Ssimokawa return (0); 1938110145Ssimokawa} 1939110145Ssimokawa 1940110145Ssimokawastatic int 1941103285Sikobsbp_detach(device_t dev) 1942103285Sikob{ 1943103285Sikob struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 1944103285Sikob struct firewire_comm *fc = sbp->fd.fc; 1945113584Ssimokawa struct sbp_target *target; 1946113584Ssimokawa struct sbp_dev *sdev; 1947113584Ssimokawa struct fw_xfer *xfer, *next; 1948113584Ssimokawa int i, j; 1949103285Sikob 1950103285SikobSBP_DEBUG(0) 1951103285Sikob printf("sbp_detach\n"); 1952103285SikobEND_DEBUG 1953113584Ssimokawa 1954103285Sikob for (i = 0; i < SBP_NUM_TARGETS; i ++) 1955110145Ssimokawa sbp_cam_detach_target(&sbp->targets[i]); 1956111615Ssimokawa xpt_free_path(sbp->path); 1957103285Sikob xpt_bus_deregister(cam_sim_path(sbp->sim)); 1958110145Ssimokawa 1959110145Ssimokawa sbp_logout_all(sbp); 1960113584Ssimokawa 1961110145Ssimokawa /* XXX wait for logout completion */ 1962110145Ssimokawa tsleep(&i, FWPRI, "sbpdtc", hz/2); 1963110145Ssimokawa 1964113584Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) { 1965113584Ssimokawa target = &sbp->targets[i]; 1966113584Ssimokawa if (target->luns == NULL) 1967113584Ssimokawa continue; 1968113584Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1969113584Ssimokawa for (j = 0; j < target->num_lun; j++) { 1970113584Ssimokawa sdev = &target->luns[j]; 1971113584Ssimokawa if (sdev->status != SBP_DEV_DEAD) { 1972113584Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) 1973113584Ssimokawa bus_dmamap_destroy(sbp->dmat, 1974113584Ssimokawa sdev->ocb[i].dmamap); 1975113584Ssimokawa fwdma_free(sbp->fd.fc, &sdev->dma); 1976113584Ssimokawa } 1977113584Ssimokawa } 1978113584Ssimokawa for (xfer = STAILQ_FIRST(&target->xferlist); 1979113584Ssimokawa xfer != NULL; xfer = next) { 1980113584Ssimokawa next = STAILQ_NEXT(xfer, link); 1981113584Ssimokawa fw_xfer_free(xfer); 1982113584Ssimokawa } 1983113584Ssimokawa free(target->luns, M_SBP); 1984113584Ssimokawa } 1985113584Ssimokawa 1986113584Ssimokawa for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist); 1987113584Ssimokawa xfer != NULL; xfer = next) { 1988113584Ssimokawa next = STAILQ_NEXT(xfer, link); 1989113584Ssimokawa fw_xfer_free(xfer); 1990113584Ssimokawa } 1991113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 1992110145Ssimokawa fw_bindremove(fc, &sbp->fwb); 1993113584Ssimokawa 1994103285Sikob bus_dma_tag_destroy(sbp->dmat); 1995110145Ssimokawa 1996103285Sikob return (0); 1997103285Sikob} 1998103285Sikob 1999103285Sikobstatic void 2000110145Ssimokawasbp_cam_detach_target(struct sbp_target *target) 2001103285Sikob{ 2002113584Ssimokawa struct sbp_dev *sdev; 2003103285Sikob int i; 2004103285Sikob 2005103285Sikob if (target->luns != NULL) { 2006108529SsimokawaSBP_DEBUG(0) 2007103285Sikob printf("sbp_detach_target %d\n", target->target_id); 2008108529SsimokawaEND_DEBUG 2009111615Ssimokawa callout_stop(&target->scan_callout); 2010110193Ssimokawa for (i = 0; i < target->num_lun; i++) { 2011103285Sikob sdev = &target->luns[i]; 2012113584Ssimokawa if (sdev->status == SBP_DEV_DEAD) 2013103285Sikob continue; 2014113584Ssimokawa if (sdev->status == SBP_DEV_RESET) 2015113584Ssimokawa continue; 2016110336Ssimokawa if (sdev->path) { 2017114286Ssimokawa xpt_release_devq(sdev->path, 2018114286Ssimokawa sdev->freeze, TRUE); 2019114286Ssimokawa sdev->freeze = 0; 2020103285Sikob xpt_async(AC_LOST_DEVICE, sdev->path, NULL); 2021110336Ssimokawa xpt_free_path(sdev->path); 2022110336Ssimokawa sdev->path = NULL; 2023110336Ssimokawa } 2024103285Sikob sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE); 2025103285Sikob } 2026103285Sikob } 2027103285Sikob} 2028103285Sikob 2029103285Sikobstatic void 2030114732Ssimokawasbp_target_reset(struct sbp_dev *sdev, int method) 2031114732Ssimokawa{ 2032114732Ssimokawa int i; 2033114732Ssimokawa struct sbp_target *target = sdev->target; 2034114732Ssimokawa struct sbp_dev *tsdev; 2035114732Ssimokawa 2036114732Ssimokawa for (i = 0; i < target->num_lun; i++) { 2037114732Ssimokawa tsdev = &target->luns[i]; 2038114732Ssimokawa if (tsdev->status == SBP_DEV_DEAD) 2039114732Ssimokawa continue; 2040114732Ssimokawa if (tsdev->status == SBP_DEV_RESET) 2041114732Ssimokawa continue; 2042114732Ssimokawa xpt_freeze_devq(tsdev->path, 1); 2043114732Ssimokawa tsdev->freeze ++; 2044114732Ssimokawa sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT); 2045114732Ssimokawa if (method == 2) 2046114732Ssimokawa tsdev->status = SBP_DEV_LOGIN; 2047114732Ssimokawa } 2048114732Ssimokawa switch(method) { 2049114732Ssimokawa case 1: 2050114732Ssimokawa printf("target reset\n"); 2051114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); 2052114732Ssimokawa break; 2053114732Ssimokawa case 2: 2054114732Ssimokawa printf("reset start\n"); 2055114732Ssimokawa sbp_reset_start(sdev); 2056114732Ssimokawa break; 2057114732Ssimokawa } 2058114732Ssimokawa 2059114732Ssimokawa} 2060114732Ssimokawa 2061114732Ssimokawastatic void 2062114732Ssimokawasbp_mgm_timeout(void *arg) 2063114732Ssimokawa{ 2064114732Ssimokawa struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2065114732Ssimokawa struct sbp_dev *sdev = ocb->sdev; 2066114732Ssimokawa struct sbp_target *target = sdev->target; 2067114732Ssimokawa 2068114732Ssimokawa sbp_show_sdev_info(sdev, 2); 2069114732Ssimokawa printf("management ORB timeout\n"); 2070114732Ssimokawa target->mgm_ocb_cur = NULL; 2071114732Ssimokawa sbp_free_ocb(sdev, ocb); 2072114732Ssimokawa#if 0 2073114732Ssimokawa /* XXX */ 2074114732Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 2075114732Ssimokawa#endif 2076114732Ssimokawa#if 0 2077114732Ssimokawa sbp_reset_start(sdev); 2078114732Ssimokawa#endif 2079114732Ssimokawa} 2080114732Ssimokawa 2081114732Ssimokawastatic void 2082103285Sikobsbp_timeout(void *arg) 2083103285Sikob{ 2084103285Sikob struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 2085103285Sikob struct sbp_dev *sdev = ocb->sdev; 2086103285Sikob 2087103285Sikob sbp_show_sdev_info(sdev, 2); 2088110336Ssimokawa printf("request timeout ... "); 2089103285Sikob 2090114732Ssimokawa sdev->timeout ++; 2091114732Ssimokawa switch(sdev->timeout) { 2092114732Ssimokawa case 1: 2093110336Ssimokawa printf("agent reset\n"); 2094114732Ssimokawa xpt_freeze_devq(sdev->path, 1); 2095114732Ssimokawa sdev->freeze ++; 2096114732Ssimokawa sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); 2097110336Ssimokawa sbp_agent_reset(sdev); 2098114732Ssimokawa break; 2099114732Ssimokawa case 2: 2100114732Ssimokawa case 3: 2101114732Ssimokawa sbp_target_reset(sdev, sdev->timeout - 1); 2102114732Ssimokawa break; 2103114732Ssimokawa#if 0 2104114732Ssimokawa default: 2105114732Ssimokawa /* XXX give up */ 2106114732Ssimokawa sbp_cam_detach_target(target); 2107114732Ssimokawa if (target->luns != NULL) 2108114732Ssimokawa free(target->luns, M_SBP); 2109114732Ssimokawa target->num_lun = 0;; 2110114732Ssimokawa target->luns = NULL; 2111114732Ssimokawa target->fwdev = NULL; 2112114732Ssimokawa#endif 2113110336Ssimokawa } 2114103285Sikob} 2115103285Sikob 2116103285Sikobstatic void 2117103285Sikobsbp_action1(struct cam_sim *sim, union ccb *ccb) 2118103285Sikob{ 2119103285Sikob 2120103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)sim->softc; 2121103285Sikob struct sbp_target *target = NULL; 2122103285Sikob struct sbp_dev *sdev = NULL; 2123103285Sikob 2124103285Sikob /* target:lun -> sdev mapping */ 2125103285Sikob if (sbp != NULL 2126103285Sikob && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD 2127103285Sikob && ccb->ccb_h.target_id < SBP_NUM_TARGETS) { 2128103285Sikob target = &sbp->targets[ccb->ccb_h.target_id]; 2129103285Sikob if (target->fwdev != NULL 2130103285Sikob && ccb->ccb_h.target_lun != CAM_LUN_WILDCARD 2131103285Sikob && ccb->ccb_h.target_lun < target->num_lun) { 2132103285Sikob sdev = &target->luns[ccb->ccb_h.target_lun]; 2133103285Sikob if (sdev->status != SBP_DEV_ATTACHED && 2134103285Sikob sdev->status != SBP_DEV_PROBE) 2135103285Sikob sdev = NULL; 2136103285Sikob } 2137103285Sikob } 2138103285Sikob 2139103285SikobSBP_DEBUG(1) 2140103285Sikob if (sdev == NULL) 2141103285Sikob printf("invalid target %d lun %d\n", 2142103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2143103285SikobEND_DEBUG 2144103285Sikob 2145103285Sikob switch (ccb->ccb_h.func_code) { 2146103285Sikob case XPT_SCSI_IO: 2147103285Sikob case XPT_RESET_DEV: 2148103285Sikob case XPT_GET_TRAN_SETTINGS: 2149103285Sikob case XPT_SET_TRAN_SETTINGS: 2150103285Sikob case XPT_CALC_GEOMETRY: 2151103285Sikob if (sdev == NULL) { 2152103285SikobSBP_DEBUG(1) 2153103285Sikob printf("%s:%d:%d:func_code 0x%04x: " 2154103285Sikob "Invalid target (target needed)\n", 2155103285Sikob device_get_nameunit(sbp->fd.dev), 2156103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2157103285Sikob ccb->ccb_h.func_code); 2158103285SikobEND_DEBUG 2159103285Sikob 2160108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2161103285Sikob xpt_done(ccb); 2162103285Sikob return; 2163103285Sikob } 2164103285Sikob break; 2165103285Sikob case XPT_PATH_INQ: 2166103285Sikob case XPT_NOOP: 2167103285Sikob /* The opcodes sometimes aimed at a target (sc is valid), 2168103285Sikob * sometimes aimed at the SIM (sc is invalid and target is 2169103285Sikob * CAM_TARGET_WILDCARD) 2170103285Sikob */ 2171103285Sikob if (sbp == NULL && 2172103285Sikob ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 2173103285SikobSBP_DEBUG(0) 2174103285Sikob printf("%s:%d:%d func_code 0x%04x: " 2175103285Sikob "Invalid target (no wildcard)\n", 2176103285Sikob device_get_nameunit(sbp->fd.dev), 2177103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2178103285Sikob ccb->ccb_h.func_code); 2179103285SikobEND_DEBUG 2180108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2181103285Sikob xpt_done(ccb); 2182103285Sikob return; 2183103285Sikob } 2184103285Sikob break; 2185103285Sikob default: 2186103285Sikob /* XXX Hm, we should check the input parameters */ 2187103285Sikob break; 2188103285Sikob } 2189103285Sikob 2190103285Sikob switch (ccb->ccb_h.func_code) { 2191103285Sikob case XPT_SCSI_IO: 2192103285Sikob { 2193103285Sikob struct ccb_scsiio *csio; 2194103285Sikob struct sbp_ocb *ocb; 2195113584Ssimokawa int speed; 2196106506Ssimokawa void *cdb; 2197103285Sikob 2198103285Sikob csio = &ccb->csio; 2199103285Sikob 2200103285SikobSBP_DEBUG(1) 2201103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 2202103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 2203103285Sikob ", flags: 0x%02x, " 2204103285Sikob "%db cmd/%db data/%db sense\n", 2205103285Sikob device_get_nameunit(sbp->fd.dev), 2206103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2207103285Sikob csio->cdb_io.cdb_bytes[0], 2208103285Sikob csio->cdb_io.cdb_bytes[1], 2209103285Sikob csio->cdb_io.cdb_bytes[2], 2210103285Sikob csio->cdb_io.cdb_bytes[3], 2211103285Sikob csio->cdb_io.cdb_bytes[4], 2212103285Sikob csio->cdb_io.cdb_bytes[5], 2213103285Sikob csio->cdb_io.cdb_bytes[6], 2214103285Sikob csio->cdb_io.cdb_bytes[7], 2215103285Sikob csio->cdb_io.cdb_bytes[8], 2216103285Sikob csio->cdb_io.cdb_bytes[9], 2217103285Sikob ccb->ccb_h.flags & CAM_DIR_MASK, 2218103285Sikob csio->cdb_len, csio->dxfer_len, 2219103285Sikob csio->sense_len); 2220103285SikobEND_DEBUG 2221103285Sikob if(sdev == NULL){ 2222103285Sikob ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2223103285Sikob xpt_done(ccb); 2224103285Sikob return; 2225103285Sikob } 2226103285Sikob#if 0 2227103285Sikob /* if we are in probe stage, pass only probe commands */ 2228103285Sikob if (sdev->status == SBP_DEV_PROBE) { 2229103285Sikob char *name; 2230103285Sikob name = xpt_path_periph(ccb->ccb_h.path)->periph_name; 2231103285Sikob printf("probe stage, periph name: %s\n", name); 2232103285Sikob if (strcmp(name, "probe") != 0) { 2233103285Sikob ccb->ccb_h.status = CAM_REQUEUE_REQ; 2234103285Sikob xpt_done(ccb); 2235103285Sikob return; 2236103285Sikob } 2237103285Sikob } 2238103285Sikob#endif 2239113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) 2240103285Sikob return; 2241113584Ssimokawa 2242103285Sikob ocb->flags = OCB_ACT_CMD; 2243103285Sikob ocb->sdev = sdev; 2244103285Sikob ocb->ccb = ccb; 2245103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 2246103285Sikob ocb->orb[0] = htonl(1 << 31); 2247103285Sikob ocb->orb[1] = 0; 2248103285Sikob ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS )<< 16) ); 2249113584Ssimokawa ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); 2250103285Sikob speed = min(target->fwdev->speed, max_speed); 2251103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) 2252103285Sikob | ORB_CMD_MAXP(speed + 7)); 2253103285Sikob if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN){ 2254103285Sikob ocb->orb[4] |= htonl(ORB_CMD_IN); 2255103285Sikob } 2256103285Sikob 2257103285Sikob if (csio->ccb_h.flags & CAM_SCATTER_VALID) 2258103285Sikob printf("sbp: CAM_SCATTER_VALID\n"); 2259103285Sikob if (csio->ccb_h.flags & CAM_DATA_PHYS) 2260103285Sikob printf("sbp: CAM_DATA_PHYS\n"); 2261103285Sikob 2262106506Ssimokawa if (csio->ccb_h.flags & CAM_CDB_POINTER) 2263106506Ssimokawa cdb = (void *)csio->cdb_io.cdb_ptr; 2264106506Ssimokawa else 2265106506Ssimokawa cdb = (void *)&csio->cdb_io.cdb_bytes; 2266106506Ssimokawa bcopy(cdb, 2267103285Sikob (void *)(uintptr_t)(volatile void *)&ocb->orb[5], 2268106506Ssimokawa csio->cdb_len); 2269103285Sikob/* 2270103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3])); 2271103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); 2272103285Sikob*/ 2273103285Sikob if (ccb->csio.dxfer_len > 0) { 2274113584Ssimokawa int s, error; 2275103285Sikob 2276103285Sikob s = splsoftvm(); 2277113584Ssimokawa error = bus_dmamap_load(/*dma tag*/sbp->dmat, 2278103285Sikob /*dma map*/ocb->dmamap, 2279103285Sikob ccb->csio.data_ptr, 2280103285Sikob ccb->csio.dxfer_len, 2281103285Sikob sbp_execute_ocb, 2282103285Sikob ocb, 2283103285Sikob /*flags*/0); 2284103285Sikob splx(s); 2285113584Ssimokawa if (error) 2286113584Ssimokawa printf("sbp: bus_dmamap_load error %d\n", error); 2287103285Sikob } else 2288103285Sikob sbp_execute_ocb(ocb, NULL, 0, 0); 2289103285Sikob break; 2290103285Sikob } 2291103285Sikob case XPT_CALC_GEOMETRY: 2292103285Sikob { 2293103285Sikob struct ccb_calc_geometry *ccg; 2294116429Ssimokawa#if __FreeBSD_version < 501100 2295116429Ssimokawa u_int32_t size_mb; 2296116429Ssimokawa u_int32_t secs_per_cylinder; 2297116429Ssimokawa int extended = 1; 2298116429Ssimokawa#endif 2299116351Snjl 2300103285Sikob ccg = &ccb->ccg; 2301103285Sikob if (ccg->block_size == 0) { 2302103285Sikob printf("sbp_action1: block_size is 0.\n"); 2303103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2304103285Sikob xpt_done(ccb); 2305103285Sikob break; 2306103285Sikob } 2307103285SikobSBP_DEBUG(1) 2308103285Sikob printf("%s:%d:%d:%d:XPT_CALC_GEOMETRY: " 2309114927Ssimokawa#if __FreeBSD_version >= 500000 2310114540Sjake "Volume size = %jd\n", 2311114927Ssimokawa#else 2312114927Ssimokawa "Volume size = %d\n", 2313114927Ssimokawa#endif 2314114927Ssimokawa device_get_nameunit(sbp->fd.dev), 2315114927Ssimokawa cam_sim_path(sbp->sim), 2316103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2317114927Ssimokawa#if __FreeBSD_version >= 500000 2318114927Ssimokawa (uintmax_t) 2319114927Ssimokawa#endif 2320114927Ssimokawa ccg->volume_size); 2321103285SikobEND_DEBUG 2322103285Sikob 2323116429Ssimokawa#if __FreeBSD_version < 501100 2324116429Ssimokawa size_mb = ccg->volume_size 2325116429Ssimokawa / ((1024L * 1024L) / ccg->block_size); 2326116429Ssimokawa 2327116429Ssimokawa if (size_mb > 1024 && extended) { 2328116429Ssimokawa ccg->heads = 255; 2329116429Ssimokawa ccg->secs_per_track = 63; 2330116429Ssimokawa } else { 2331116429Ssimokawa ccg->heads = 64; 2332116429Ssimokawa ccg->secs_per_track = 32; 2333116429Ssimokawa } 2334116429Ssimokawa secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2335116429Ssimokawa ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2336116429Ssimokawa ccb->ccb_h.status = CAM_REQ_CMP; 2337116429Ssimokawa#else 2338116351Snjl cam_calc_geometry(ccg, /*extended*/1); 2339116429Ssimokawa#endif 2340103285Sikob xpt_done(ccb); 2341103285Sikob break; 2342103285Sikob } 2343103285Sikob case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2344103285Sikob { 2345103285Sikob 2346103285SikobSBP_DEBUG(1) 2347103285Sikob printf("%s:%d:XPT_RESET_BUS: \n", 2348103285Sikob device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); 2349103285SikobEND_DEBUG 2350103285Sikob 2351103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2352103285Sikob xpt_done(ccb); 2353103285Sikob break; 2354103285Sikob } 2355103285Sikob case XPT_PATH_INQ: /* Path routing inquiry */ 2356103285Sikob { 2357103285Sikob struct ccb_pathinq *cpi = &ccb->cpi; 2358103285Sikob 2359103285SikobSBP_DEBUG(1) 2360103285Sikob printf("%s:%d:%d XPT_PATH_INQ:.\n", 2361103285Sikob device_get_nameunit(sbp->fd.dev), 2362103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2363103285SikobEND_DEBUG 2364103285Sikob cpi->version_num = 1; /* XXX??? */ 2365111615Ssimokawa cpi->hba_inquiry = PI_TAG_ABLE; 2366103285Sikob cpi->target_sprt = 0; 2367111199Ssimokawa cpi->hba_misc = PIM_NOBUSRESET; 2368103285Sikob cpi->hba_eng_cnt = 0; 2369103285Sikob cpi->max_target = SBP_NUM_TARGETS - 1; 2370103285Sikob cpi->max_lun = SBP_NUM_LUNS - 1; 2371103285Sikob cpi->initiator_id = SBP_INITIATOR; 2372103285Sikob cpi->bus_id = sim->bus_id; 2373103285Sikob cpi->base_transfer_speed = 400 * 1000 / 8; 2374103285Sikob strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2375103285Sikob strncpy(cpi->hba_vid, "SBP", HBA_IDLEN); 2376103285Sikob strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); 2377103285Sikob cpi->unit_number = sim->unit_number; 2378103285Sikob 2379103285Sikob cpi->ccb_h.status = CAM_REQ_CMP; 2380103285Sikob xpt_done(ccb); 2381103285Sikob break; 2382103285Sikob } 2383103285Sikob case XPT_GET_TRAN_SETTINGS: 2384103285Sikob { 2385103285Sikob struct ccb_trans_settings *cts = &ccb->cts; 2386103285SikobSBP_DEBUG(1) 2387103285Sikob printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", 2388103285Sikob device_get_nameunit(sbp->fd.dev), 2389103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2390103285SikobEND_DEBUG 2391111615Ssimokawa /* Enable disconnect and tagged queuing */ 2392103285Sikob cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 2393111615Ssimokawa cts->flags = CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB; 2394103285Sikob 2395103285Sikob cts->ccb_h.status = CAM_REQ_CMP; 2396103285Sikob xpt_done(ccb); 2397103285Sikob break; 2398103285Sikob } 2399103285Sikob case XPT_ABORT: 2400103285Sikob ccb->ccb_h.status = CAM_UA_ABORT; 2401103285Sikob xpt_done(ccb); 2402103285Sikob break; 2403111615Ssimokawa case XPT_SET_TRAN_SETTINGS: 2404111615Ssimokawa /* XXX */ 2405103285Sikob default: 2406103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2407103285Sikob xpt_done(ccb); 2408103285Sikob break; 2409103285Sikob } 2410103285Sikob return; 2411103285Sikob} 2412103285Sikob 2413103285Sikobstatic void 2414103285Sikobsbp_action(struct cam_sim *sim, union ccb *ccb) 2415103285Sikob{ 2416103285Sikob int s; 2417103285Sikob 2418103285Sikob s = splfw(); 2419103285Sikob sbp_action1(sim, ccb); 2420103285Sikob splx(s); 2421103285Sikob} 2422103285Sikob 2423103285Sikobstatic void 2424103285Sikobsbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error) 2425103285Sikob{ 2426103285Sikob int i; 2427103285Sikob struct sbp_ocb *ocb; 2428103285Sikob struct sbp_ocb *prev; 2429105633Ssimokawa bus_dma_segment_t *s; 2430103285Sikob 2431103285Sikob if (error) 2432103285Sikob printf("sbp_execute_ocb: error=%d\n", error); 2433103285Sikob 2434103285Sikob ocb = (struct sbp_ocb *)arg; 2435113584Ssimokawa 2436113584SsimokawaSBP_DEBUG(1) 2437113584Ssimokawa printf("sbp_execute_ocb: seg %d", seg); 2438113584Ssimokawa for (i = 0; i < seg; i++) 2439113584Ssimokawa#if __FreeBSD_version >= 500000 2440113972Ssimokawa printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr, 2441113972Ssimokawa (uintmax_t)segments[i].ds_len); 2442113584Ssimokawa#else 2443113972Ssimokawa printf(", %x:%d", segments[i].ds_addr, segments[i].ds_len); 2444113584Ssimokawa#endif 2445113584Ssimokawa printf("\n"); 2446113584SsimokawaEND_DEBUG 2447113584Ssimokawa 2448103285Sikob if (seg == 1) { 2449103285Sikob /* direct pointer */ 2450113474Ssimokawa s = &segments[0]; 2451113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2452113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2453113474Ssimokawa ocb->orb[3] = htonl(s->ds_addr); 2454113474Ssimokawa ocb->orb[4] |= htonl(s->ds_len); 2455103285Sikob } else if(seg > 1) { 2456103285Sikob /* page table */ 2457103285Sikob for (i = 0; i < seg; i++) { 2458105633Ssimokawa s = &segments[i]; 2459108877SsimokawaSBP_DEBUG(0) 2460108877Ssimokawa /* XXX LSI Logic "< 16 byte" bug might be hit */ 2461105633Ssimokawa if (s->ds_len < 16) 2462105633Ssimokawa printf("sbp_execute_ocb: warning, " 2463108877Ssimokawa#if __FreeBSD_version >= 500000 2464106543Ssimokawa "segment length(%zd) is less than 16." 2465108877Ssimokawa#else 2466108877Ssimokawa "segment length(%d) is less than 16." 2467108877Ssimokawa#endif 2468105633Ssimokawa "(seg=%d/%d)\n", s->ds_len, i+1, seg); 2469108877SsimokawaEND_DEBUG 2470113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2471113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2472105633Ssimokawa ocb->ind_ptr[i].hi = htonl(s->ds_len << 16); 2473105633Ssimokawa ocb->ind_ptr[i].lo = htonl(s->ds_addr); 2474103285Sikob } 2475103285Sikob ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg); 2476103285Sikob } 2477103285Sikob 2478113584Ssimokawa if (seg > 0) 2479113584Ssimokawa bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap, 2480113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2481113584Ssimokawa BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 2482103285Sikob prev = sbp_enqueue_ocb(ocb->sdev, ocb); 2483113584Ssimokawa fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE); 2484111819Ssimokawa if (prev == NULL) 2485103285Sikob sbp_orb_pointer(ocb->sdev, ocb); 2486103285Sikob} 2487103285Sikob 2488103285Sikobstatic void 2489103285Sikobsbp_poll(struct cam_sim *sim) 2490103285Sikob{ 2491103285Sikob /* should call fwohci_intr? */ 2492103285Sikob return; 2493103285Sikob} 2494103285Sikobstatic struct sbp_ocb * 2495111615Ssimokawasbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status) 2496103285Sikob{ 2497103285Sikob struct sbp_ocb *ocb; 2498103285Sikob struct sbp_ocb *next; 2499103285Sikob int s = splfw(), order = 0; 2500103285Sikob int flags; 2501103285Sikob 2502103285Sikob for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) { 2503103285Sikob next = STAILQ_NEXT(ocb, ocb); 2504103285Sikob flags = ocb->flags; 2505103285SikobSBP_DEBUG(1) 2506110336Ssimokawa sbp_show_sdev_info(sdev, 2); 2507108712Ssimokawa#if __FreeBSD_version >= 500000 2508113972Ssimokawa printf("orb: 0x%jx next: 0x%x, flags %x\n", 2509113972Ssimokawa (uintmax_t)ocb->bus_addr, 2510108712Ssimokawa#else 2511108712Ssimokawa printf("orb: 0x%x next: 0x%lx, flags %x\n", 2512113972Ssimokawa ocb->bus_addr, 2513108712Ssimokawa#endif 2514113972Ssimokawa ntohl(ocb->orb[1]), flags); 2515103285SikobEND_DEBUG 2516111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 2517103285Sikob /* found */ 2518111819Ssimokawa STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); 2519103285Sikob if (ocb->ccb != NULL) 2520103285Sikob untimeout(sbp_timeout, (caddr_t)ocb, 2521103285Sikob ocb->ccb->ccb_h.timeout_ch); 2522113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2523113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, 2524113584Ssimokawa ocb->dmamap, 2525113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2526113584Ssimokawa BUS_DMASYNC_POSTREAD : 2527113584Ssimokawa BUS_DMASYNC_POSTWRITE); 2528113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, 2529113584Ssimokawa ocb->dmamap); 2530103285Sikob } 2531111819Ssimokawa if (next != NULL && sbp_status->src == 1) 2532111819Ssimokawa sbp_orb_pointer(sdev, next); 2533103285Sikob break; 2534111819Ssimokawa } else 2535111819Ssimokawa order ++; 2536103285Sikob } 2537103285Sikob splx(s); 2538103285SikobSBP_DEBUG(0) 2539103285Sikob if (ocb && order > 0) { 2540103285Sikob sbp_show_sdev_info(sdev, 2); 2541103285Sikob printf("unordered execution order:%d\n", order); 2542103285Sikob } 2543103285SikobEND_DEBUG 2544103285Sikob return (ocb); 2545103285Sikob} 2546103285Sikob 2547103285Sikobstatic struct sbp_ocb * 2548103285Sikobsbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2549103285Sikob{ 2550103285Sikob int s = splfw(); 2551103285Sikob struct sbp_ocb *prev; 2552103285Sikob 2553103285SikobSBP_DEBUG(2) 2554103285Sikob sbp_show_sdev_info(sdev, 2); 2555108712Ssimokawa#if __FreeBSD_version >= 500000 2556113972Ssimokawa printf("sbp_enqueue_ocb orb=0x%jx in physical memory\n", 2557113972Ssimokawa (uintmax_t)ocb->bus_addr); 2558108712Ssimokawa#else 2559113584Ssimokawa printf("sbp_enqueue_ocb orb=0x%x in physical memory\n", ocb->bus_addr); 2560108712Ssimokawa#endif 2561103285SikobEND_DEBUG 2562103285Sikob prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb); 2563103285Sikob STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb); 2564103285Sikob 2565103285Sikob if (ocb->ccb != NULL) 2566103285Sikob ocb->ccb->ccb_h.timeout_ch = timeout(sbp_timeout, (caddr_t)ocb, 2567103285Sikob (ocb->ccb->ccb_h.timeout * hz) / 1000); 2568103285Sikob 2569110579Ssimokawa if (prev != NULL ) { 2570103285SikobSBP_DEBUG(1) 2571108712Ssimokawa#if __FreeBSD_version >= 500000 2572113972Ssimokawa printf("linking chain 0x%jx -> 0x%jx\n", 2573113972Ssimokawa (uintmax_t)prev->bus_addr, (uintmax_t)ocb->bus_addr); 2574108712Ssimokawa#else 2575113972Ssimokawa printf("linking chain 0x%x -> 0x%x\n", prev->bus_addr, ocb->bus_addr); 2576108712Ssimokawa#endif 2577103285SikobEND_DEBUG 2578113584Ssimokawa prev->orb[1] = htonl(ocb->bus_addr); 2579103285Sikob prev->orb[0] = 0; 2580103285Sikob } 2581103285Sikob splx(s); 2582103285Sikob 2583103285Sikob return prev; 2584103285Sikob} 2585103285Sikob 2586103285Sikobstatic struct sbp_ocb * 2587113584Ssimokawasbp_get_ocb(struct sbp_dev *sdev) 2588103285Sikob{ 2589103285Sikob struct sbp_ocb *ocb; 2590103285Sikob int s = splfw(); 2591113584Ssimokawa ocb = STAILQ_FIRST(&sdev->free_ocbs); 2592103285Sikob if (ocb == NULL) { 2593103285Sikob printf("ocb shortage!!!\n"); 2594103285Sikob return NULL; 2595103285Sikob } 2596113584Ssimokawa STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb); 2597103285Sikob splx(s); 2598103285Sikob ocb->ccb = NULL; 2599103285Sikob return (ocb); 2600103285Sikob} 2601103285Sikob 2602103285Sikobstatic void 2603113584Ssimokawasbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2604103285Sikob{ 2605103285Sikob ocb->flags = 0; 2606103285Sikob ocb->ccb = NULL; 2607113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); 2608103285Sikob} 2609103285Sikob 2610103285Sikobstatic void 2611103285Sikobsbp_abort_ocb(struct sbp_ocb *ocb, int status) 2612103285Sikob{ 2613103285Sikob struct sbp_dev *sdev; 2614103285Sikob 2615103285Sikob sdev = ocb->sdev; 2616113584SsimokawaSBP_DEBUG(0) 2617103285Sikob sbp_show_sdev_info(sdev, 2); 2618111819Ssimokawa#if __FreeBSD_version >= 500000 2619113972Ssimokawa printf("sbp_abort_ocb 0x%jx\n", (uintmax_t)ocb->bus_addr); 2620111819Ssimokawa#else 2621113972Ssimokawa printf("sbp_abort_ocb 0x%x\n", ocb->bus_addr); 2622111819Ssimokawa#endif 2623113584SsimokawaEND_DEBUG 2624113584SsimokawaSBP_DEBUG(1) 2625105792Ssimokawa if (ocb->ccb != NULL) 2626105792Ssimokawa sbp_print_scsi_cmd(ocb); 2627103285SikobEND_DEBUG 2628113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2629113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap, 2630113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2631113584Ssimokawa BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 2632113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap); 2633113584Ssimokawa } 2634111819Ssimokawa if (ocb->ccb != NULL) { 2635110336Ssimokawa untimeout(sbp_timeout, (caddr_t)ocb, 2636110336Ssimokawa ocb->ccb->ccb_h.timeout_ch); 2637103285Sikob ocb->ccb->ccb_h.status = status; 2638103285Sikob xpt_done(ocb->ccb); 2639103285Sikob } 2640113584Ssimokawa sbp_free_ocb(sdev, ocb); 2641103285Sikob} 2642103285Sikob 2643103285Sikobstatic void 2644103285Sikobsbp_abort_all_ocbs(struct sbp_dev *sdev, int status) 2645103285Sikob{ 2646103285Sikob int s; 2647105792Ssimokawa struct sbp_ocb *ocb, *next; 2648105792Ssimokawa STAILQ_HEAD(, sbp_ocb) temp; 2649103285Sikob 2650103285Sikob s = splfw(); 2651105792Ssimokawa 2652105792Ssimokawa bcopy(&sdev->ocbs, &temp, sizeof(temp)); 2653105792Ssimokawa STAILQ_INIT(&sdev->ocbs); 2654105792Ssimokawa for (ocb = STAILQ_FIRST(&temp); ocb != NULL; ocb = next) { 2655105792Ssimokawa next = STAILQ_NEXT(ocb, ocb); 2656103285Sikob sbp_abort_ocb(ocb, status); 2657103285Sikob } 2658105792Ssimokawa 2659103285Sikob splx(s); 2660103285Sikob} 2661103285Sikob 2662103285Sikobstatic devclass_t sbp_devclass; 2663103285Sikob 2664103285Sikobstatic device_method_t sbp_methods[] = { 2665103285Sikob /* device interface */ 2666103285Sikob DEVMETHOD(device_identify, sbp_identify), 2667103285Sikob DEVMETHOD(device_probe, sbp_probe), 2668103285Sikob DEVMETHOD(device_attach, sbp_attach), 2669103285Sikob DEVMETHOD(device_detach, sbp_detach), 2670110145Ssimokawa DEVMETHOD(device_shutdown, sbp_shutdown), 2671103285Sikob 2672103285Sikob { 0, 0 } 2673103285Sikob}; 2674103285Sikob 2675103285Sikobstatic driver_t sbp_driver = { 2676103285Sikob "sbp", 2677103285Sikob sbp_methods, 2678103285Sikob sizeof(struct sbp_softc), 2679103285Sikob}; 2680103285SikobDRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0); 2681103285SikobMODULE_VERSION(sbp, 1); 2682103285SikobMODULE_DEPEND(sbp, firewire, 1, 1, 1); 2683103285SikobMODULE_DEPEND(sbp, cam, 1, 1, 1); 2684