sbp.c revision 114069
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 114069 2003-04-26 16:45:40Z 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 */ 261110336Ssimokawa#if 0 262103285Sikob#define SBP_DEV_LOGIN 1 /* to login */ 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, 271110336Ssimokawa#define SBP_DEV_TIMEOUT 1 272110336Ssimokawa flags:4; 273108503Ssimokawa u_int8_t type; 274108503Ssimokawa u_int16_t lun_id; 275111615Ssimokawa int freeze; 276103285Sikob struct cam_path *path; 277103285Sikob struct sbp_target *target; 278113584Ssimokawa struct fwdma_alloc dma; 279113584Ssimokawa struct sbp_login_res *login; 280111615Ssimokawa struct callout login_callout; 281113584Ssimokawa struct sbp_ocb *ocb; 282103285Sikob STAILQ_HEAD(, sbp_ocb) ocbs; 283113584Ssimokawa STAILQ_HEAD(, sbp_ocb) free_ocbs; 284103285Sikob char vendor[32]; 285103285Sikob char product[32]; 286103285Sikob char revision[10]; 287103285Sikob}; 288103285Sikob 289103285Sikobstruct sbp_target { 290103285Sikob int target_id; 291103285Sikob int num_lun; 292103285Sikob struct sbp_dev *luns; 293103285Sikob struct sbp_softc *sbp; 294103285Sikob struct fw_device *fwdev; 295103285Sikob u_int32_t mgm_hi, mgm_lo; 296111615Ssimokawa struct sbp_ocb *mgm_ocb_cur; 297111615Ssimokawa STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; 298111615Ssimokawa struct callout mgm_ocb_timeout; 299111615Ssimokawa#define SCAN_DELAY 2 300111615Ssimokawa struct callout scan_callout; 301113584Ssimokawa STAILQ_HEAD(, fw_xfer) xferlist; 302113584Ssimokawa int n_xfer; 303103285Sikob}; 304103285Sikob 305103285Sikobstruct sbp_softc { 306103285Sikob struct firewire_dev_comm fd; 307103285Sikob struct cam_sim *sim; 308111615Ssimokawa struct cam_path *path; 309103285Sikob struct sbp_target targets[SBP_NUM_TARGETS]; 310103285Sikob struct fw_bind fwb; 311103285Sikob bus_dma_tag_t dmat; 312111615Ssimokawa#define SBP_RESOURCE_SHORTAGE 0x10 313111615Ssimokawa unsigned char flags; 314103285Sikob}; 315103285Sikobstatic void sbp_post_explore __P((void *)); 316103285Sikobstatic void sbp_recv __P((struct fw_xfer *)); 317103285Sikobstatic void sbp_login_callback __P((struct fw_xfer *)); 318103285Sikobstatic void sbp_cmd_callback __P((struct fw_xfer *)); 319103285Sikobstatic void sbp_orb_pointer __P((struct sbp_dev *, struct sbp_ocb *)); 320103285Sikobstatic void sbp_execute_ocb __P((void *, bus_dma_segment_t *, int, int)); 321113584Ssimokawastatic void sbp_free_ocb __P((struct sbp_dev *, struct sbp_ocb *)); 322103285Sikobstatic void sbp_abort_ocb __P((struct sbp_ocb *, int)); 323103285Sikobstatic void sbp_abort_all_ocbs __P((struct sbp_dev *, int)); 324103285Sikobstatic struct fw_xfer * sbp_write_cmd __P((struct sbp_dev *, int, int)); 325113584Ssimokawastatic struct sbp_ocb * sbp_get_ocb __P((struct sbp_dev *)); 326103285Sikobstatic struct sbp_ocb * sbp_enqueue_ocb __P((struct sbp_dev *, struct sbp_ocb *)); 327111615Ssimokawastatic struct sbp_ocb * sbp_dequeue_ocb __P((struct sbp_dev *, struct sbp_status *)); 328110145Ssimokawastatic void sbp_cam_detach_target __P((struct sbp_target *)); 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)); 644114069Ssimokawa /* get firmware revision */ 645114069Ssimokawa reg = crom_search_key(cc, CSRKEY_FIRM_VER); 646114069Ssimokawa if (reg != NULL) 647114069Ssimokawa snprintf(sdev->revision, sizeof(sdev->revision), 648114069Ssimokawa "%06x", reg->val); 649114069Ssimokawa /* get product string */ 650114069Ssimokawa crom_search_key(cc, CSRKEY_MODEL); 651114069Ssimokawa crom_next(cc); 652114069Ssimokawa crom_parse_text(cc, sdev->product, sizeof(sdev->product)); 653103285Sikob} 654111615Ssimokawa 655103285Sikobstatic void 656111615Ssimokawasbp_login_callout(void *arg) 657103285Sikob{ 658111615Ssimokawa struct sbp_dev *sdev = (struct sbp_dev *)arg; 659111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL); 660111615Ssimokawa} 661111615Ssimokawa 662114069Ssimokawa#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ 663114069Ssimokawa && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) 664111615Ssimokawa 665111615Ssimokawastatic void 666111615Ssimokawasbp_probe_target(void *arg) 667111615Ssimokawa{ 668111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 669103285Sikob struct sbp_softc *sbp; 670103285Sikob struct sbp_dev *sdev; 671103285Sikob struct firewire_comm *fc; 672111615Ssimokawa int i, alive; 673103285Sikob 674111615Ssimokawa alive = SBP_FWDEV_ALIVE(target->fwdev); 675103285SikobSBP_DEBUG(1) 676103285Sikob printf("sbp_probe_target %d\n", target->target_id); 677103285Sikob if (!alive) 678103285Sikob printf("not alive\n"); 679103285SikobEND_DEBUG 680103285Sikob 681103285Sikob sbp = target->sbp; 682103285Sikob fc = target->sbp->fd.fc; 683111615Ssimokawa /* XXX untimeout mgm_ocb and dequeue */ 684103285Sikob for (i=0; i < target->num_lun; i++) { 685103285Sikob sdev = &target->luns[i]; 686103285Sikob if (alive && (sdev->status != SBP_DEV_DEAD)) { 687103285Sikob if (sdev->path != NULL) { 688103285Sikob xpt_freeze_devq(sdev->path, 1); 689111615Ssimokawa sdev->freeze ++; 690103285Sikob } 691111615Ssimokawa sbp_probe_lun(sdev); 692111615SsimokawaSBP_DEBUG(0) 693111615Ssimokawa sbp_show_sdev_info(sdev, 694111615Ssimokawa (sdev->status == SBP_DEV_RESET)); 695111615SsimokawaEND_DEBUG 696111615Ssimokawa 697111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 698103285Sikob switch (sdev->status) { 699110336Ssimokawa case SBP_DEV_RESET: 700103285Sikob /* new or revived target */ 701113584Ssimokawa if (auto_login) 702111615Ssimokawa sbp_login(sdev); 703103285Sikob break; 704111615Ssimokawa case SBP_DEV_TOATTACH: 705111615Ssimokawa case SBP_DEV_PROBE: 706111615Ssimokawa case SBP_DEV_ATTACHED: 707110336Ssimokawa case SBP_DEV_RETRY: 708110336Ssimokawa default: 709111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); 710110336Ssimokawa break; 711103285Sikob } 712103285Sikob } else { 713103285Sikob switch (sdev->status) { 714103285Sikob case SBP_DEV_ATTACHED: 715103285SikobSBP_DEBUG(0) 716103285Sikob /* the device has gone */ 717103285Sikob sbp_show_sdev_info(sdev, 2); 718103285Sikob printf("lost target\n"); 719103285SikobEND_DEBUG 720111615Ssimokawa if (sdev->path) { 721103285Sikob xpt_freeze_devq(sdev->path, 1); 722111615Ssimokawa sdev->freeze ++; 723111615Ssimokawa } 724103285Sikob sdev->status = SBP_DEV_RETRY; 725111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET); 726103285Sikob break; 727103285Sikob case SBP_DEV_PROBE: 728103285Sikob case SBP_DEV_TOATTACH: 729103285Sikob sdev->status = SBP_DEV_RESET; 730103285Sikob break; 731103285Sikob case SBP_DEV_RETRY: 732103285Sikob case SBP_DEV_RESET: 733103285Sikob case SBP_DEV_DEAD: 734103285Sikob break; 735103285Sikob } 736103285Sikob } 737103285Sikob } 738103285Sikob} 739103285Sikob 740103285Sikobstatic void 741113584Ssimokawasbp_post_busreset(void *arg) 742113584Ssimokawa{ 743113584Ssimokawa struct sbp_softc *sbp; 744113584Ssimokawa 745113584Ssimokawa sbp = (struct sbp_softc *)arg; 746113584SsimokawaSBP_DEBUG(0) 747113584Ssimokawa printf("sbp_post_busreset\n"); 748113584SsimokawaEND_DEBUG 749113584Ssimokawa} 750113584Ssimokawa 751113584Ssimokawastatic void 752103285Sikobsbp_post_explore(void *arg) 753103285Sikob{ 754103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)arg; 755103285Sikob struct sbp_target *target; 756103285Sikob struct fw_device *fwdev; 757103285Sikob int i, alive; 758103285Sikob 759111199SsimokawaSBP_DEBUG(0) 760111199Ssimokawa printf("sbp_post_explore (sbp_cold=%d)\n", sbp_cold); 761103285SikobEND_DEBUG 762111615Ssimokawa#if 0 /* 763111615Ssimokawa * XXX don't let CAM the bus rest. CAM tries to do something with 764111615Ssimokawa * freezed (DEV_RETRY) devices 765111615Ssimokawa */ 766111615Ssimokawa xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); 767103285Sikob#endif 768111199Ssimokawa if (sbp_cold > 0) 769111199Ssimokawa sbp_cold --; 770111615Ssimokawa 771103285Sikob /* Gabage Collection */ 772103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 773103285Sikob target = &sbp->targets[i]; 774110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) 775110193Ssimokawa if (target->fwdev == NULL || target->fwdev == fwdev) 776110193Ssimokawa break; 777103285Sikob if(fwdev == NULL){ 778103285Sikob /* device has removed in lower driver */ 779110145Ssimokawa sbp_cam_detach_target(target); 780110145Ssimokawa if (target->luns != NULL) 781110145Ssimokawa free(target->luns, M_SBP); 782110145Ssimokawa target->num_lun = 0;; 783110145Ssimokawa target->luns = NULL; 784110145Ssimokawa target->fwdev = NULL; 785103285Sikob } 786103285Sikob } 787103285Sikob /* traverse device list */ 788110193Ssimokawa STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) { 789103285SikobSBP_DEBUG(0) 790103285Sikob printf("sbp_post_explore: EUI:%08x%08x ", 791103285Sikob fwdev->eui.hi, fwdev->eui.lo); 792114069Ssimokawa if (fwdev->status != FWDEVATTACHED) 793103285Sikob printf("not attached, state=%d.\n", fwdev->status); 794114069Ssimokawa else 795114069Ssimokawa printf("attached\n"); 796103285SikobEND_DEBUG 797111615Ssimokawa alive = SBP_FWDEV_ALIVE(fwdev); 798103285Sikob for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){ 799103285Sikob target = &sbp->targets[i]; 800103285Sikob if(target->fwdev == fwdev ) { 801103285Sikob /* known target */ 802103285Sikob break; 803103285Sikob } 804103285Sikob } 805103285Sikob if(i == SBP_NUM_TARGETS){ 806103285Sikob if (alive) { 807103285Sikob /* new target */ 808103285Sikob target = sbp_alloc_target(sbp, fwdev); 809103285Sikob if (target == NULL) 810103285Sikob continue; 811103285Sikob } else { 812103285Sikob continue; 813103285Sikob } 814103285Sikob } 815111615Ssimokawa sbp_probe_target((void *)target); 816103285Sikob } 817103285Sikob} 818103285Sikob 819103285Sikob#if NEED_RESPONSE 820103285Sikobstatic void 821103285Sikobsbp_loginres_callback(struct fw_xfer *xfer){ 822113584Ssimokawa int s; 823103285Sikob struct sbp_dev *sdev; 824103285Sikob sdev = (struct sbp_dev *)xfer->sc; 825113584SsimokawaSBP_DEBUG(1) 826103285Sikob sbp_show_sdev_info(sdev, 2); 827103285Sikob printf("sbp_loginres_callback\n"); 828103285SikobEND_DEBUG 829113584Ssimokawa /* recycle */ 830113584Ssimokawa s = splfw(); 831113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link); 832113584Ssimokawa splx(s); 833103285Sikob return; 834103285Sikob} 835103285Sikob#endif 836103285Sikob 837113584Ssimokawastatic __inline void 838113584Ssimokawasbp_xfer_free(struct fw_xfer *xfer) 839113584Ssimokawa{ 840113584Ssimokawa struct sbp_dev *sdev; 841113584Ssimokawa int s; 842113584Ssimokawa 843113584Ssimokawa sdev = (struct sbp_dev *)xfer->sc; 844113584Ssimokawa fw_xfer_unload(xfer); 845113584Ssimokawa s = splfw(); 846113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); 847113584Ssimokawa splx(s); 848113584Ssimokawa} 849113584Ssimokawa 850103285Sikobstatic void 851103285Sikobsbp_login_callback(struct fw_xfer *xfer) 852103285Sikob{ 853103285SikobSBP_DEBUG(1) 854103285Sikob struct sbp_dev *sdev; 855103285Sikob sdev = (struct sbp_dev *)xfer->sc; 856103285Sikob sbp_show_sdev_info(sdev, 2); 857103285Sikob printf("sbp_login_callback\n"); 858103285SikobEND_DEBUG 859113584Ssimokawa sbp_xfer_free(xfer); 860103285Sikob return; 861103285Sikob} 862103285Sikob 863103285Sikobstatic void 864103285Sikobsbp_cmd_callback(struct fw_xfer *xfer) 865103285Sikob{ 866103285SikobSBP_DEBUG(2) 867103285Sikob struct sbp_dev *sdev; 868103285Sikob sdev = (struct sbp_dev *)xfer->sc; 869103285Sikob sbp_show_sdev_info(sdev, 2); 870103285Sikob printf("sbp_cmd_callback\n"); 871103285SikobEND_DEBUG 872113584Ssimokawa sbp_xfer_free(xfer); 873103285Sikob return; 874103285Sikob} 875103285Sikob 876111615Ssimokawastatic struct sbp_dev * 877111615Ssimokawasbp_next_dev(struct sbp_target *target, int lun) 878111615Ssimokawa{ 879111615Ssimokawa struct sbp_dev *sdev; 880111615Ssimokawa int i; 881111615Ssimokawa 882111615Ssimokawa for (i = lun, sdev = &target->luns[lun]; 883111615Ssimokawa i < target->num_lun; i++, sdev++) { 884111615Ssimokawa if (sdev->status == SBP_DEV_PROBE) 885111615Ssimokawa break; 886111615Ssimokawa } 887111615Ssimokawa if (i >= target->num_lun) 888111615Ssimokawa return(NULL); 889111615Ssimokawa return(sdev); 890111615Ssimokawa} 891111615Ssimokawa 892111615Ssimokawa#define SCAN_PRI 1 893103285Sikobstatic void 894111615Ssimokawasbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb) 895103285Sikob{ 896111615Ssimokawa struct sbp_target *target; 897103285Sikob struct sbp_dev *sdev; 898111615Ssimokawa 899103285Sikob sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr; 900111615Ssimokawa target = sdev->target; 901110269SsimokawaSBP_DEBUG(0) 902103285Sikob sbp_show_sdev_info(sdev, 2); 903111615Ssimokawa printf("sbp_cam_scan_lun\n"); 904103285SikobEND_DEBUG 905111615Ssimokawa if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 906111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 907111615Ssimokawa } else { 908111615Ssimokawa sbp_show_sdev_info(sdev, 2); 909111615Ssimokawa printf("scan failed\n"); 910111615Ssimokawa } 911111615Ssimokawa sdev = sbp_next_dev(target, sdev->lun_id + 1); 912111615Ssimokawa if (sdev == NULL) { 913111615Ssimokawa free(ccb, M_SBP); 914111615Ssimokawa return; 915111615Ssimokawa } 916111615Ssimokawa /* reuse ccb */ 917111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 918111615Ssimokawa ccb->ccb_h.ccb_sdev_ptr = sdev; 919111615Ssimokawa xpt_action(ccb); 920111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 921111615Ssimokawa sdev->freeze = 1; 922103285Sikob} 923103285Sikob 924103285Sikobstatic void 925111615Ssimokawasbp_cam_scan_target(void *arg) 926103285Sikob{ 927111615Ssimokawa struct sbp_target *target = (struct sbp_target *)arg; 928111615Ssimokawa struct sbp_dev *sdev; 929110798Ssimokawa union ccb *ccb; 930103285Sikob 931111615Ssimokawa sdev = sbp_next_dev(target, 0); 932111615Ssimokawa if (sdev == NULL) { 933111615Ssimokawa printf("sbp_cam_scan_target: nothing to do for target%d\n", 934111615Ssimokawa target->target_id); 935110798Ssimokawa return; 936110798Ssimokawa } 937103285SikobSBP_DEBUG(0) 938103285Sikob sbp_show_sdev_info(sdev, 2); 939111615Ssimokawa printf("sbp_cam_scan_target\n"); 940103285SikobEND_DEBUG 941111615Ssimokawa ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO); 942111615Ssimokawa if (ccb == NULL) { 943111615Ssimokawa printf("sbp_cam_scan_target: malloc failed\n"); 944111615Ssimokawa return; 945111615Ssimokawa } 946111615Ssimokawa xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI); 947103285Sikob ccb->ccb_h.func_code = XPT_SCAN_LUN; 948111615Ssimokawa ccb->ccb_h.cbfcnp = sbp_cam_scan_lun; 949111615Ssimokawa ccb->ccb_h.flags |= CAM_DEV_QFREEZE; 950103285Sikob ccb->crcn.flags = CAM_FLAG_NONE; 951103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 952103285Sikob 953103285Sikob /* The scan is in progress now. */ 954111040Ssimokawa xpt_action(ccb); 955111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 956111615Ssimokawa sdev->freeze = 1; 957103285Sikob} 958103285Sikob 959111615Ssimokawastatic __inline void 960111615Ssimokawasbp_scan_dev(struct sbp_dev *sdev) 961111615Ssimokawa{ 962111040Ssimokawa sdev->status = SBP_DEV_PROBE; 963111615Ssimokawa callout_reset(&sdev->target->scan_callout, SCAN_DELAY * hz, 964111615Ssimokawa sbp_cam_scan_target, (void *)sdev->target); 965103285Sikob} 966103285Sikob 967103285Sikobstatic void 968103285Sikobsbp_do_attach(struct fw_xfer *xfer) 969103285Sikob{ 970103285Sikob struct sbp_dev *sdev; 971111615Ssimokawa struct sbp_target *target; 972111615Ssimokawa struct sbp_softc *sbp; 973103285Sikob 974103285Sikob sdev = (struct sbp_dev *)xfer->sc; 975111615Ssimokawa target = sdev->target; 976111615Ssimokawa sbp = target->sbp; 977103285SikobSBP_DEBUG(0) 978103285Sikob sbp_show_sdev_info(sdev, 2); 979103285Sikob printf("sbp_do_attach\n"); 980103285SikobEND_DEBUG 981113584Ssimokawa sbp_xfer_free(xfer); 982111199Ssimokawa 983103285Sikob if (sdev->path == NULL) 984103285Sikob xpt_create_path(&sdev->path, xpt_periph, 985111615Ssimokawa cam_sim_path(target->sbp->sim), 986111615Ssimokawa target->target_id, sdev->lun_id); 987103285Sikob 988111199Ssimokawa /* 989111199Ssimokawa * Let CAM scan the bus if we are in the boot process. 990111199Ssimokawa * XXX xpt_scan_bus cannot detect LUN larger than 0 991111199Ssimokawa * if LUN 0 doesn't exists. 992111199Ssimokawa */ 993111199Ssimokawa if (sbp_cold > 0) { 994111615Ssimokawa sdev->status = SBP_DEV_ATTACHED; 995111199Ssimokawa return; 996111199Ssimokawa } 997111199Ssimokawa 998111615Ssimokawa sbp_scan_dev(sdev); 999103285Sikob return; 1000103285Sikob} 1001103285Sikob 1002103285Sikobstatic void 1003103285Sikobsbp_agent_reset_callback(struct fw_xfer *xfer) 1004103285Sikob{ 1005103285Sikob struct sbp_dev *sdev; 1006103285Sikob 1007103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1008103285SikobSBP_DEBUG(1) 1009103285Sikob sbp_show_sdev_info(sdev, 2); 1010103285Sikob printf("sbp_cmd_callback\n"); 1011103285SikobEND_DEBUG 1012113584Ssimokawa sbp_xfer_free(xfer); 1013111615Ssimokawa if (sdev->path) { 1014111615Ssimokawa xpt_release_devq(sdev->path, sdev->freeze, TRUE); 1015111615Ssimokawa sdev->freeze = 0; 1016111615Ssimokawa } 1017103285Sikob} 1018103285Sikob 1019103285Sikobstatic void 1020110336Ssimokawasbp_agent_reset(struct sbp_dev *sdev) 1021103285Sikob{ 1022103285Sikob struct fw_xfer *xfer; 1023103285Sikob struct fw_pkt *fp; 1024103285Sikob 1025103285SikobSBP_DEBUG(0) 1026103285Sikob sbp_show_sdev_info(sdev, 2); 1027103285Sikob printf("sbp_agent_reset\n"); 1028103285SikobEND_DEBUG 1029103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04); 1030103285Sikob if (xfer == NULL) 1031103285Sikob return; 1032110336Ssimokawa if (sdev->status == SBP_DEV_ATTACHED) 1033110336Ssimokawa xfer->act.hand = sbp_agent_reset_callback; 1034110336Ssimokawa else 1035103285Sikob xfer->act.hand = sbp_do_attach; 1036103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1037103285Sikob fp->mode.wreqq.data = htonl(0xf); 1038103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1039111615Ssimokawa sbp_abort_all_ocbs(sdev, CAM_BDR_SENT); 1040103285Sikob} 1041103285Sikob 1042103285Sikobstatic void 1043103285Sikobsbp_busy_timeout_callback(struct fw_xfer *xfer) 1044103285Sikob{ 1045103285Sikob struct sbp_dev *sdev; 1046103285Sikob 1047103285Sikob sdev = (struct sbp_dev *)xfer->sc; 1048103285SikobSBP_DEBUG(1) 1049103285Sikob sbp_show_sdev_info(sdev, 2); 1050110336Ssimokawa printf("sbp_busy_timeout_callback\n"); 1051103285SikobEND_DEBUG 1052113584Ssimokawa sbp_xfer_free(xfer); 1053110336Ssimokawa sbp_agent_reset(sdev); 1054103285Sikob} 1055103285Sikob 1056103285Sikobstatic void 1057103285Sikobsbp_busy_timeout(struct sbp_dev *sdev) 1058103285Sikob{ 1059103285Sikob struct fw_pkt *fp; 1060103285Sikob struct fw_xfer *xfer; 1061103285SikobSBP_DEBUG(0) 1062103285Sikob sbp_show_sdev_info(sdev, 2); 1063103285Sikob printf("sbp_busy_timeout\n"); 1064103285SikobEND_DEBUG 1065103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 1066103285Sikob 1067103285Sikob xfer->act.hand = sbp_busy_timeout_callback; 1068103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1069113584Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 1070113584Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; 1071110129Ssimokawa fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf); 1072103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1073103285Sikob} 1074103285Sikob 1075103285Sikob#if 0 1076103285Sikobstatic void 1077103285Sikobsbp_reset_start(struct sbp_dev *sdev) 1078103285Sikob{ 1079103285Sikob struct fw_xfer *xfer; 1080103285Sikob struct fw_pkt *fp; 1081103285Sikob 1082103285SikobSBP_DEBUG(0) 1083103285Sikob sbp_show_sdev_info(sdev, 2); 1084103285Sikob printf("sbp_reset_start\n"); 1085103285SikobEND_DEBUG 1086103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); 1087103285Sikob 1088103285Sikob xfer->act.hand = sbp_busy_timeout; 1089103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1090113584Ssimokawa fp->mode.wreqq.dest_hi = 0xffff; 1091113584Ssimokawa fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 1092103285Sikob fp->mode.wreqq.data = htonl(0xf); 1093103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1094103285Sikob} 1095103285Sikob#endif 1096103285Sikob 1097103285Sikobstatic void 1098103285Sikobsbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) 1099103285Sikob{ 1100103285Sikob struct fw_xfer *xfer; 1101103285Sikob struct fw_pkt *fp; 1102103285SikobSBP_DEBUG(2) 1103103285Sikob sbp_show_sdev_info(sdev, 2); 1104103285Sikob printf("sbp_orb_pointer\n"); 1105103285SikobEND_DEBUG 1106103285Sikob 1107103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0x08); 1108103285Sikob if (xfer == NULL) 1109103285Sikob return; 1110103285Sikob xfer->act.hand = sbp_cmd_callback; 1111103285Sikob 1112103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1113113584Ssimokawa fp->mode.wreqb.len = 8; 1114103285Sikob fp->mode.wreqb.extcode = 0; 1115103285Sikob fp->mode.wreqb.payload[0] = 1116103285Sikob htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); 1117113584Ssimokawa fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr); 1118103285Sikob 1119103285Sikob if(fw_asyreq(xfer->fc, -1, xfer) != 0){ 1120113584Ssimokawa sbp_xfer_free(xfer); 1121103285Sikob ocb->ccb->ccb_h.status = CAM_REQ_INVALID; 1122103285Sikob xpt_done(ocb->ccb); 1123103285Sikob } 1124103285Sikob} 1125103285Sikob 1126111819Ssimokawa#if 0 1127103285Sikobstatic void 1128103285Sikobsbp_doorbell(struct sbp_dev *sdev) 1129103285Sikob{ 1130103285Sikob struct fw_xfer *xfer; 1131103285Sikob struct fw_pkt *fp; 1132103285SikobSBP_DEBUG(1) 1133103285Sikob sbp_show_sdev_info(sdev, 2); 1134103285Sikob printf("sbp_doorbell\n"); 1135103285SikobEND_DEBUG 1136103285Sikob 1137103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x10); 1138103285Sikob if (xfer == NULL) 1139103285Sikob return; 1140103285Sikob xfer->act.hand = sbp_cmd_callback; 1141103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1142103285Sikob fp->mode.wreqq.data = htonl(0xf); 1143103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1144103285Sikob} 1145111819Ssimokawa#endif 1146103285Sikob 1147103285Sikobstatic struct fw_xfer * 1148103285Sikobsbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) 1149103285Sikob{ 1150103285Sikob struct fw_xfer *xfer; 1151103285Sikob struct fw_pkt *fp; 1152113584Ssimokawa struct sbp_target *target; 1153113584Ssimokawa int s, new = 0; 1154103285Sikob 1155113584Ssimokawa target = sdev->target; 1156113584Ssimokawa s = splfw(); 1157113584Ssimokawa xfer = STAILQ_FIRST(&target->xferlist); 1158113584Ssimokawa if (xfer == NULL) { 1159113584Ssimokawa if (target->n_xfer > 5 /* XXX */) { 1160113584Ssimokawa printf("sbp: no more xfer for this target\n"); 1161113584Ssimokawa splx(s); 1162113584Ssimokawa return(NULL); 1163113584Ssimokawa } 1164113584Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 24, 12); 1165113584Ssimokawa if(xfer == NULL){ 1166113584Ssimokawa printf("sbp: fw_xfer_alloc_buf failed\n"); 1167113584Ssimokawa splx(s); 1168113584Ssimokawa return NULL; 1169113584Ssimokawa } 1170113584Ssimokawa target->n_xfer ++; 1171113584Ssimokawa if (debug) 1172113584Ssimokawa printf("sbp: alloc %d xfer\n", target->n_xfer); 1173113584Ssimokawa new = 1; 1174113584Ssimokawa } else { 1175113584Ssimokawa STAILQ_REMOVE_HEAD(&target->xferlist, link); 1176103285Sikob } 1177113584Ssimokawa splx(s); 1178113584Ssimokawa 1179113584Ssimokawa microtime(&xfer->tv); 1180113584Ssimokawa 1181103285Sikob if (tcode == FWTCODE_WREQQ) 1182103285Sikob xfer->send.len = 16; 1183103285Sikob else 1184103285Sikob xfer->send.len = 24; 1185113584Ssimokawa xfer->recv.len = 12; 1186103285Sikob 1187113584Ssimokawa if (new) { 1188113584Ssimokawa xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1189113584Ssimokawa xfer->fc = sdev->target->sbp->fd.fc; 1190113584Ssimokawa xfer->retry_req = fw_asybusy; 1191103285Sikob } 1192103285Sikob xfer->sc = (caddr_t)sdev; 1193103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1194113584Ssimokawa fp->mode.wreqq.dest_hi = sdev->login->cmd_hi; 1195113584Ssimokawa fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset; 1196103285Sikob fp->mode.wreqq.tlrt = 0; 1197103285Sikob fp->mode.wreqq.tcode = tcode; 1198103285Sikob fp->mode.wreqq.pri = 0; 1199103285Sikob xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst; 1200113584Ssimokawa fp->mode.wreqq.dst = xfer->dst; 1201103285Sikob 1202103285Sikob return xfer; 1203103285Sikob 1204103285Sikob} 1205103285Sikob 1206103285Sikobstatic void 1207111615Ssimokawasbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) 1208103285Sikob{ 1209103285Sikob struct fw_xfer *xfer; 1210103285Sikob struct fw_pkt *fp; 1211103285Sikob struct sbp_ocb *ocb; 1212111615Ssimokawa struct sbp_target *target; 1213103285Sikob int s, nid; 1214103285Sikob 1215111615Ssimokawa target = sdev->target; 1216111615Ssimokawa nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; 1217111615Ssimokawa 1218111615Ssimokawa s = splfw(); 1219111615Ssimokawa if (func == ORB_FUN_RUNQUEUE) { 1220111615Ssimokawa ocb = STAILQ_FIRST(&target->mgm_ocb_queue); 1221111615Ssimokawa if (target->mgm_ocb_cur != NULL || ocb == NULL) { 1222111615Ssimokawa splx(s); 1223111615Ssimokawa return; 1224111615Ssimokawa } 1225111615Ssimokawa STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); 1226111615Ssimokawa goto start; 1227111615Ssimokawa } 1228113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) { 1229103285Sikob splx(s); 1230103285Sikob return; 1231103285Sikob } 1232103285Sikob ocb->flags = OCB_ACT_MGM; 1233103285Sikob ocb->sdev = sdev; 1234103285Sikob 1235103285Sikob bzero((void *)(uintptr_t)(volatile void *)ocb->orb, sizeof(ocb->orb)); 1236103285Sikob ocb->orb[6] = htonl((nid << 16) | SBP_BIND_HI); 1237103285Sikob ocb->orb[7] = htonl(SBP_DEV2ADDR( 1238111615Ssimokawa device_get_unit(target->sbp->fd.dev), 1239111615Ssimokawa target->target_id, 1240103285Sikob sdev->lun_id)); 1241103285Sikob 1242107653SsimokawaSBP_DEBUG(0) 1243103285Sikob sbp_show_sdev_info(sdev, 2); 1244103285Sikob printf("%s\n", orb_fun_name[(func>>16)&0xf]); 1245107653SsimokawaEND_DEBUG 1246103285Sikob switch (func) { 1247103285Sikob case ORB_FUN_LGI: 1248103285Sikob ocb->orb[2] = htonl(nid << 16); 1249113584Ssimokawa ocb->orb[3] = htonl(sdev->dma.bus_addr); 1250103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id); 1251113584Ssimokawa ocb->orb[5] = htonl(SBP_LOGIN_SIZE); 1252113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD); 1253103285Sikob break; 1254110336Ssimokawa case ORB_FUN_ATA: 1255111615Ssimokawa ocb->orb[0] = htonl((0 << 16) | 0); 1256113584Ssimokawa ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff); 1257110336Ssimokawa /* fall through */ 1258103285Sikob case ORB_FUN_RCN: 1259103285Sikob case ORB_FUN_LGO: 1260103285Sikob case ORB_FUN_LUR: 1261103285Sikob case ORB_FUN_RST: 1262103285Sikob case ORB_FUN_ATS: 1263113584Ssimokawa ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id); 1264103285Sikob break; 1265103285Sikob } 1266103285Sikob 1267111615Ssimokawa if (target->mgm_ocb_cur != NULL) { 1268111615Ssimokawa /* there is a standing ORB */ 1269111615Ssimokawa STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); 1270111615Ssimokawa splx(s); 1271111615Ssimokawa return; 1272111615Ssimokawa } 1273111615Ssimokawastart: 1274111615Ssimokawa target->mgm_ocb_cur = ocb; 1275111615Ssimokawa splx(s); 1276111615Ssimokawa 1277111615Ssimokawa callout_reset(&target->mgm_ocb_timeout, 5*hz, 1278111615Ssimokawa sbp_timeout, (caddr_t)ocb); 1279103285Sikob xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); 1280103285Sikob if(xfer == NULL){ 1281103285Sikob return; 1282103285Sikob } 1283103285Sikob xfer->act.hand = sbp_login_callback; 1284103285Sikob 1285103285Sikob fp = (struct fw_pkt *)xfer->send.buf; 1286113584Ssimokawa fp->mode.wreqb.dest_hi = sdev->target->mgm_hi; 1287113584Ssimokawa fp->mode.wreqb.dest_lo = sdev->target->mgm_lo; 1288113584Ssimokawa fp->mode.wreqb.len = 8; 1289103285Sikob fp->mode.wreqb.extcode = 0; 1290108503Ssimokawa fp->mode.wreqb.payload[0] = htonl(nid << 16); 1291113584Ssimokawa fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr); 1292103285Sikob 1293103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1294103285Sikob} 1295103285Sikob 1296103285Sikobstatic void 1297105792Ssimokawasbp_print_scsi_cmd(struct sbp_ocb *ocb) 1298103285Sikob{ 1299103285Sikob struct ccb_scsiio *csio; 1300103285Sikob 1301103285Sikob csio = &ocb->ccb->csio; 1302103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 1303103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 1304103285Sikob ", flags: 0x%02x, " 1305103285Sikob "%db cmd/%db data/%db sense\n", 1306103285Sikob device_get_nameunit(ocb->sdev->target->sbp->fd.dev), 1307103285Sikob ocb->ccb->ccb_h.target_id, ocb->ccb->ccb_h.target_lun, 1308103285Sikob csio->cdb_io.cdb_bytes[0], 1309103285Sikob csio->cdb_io.cdb_bytes[1], 1310103285Sikob csio->cdb_io.cdb_bytes[2], 1311103285Sikob csio->cdb_io.cdb_bytes[3], 1312103285Sikob csio->cdb_io.cdb_bytes[4], 1313103285Sikob csio->cdb_io.cdb_bytes[5], 1314103285Sikob csio->cdb_io.cdb_bytes[6], 1315103285Sikob csio->cdb_io.cdb_bytes[7], 1316103285Sikob csio->cdb_io.cdb_bytes[8], 1317103285Sikob csio->cdb_io.cdb_bytes[9], 1318103285Sikob ocb->ccb->ccb_h.flags & CAM_DIR_MASK, 1319103285Sikob csio->cdb_len, csio->dxfer_len, 1320103285Sikob csio->sense_len); 1321105792Ssimokawa} 1322105792Ssimokawa 1323105792Ssimokawastatic void 1324105792Ssimokawasbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb) 1325105792Ssimokawa{ 1326105792Ssimokawa struct sbp_cmd_status *sbp_cmd_status; 1327105792Ssimokawa struct scsi_sense_data *sense; 1328105792Ssimokawa 1329105792Ssimokawa sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data; 1330105792Ssimokawa sense = &ocb->ccb->csio.sense_data; 1331105792Ssimokawa 1332105792SsimokawaSBP_DEBUG(0) 1333105792Ssimokawa sbp_print_scsi_cmd(ocb); 1334103285Sikob /* XXX need decode status */ 1335103285Sikob sbp_show_sdev_info(ocb->sdev, 2); 1336113584Ssimokawa printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", 1337103285Sikob sbp_cmd_status->status, 1338103285Sikob sbp_cmd_status->sfmt, 1339103285Sikob sbp_cmd_status->valid, 1340103285Sikob sbp_cmd_status->s_key, 1341103285Sikob sbp_cmd_status->s_code, 1342103285Sikob sbp_cmd_status->s_qlfr, 1343103285Sikob sbp_status->len 1344103285Sikob ); 1345103285SikobEND_DEBUG 1346103285Sikob 1347110071Ssimokawa switch (sbp_cmd_status->status) { 1348110071Ssimokawa case SCSI_STATUS_CHECK_COND: 1349110071Ssimokawa case SCSI_STATUS_BUSY: 1350110071Ssimokawa case SCSI_STATUS_CMD_TERMINATED: 1351103285Sikob if(sbp_cmd_status->sfmt == SBP_SFMT_CURR){ 1352103285Sikob sense->error_code = SSD_CURRENT_ERROR; 1353103285Sikob }else{ 1354103285Sikob sense->error_code = SSD_DEFERRED_ERROR; 1355103285Sikob } 1356103285Sikob if(sbp_cmd_status->valid) 1357103285Sikob sense->error_code |= SSD_ERRCODE_VALID; 1358103285Sikob sense->flags = sbp_cmd_status->s_key; 1359103285Sikob if(sbp_cmd_status->mark) 1360103285Sikob sense->flags |= SSD_FILEMARK; 1361103285Sikob if(sbp_cmd_status->eom) 1362103285Sikob sense->flags |= SSD_EOM; 1363103285Sikob if(sbp_cmd_status->ill_len) 1364103285Sikob sense->flags |= SSD_ILI; 1365103285Sikob sense->info[0] = ntohl(sbp_cmd_status->info) & 0xff; 1366103285Sikob sense->info[1] =(ntohl(sbp_cmd_status->info) >> 8) & 0xff; 1367103285Sikob sense->info[2] =(ntohl(sbp_cmd_status->info) >> 16) & 0xff; 1368103285Sikob sense->info[3] =(ntohl(sbp_cmd_status->info) >> 24) & 0xff; 1369103285Sikob if (sbp_status->len <= 1) 1370103285Sikob /* XXX not scsi status. shouldn't be happened */ 1371103285Sikob sense->extra_len = 0; 1372103285Sikob else if (sbp_status->len <= 4) 1373103285Sikob /* add_sense_code(_qual), info, cmd_spec_info */ 1374103285Sikob sense->extra_len = 6; 1375103285Sikob else 1376103285Sikob /* fru, sense_key_spec */ 1377103285Sikob sense->extra_len = 10; 1378103285Sikob sense->cmd_spec_info[0] = ntohl(sbp_cmd_status->cdb) & 0xff; 1379103285Sikob sense->cmd_spec_info[1] = (ntohl(sbp_cmd_status->cdb) >> 8) & 0xff; 1380103285Sikob sense->cmd_spec_info[2] = (ntohl(sbp_cmd_status->cdb) >> 16) & 0xff; 1381103285Sikob sense->cmd_spec_info[3] = (ntohl(sbp_cmd_status->cdb) >> 24) & 0xff; 1382103285Sikob sense->add_sense_code = sbp_cmd_status->s_code; 1383103285Sikob sense->add_sense_code_qual = sbp_cmd_status->s_qlfr; 1384103285Sikob sense->fru = sbp_cmd_status->fru; 1385103285Sikob sense->sense_key_spec[0] = ntohl(sbp_cmd_status->s_keydep) & 0xff; 1386103285Sikob sense->sense_key_spec[1] = (ntohl(sbp_cmd_status->s_keydep) >>8) & 0xff; 1387103285Sikob sense->sense_key_spec[2] = (ntohl(sbp_cmd_status->s_keydep) >>16) & 0xff; 1388103285Sikob 1389103285Sikob ocb->ccb->csio.scsi_status = sbp_cmd_status->status;; 1390103285Sikob ocb->ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR 1391103285Sikob | CAM_AUTOSNS_VALID; 1392103285Sikob/* 1393103285Sikob{ 1394103285Sikob u_int8_t j, *tmp; 1395103285Sikob tmp = sense; 1396103285Sikob for( j = 0 ; j < 32 ; j+=8){ 1397103285Sikob printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n", 1398103285Sikob tmp[j], tmp[j+1], tmp[j+2], tmp[j+3], 1399103285Sikob tmp[j+4], tmp[j+5], tmp[j+6], tmp[j+7]); 1400103285Sikob } 1401103285Sikob 1402103285Sikob} 1403103285Sikob*/ 1404110071Ssimokawa break; 1405110071Ssimokawa default: 1406110071Ssimokawa sbp_show_sdev_info(ocb->sdev, 2); 1407110071Ssimokawa printf("sbp_scsi_status: unknown scsi status 0x%x\n", 1408110071Ssimokawa sbp_cmd_status->status); 1409103285Sikob } 1410103285Sikob} 1411103285Sikob 1412103285Sikobstatic void 1413103285Sikobsbp_fix_inq_data(struct sbp_ocb *ocb) 1414103285Sikob{ 1415103285Sikob union ccb *ccb; 1416103285Sikob struct sbp_dev *sdev; 1417103285Sikob struct scsi_inquiry_data *inq; 1418103285Sikob 1419103285Sikob ccb = ocb->ccb; 1420103285Sikob sdev = ocb->sdev; 1421103285Sikob 1422103285Sikob if (ccb->csio.cdb_io.cdb_bytes[1] & SI_EVPD) 1423103285Sikob return; 1424103285SikobSBP_DEBUG(1) 1425103285Sikob sbp_show_sdev_info(sdev, 2); 1426103285Sikob printf("sbp_fix_inq_data\n"); 1427103285SikobEND_DEBUG 1428103285Sikob inq = (struct scsi_inquiry_data *) ccb->csio.data_ptr; 1429103285Sikob switch (SID_TYPE(inq)) { 1430103285Sikob case T_DIRECT: 1431103285Sikob /* 1432103285Sikob * XXX Convert Direct Access device to RBC. 1433108281Ssimokawa * I've never seen FireWire DA devices which support READ_6. 1434103285Sikob */ 1435103285Sikob#if 1 1436103285Sikob if (SID_TYPE(inq) == T_DIRECT) 1437103285Sikob inq->device |= T_RBC; /* T_DIRECT == 0 */ 1438103285Sikob#endif 1439103285Sikob /* fall through */ 1440103285Sikob case T_RBC: 1441111615Ssimokawa /* enable tag queuing */ 1442111615Ssimokawa#if 1 1443111615Ssimokawa inq->flags |= SID_CmdQue; 1444111615Ssimokawa#endif 1445103285Sikob /* 1446103285Sikob * Override vendor/product/revision information. 1447103285Sikob * Some devices sometimes return strange strings. 1448103285Sikob */ 1449111615Ssimokawa#if 1 1450103285Sikob bcopy(sdev->vendor, inq->vendor, sizeof(inq->vendor)); 1451103285Sikob bcopy(sdev->product, inq->product, sizeof(inq->product)); 1452103285Sikob bcopy(sdev->revision+2, inq->revision, sizeof(inq->revision)); 1453111615Ssimokawa#endif 1454103285Sikob break; 1455103285Sikob } 1456103285Sikob} 1457103285Sikob 1458103285Sikobstatic void 1459113584Ssimokawasbp_recv1(struct fw_xfer *xfer) 1460113584Ssimokawa{ 1461103285Sikob struct fw_pkt *rfp; 1462103285Sikob#if NEED_RESPONSE 1463103285Sikob struct fw_pkt *sfp; 1464103285Sikob#endif 1465103285Sikob struct sbp_softc *sbp; 1466103285Sikob struct sbp_dev *sdev; 1467103285Sikob struct sbp_ocb *ocb; 1468103285Sikob struct sbp_login_res *login_res = NULL; 1469103285Sikob struct sbp_status *sbp_status; 1470103285Sikob struct sbp_target *target; 1471111704Ssimokawa int orb_fun, status_valid0, status_valid, t, l, reset_agent = 0; 1472103285Sikob u_int32_t addr; 1473103285Sikob/* 1474103285Sikob u_int32_t *ld; 1475103285Sikob ld = xfer->recv.buf; 1476103285Sikobprintf("sbp %x %d %d %08x %08x %08x %08x\n", 1477103285Sikob xfer->resp, xfer->recv.len, xfer->recv.off, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); 1478103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); 1479103285Sikobprintf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11])); 1480103285Sikob*/ 1481113584Ssimokawa 1482113584Ssimokawa sbp = (struct sbp_softc *)xfer->sc; 1483103285Sikob if(xfer->resp != 0){ 1484103285Sikob printf("sbp_recv: xfer->resp != 0\n"); 1485113584Ssimokawa goto done0; 1486103285Sikob } 1487103285Sikob if(xfer->recv.buf == NULL){ 1488103285Sikob printf("sbp_recv: xfer->recv.buf == NULL\n"); 1489113584Ssimokawa goto done0; 1490103285Sikob } 1491103285Sikob sbp = (struct sbp_softc *)xfer->sc; 1492103285Sikob rfp = (struct fw_pkt *)xfer->recv.buf; 1493103285Sikob if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){ 1494103285Sikob printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); 1495113584Ssimokawa goto done0; 1496103285Sikob } 1497103285Sikob sbp_status = (struct sbp_status *)rfp->mode.wreqb.payload; 1498113584Ssimokawa addr = rfp->mode.wreqb.dest_lo; 1499103285SikobSBP_DEBUG(2) 1500103285Sikob printf("received address 0x%x\n", addr); 1501103285SikobEND_DEBUG 1502110189Ssimokawa t = SBP_ADDR2TRG(addr); 1503110189Ssimokawa if (t >= SBP_NUM_TARGETS) { 1504110189Ssimokawa device_printf(sbp->fd.dev, 1505110189Ssimokawa "sbp_recv1: invalid target %d\n", t); 1506113584Ssimokawa goto done0; 1507110189Ssimokawa } 1508110189Ssimokawa target = &sbp->targets[t]; 1509110189Ssimokawa l = SBP_ADDR2LUN(addr); 1510110189Ssimokawa if (l >= target->num_lun) { 1511110189Ssimokawa device_printf(sbp->fd.dev, 1512110189Ssimokawa "sbp_recv1: invalid lun %d (target=%d)\n", l, t); 1513113584Ssimokawa goto done0; 1514110189Ssimokawa } 1515110189Ssimokawa sdev = &target->luns[l]; 1516103285Sikob 1517110189Ssimokawa ocb = NULL; 1518110189Ssimokawa switch (sbp_status->src) { 1519110189Ssimokawa case 0: 1520110189Ssimokawa case 1: 1521111615Ssimokawa /* check mgm_ocb_cur first */ 1522111615Ssimokawa ocb = target->mgm_ocb_cur; 1523111615Ssimokawa if (ocb != NULL) { 1524111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 1525111615Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1526111615Ssimokawa target->mgm_ocb_cur = NULL; 1527111615Ssimokawa break; 1528111615Ssimokawa } 1529111615Ssimokawa } 1530111615Ssimokawa ocb = sbp_dequeue_ocb(sdev, sbp_status); 1531110189Ssimokawa if (ocb == NULL) { 1532110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1533111858Ssimokawa#if __FreeBSD_version >= 500000 1534111819Ssimokawa printf("No ocb(%x) on the queue\n", 1535111858Ssimokawa#else 1536111858Ssimokawa printf("No ocb(%lx) on the queue\n", 1537111858Ssimokawa#endif 1538111819Ssimokawa ntohl(sbp_status->orb_lo)); 1539110189Ssimokawa } 1540110189Ssimokawa break; 1541110189Ssimokawa case 2: 1542110189Ssimokawa /* unsolicit */ 1543110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1544110189Ssimokawa printf("unsolicit status received\n"); 1545110189Ssimokawa break; 1546110189Ssimokawa default: 1547110189Ssimokawa sbp_show_sdev_info(sdev, 2); 1548110189Ssimokawa printf("unknown sbp_status->src\n"); 1549110189Ssimokawa } 1550110189Ssimokawa 1551111615Ssimokawa status_valid0 = (sbp_status->src < 2 1552110189Ssimokawa && sbp_status->resp == ORB_RES_CMPL 1553111615Ssimokawa && sbp_status->dead == 0); 1554111615Ssimokawa status_valid = (status_valid0 && sbp_status->status == 0); 1555103285Sikob 1556111615Ssimokawa if (!status_valid0 || debug > 1){ 1557103285Sikob int status; 1558110129SsimokawaSBP_DEBUG(0) 1559103285Sikob sbp_show_sdev_info(sdev, 2); 1560103285Sikob printf("ORB status src:%x resp:%x dead:%x" 1561108712Ssimokawa#if __FreeBSD_version >= 500000 1562103285Sikob " len:%x stat:%x orb:%x%08x\n", 1563108712Ssimokawa#else 1564108712Ssimokawa " len:%x stat:%x orb:%x%08lx\n", 1565108712Ssimokawa#endif 1566103285Sikob sbp_status->src, sbp_status->resp, sbp_status->dead, 1567103285Sikob sbp_status->len, sbp_status->status, 1568108280Ssimokawa ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); 1569110129SsimokawaEND_DEBUG 1570103285Sikob sbp_show_sdev_info(sdev, 2); 1571103285Sikob status = sbp_status->status; 1572103285Sikob switch(sbp_status->resp) { 1573103285Sikob case 0: 1574103285Sikob if (status > MAX_ORB_STATUS0) 1575103285Sikob printf("%s\n", orb_status0[MAX_ORB_STATUS0]); 1576110189Ssimokawa else 1577110129Ssimokawa printf("%s\n", orb_status0[status]); 1578103285Sikob break; 1579103285Sikob case 1: 1580110336Ssimokawa printf("Obj: %s, Error: %s\n", 1581103285Sikob orb_status1_object[(status>>6) & 3], 1582103285Sikob orb_status1_serial_bus_error[status & 0xf]); 1583103285Sikob break; 1584110129Ssimokawa case 2: 1585110129Ssimokawa printf("Illegal request\n"); 1586110129Ssimokawa break; 1587110129Ssimokawa case 3: 1588110129Ssimokawa printf("Vendor dependent\n"); 1589110129Ssimokawa break; 1590103285Sikob default: 1591110129Ssimokawa printf("unknown respose code %d\n", sbp_status->resp); 1592103285Sikob } 1593103285Sikob } 1594103285Sikob 1595103285Sikob /* we have to reset the fetch agent if it's dead */ 1596103285Sikob if (sbp_status->dead) { 1597111615Ssimokawa if (sdev->path) { 1598103285Sikob xpt_freeze_devq(sdev->path, 1); 1599111615Ssimokawa sdev->freeze ++; 1600111615Ssimokawa } 1601111704Ssimokawa reset_agent = 1; 1602103285Sikob } 1603103285Sikob 1604111704Ssimokawa if (ocb == NULL) 1605111704Ssimokawa goto done; 1606103285Sikob 1607110336Ssimokawa sdev->flags &= ~SBP_DEV_TIMEOUT; 1608110336Ssimokawa 1609103285Sikob switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK){ 1610103285Sikob case ORB_FMT_NOP: 1611103285Sikob break; 1612103285Sikob case ORB_FMT_VED: 1613103285Sikob break; 1614103285Sikob case ORB_FMT_STD: 1615111819Ssimokawa switch(ocb->flags) { 1616103285Sikob case OCB_ACT_MGM: 1617103285Sikob orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK; 1618103285Sikob switch(orb_fun) { 1619103285Sikob case ORB_FUN_LGI: 1620113584Ssimokawa fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD); 1621113584Ssimokawa login_res = sdev->login; 1622103285Sikob login_res->len = ntohs(login_res->len); 1623103285Sikob login_res->id = ntohs(login_res->id); 1624103285Sikob login_res->cmd_hi = ntohs(login_res->cmd_hi); 1625103285Sikob login_res->cmd_lo = ntohl(login_res->cmd_lo); 1626103285Sikob if (status_valid) { 1627103285SikobSBP_DEBUG(0) 1628103285Sikobsbp_show_sdev_info(sdev, 2); 1629103285Sikobprintf("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)); 1630103285SikobEND_DEBUG 1631103285Sikob sbp_busy_timeout(sdev); 1632103285Sikob } else { 1633110336Ssimokawa /* forgot logout? */ 1634110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1635103285Sikob printf("login failed\n"); 1636103285Sikob sdev->status = SBP_DEV_RESET; 1637103285Sikob } 1638103285Sikob break; 1639103285Sikob case ORB_FUN_RCN: 1640113584Ssimokawa login_res = sdev->login; 1641103285Sikob if (status_valid) { 1642103285SikobSBP_DEBUG(0) 1643103285Sikobsbp_show_sdev_info(sdev, 2); 1644103285Sikobprintf("reconnect: len %d, ID %d, cmd %08x%08x\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo); 1645103285SikobEND_DEBUG 1646103285Sikob#if 1 1647111615Ssimokawa if (sdev->status == SBP_DEV_ATTACHED) 1648111615Ssimokawa sbp_scan_dev(sdev); 1649111615Ssimokawa else 1650111615Ssimokawa sbp_agent_reset(sdev); 1651103285Sikob#else 1652110336Ssimokawa sdev->status = SBP_DEV_ATTACHED; 1653111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_ATS, NULL); 1654103285Sikob#endif 1655103285Sikob } else { 1656103285Sikob /* reconnection hold time exceed? */ 1657110336SsimokawaSBP_DEBUG(0) 1658110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1659103285Sikob printf("reconnect failed\n"); 1660110336SsimokawaEND_DEBUG 1661111615Ssimokawa sbp_login(sdev); 1662103285Sikob } 1663103285Sikob break; 1664103285Sikob case ORB_FUN_LGO: 1665103285Sikob sdev->status = SBP_DEV_RESET; 1666103285Sikob break; 1667110336Ssimokawa case ORB_FUN_RST: 1668110336Ssimokawa sbp_busy_timeout(sdev); 1669110336Ssimokawa break; 1670103285Sikob case ORB_FUN_LUR: 1671103285Sikob case ORB_FUN_ATA: 1672103285Sikob case ORB_FUN_ATS: 1673110336Ssimokawa sbp_agent_reset(sdev); 1674103285Sikob break; 1675103285Sikob default: 1676110336Ssimokawa sbp_show_sdev_info(sdev, 2); 1677110336Ssimokawa printf("unknown function %d\n", orb_fun); 1678103285Sikob break; 1679103285Sikob } 1680111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 1681103285Sikob break; 1682103285Sikob case OCB_ACT_CMD: 1683103285Sikob if(ocb->ccb != NULL){ 1684103285Sikob union ccb *ccb; 1685103285Sikob/* 1686103285Sikob u_int32_t *ld; 1687103285Sikob ld = ocb->ccb->csio.data_ptr; 1688103285Sikob if(ld != NULL && ocb->ccb->csio.dxfer_len != 0) 1689103285Sikob printf("ptr %08x %08x %08x %08x\n", ld[0], ld[1], ld[2], ld[3]); 1690103285Sikob else 1691103285Sikob printf("ptr NULL\n"); 1692103285Sikobprintf("len %d\n", sbp_status->len); 1693103285Sikob*/ 1694103285Sikob ccb = ocb->ccb; 1695103285Sikob if(sbp_status->len > 1){ 1696103285Sikob sbp_scsi_status(sbp_status, ocb); 1697103285Sikob }else{ 1698103285Sikob if(sbp_status->resp != ORB_RES_CMPL){ 1699103285Sikob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1700103285Sikob }else{ 1701103285Sikob ccb->ccb_h.status = CAM_REQ_CMP; 1702103285Sikob } 1703103285Sikob } 1704103285Sikob /* fix up inq data */ 1705103285Sikob if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY) 1706103285Sikob sbp_fix_inq_data(ocb); 1707103285Sikob xpt_done(ccb); 1708103285Sikob } 1709103285Sikob break; 1710103285Sikob default: 1711103285Sikob break; 1712103285Sikob } 1713103285Sikob } 1714103285Sikob 1715113584Ssimokawa sbp_free_ocb(sdev, ocb); 1716111704Ssimokawadone: 1717111704Ssimokawa if (reset_agent) 1718111704Ssimokawa sbp_agent_reset(sdev); 1719103285Sikob 1720113584Ssimokawadone0: 1721103285Sikob/* The received packet is usually small enough to be stored within 1722103285Sikob * the buffer. In that case, the controller return ack_complete and 1723103285Sikob * no respose is necessary. 1724103285Sikob * 1725103285Sikob * XXX fwohci.c and firewire.c should inform event_code such as 1726103285Sikob * ack_complete or ack_pending to upper driver. 1727103285Sikob */ 1728103285Sikob#if NEED_RESPONSE 1729103285Sikob xfer->send.off = 0; 1730103285Sikob sfp = (struct fw_pkt *)xfer->send.buf; 1731103285Sikob sfp->mode.wres.dst = rfp->mode.wreqb.src; 1732113584Ssimokawa xfer->dst = sfp->mode.wres.dst; 1733103285Sikob xfer->spd = min(sdev->target->fwdev->speed, max_speed); 1734103285Sikob xfer->act.hand = sbp_loginres_callback; 1735103285Sikob xfer->retry_req = fw_asybusy; 1736103285Sikob 1737103285Sikob sfp->mode.wres.tlrt = rfp->mode.wreqb.tlrt; 1738103285Sikob sfp->mode.wres.tcode = FWTCODE_WRES; 1739103285Sikob sfp->mode.wres.rtcode = 0; 1740103285Sikob sfp->mode.wres.pri = 0; 1741103285Sikob 1742103285Sikob fw_asyreq(xfer->fc, -1, xfer); 1743103285Sikob#else 1744113584Ssimokawa /* recycle */ 1745113584Ssimokawa xfer->recv.len = SBP_RECV_LEN; 1746113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1747103285Sikob#endif 1748103285Sikob 1749103285Sikob return; 1750103285Sikob 1751103285Sikob} 1752103285Sikob 1753103285Sikobstatic void 1754103285Sikobsbp_recv(struct fw_xfer *xfer) 1755103285Sikob{ 1756103285Sikob int s; 1757103285Sikob 1758103285Sikob s = splcam(); 1759103285Sikob sbp_recv1(xfer); 1760103285Sikob splx(s); 1761103285Sikob} 1762103285Sikob/* 1763103285Sikob * sbp_attach() 1764103285Sikob */ 1765103285Sikobstatic int 1766103285Sikobsbp_attach(device_t dev) 1767103285Sikob{ 1768103285Sikob struct sbp_softc *sbp; 1769103285Sikob struct cam_devq *devq; 1770103285Sikob struct fw_xfer *xfer; 1771103285Sikob int i, s, error; 1772103285Sikob 1773103285SikobSBP_DEBUG(0) 1774111199Ssimokawa printf("sbp_attach (cold=%d)\n", cold); 1775103285SikobEND_DEBUG 1776103285Sikob 1777111199Ssimokawa if (cold) 1778111199Ssimokawa sbp_cold ++; 1779103285Sikob sbp = ((struct sbp_softc *)device_get_softc(dev)); 1780103285Sikob bzero(sbp, sizeof(struct sbp_softc)); 1781103285Sikob sbp->fd.dev = dev; 1782103285Sikob sbp->fd.fc = device_get_ivars(dev); 1783113584Ssimokawa error = bus_dma_tag_create(/*parent*/sbp->fd.fc->dmat, 1784113584Ssimokawa /* XXX shoud be 4 for sane backend? */ 1785113584Ssimokawa /*alignment*/1, 1786103285Sikob /*boundary*/0, 1787103285Sikob /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1788103285Sikob /*highaddr*/BUS_SPACE_MAXADDR, 1789103285Sikob /*filter*/NULL, /*filterarg*/NULL, 1790103285Sikob /*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX, 1791113474Ssimokawa /*maxsegsz*/SBP_SEG_MAX, 1792103285Sikob /*flags*/BUS_DMA_ALLOCNOW, 1793103285Sikob &sbp->dmat); 1794103285Sikob if (error != 0) { 1795103285Sikob printf("sbp_attach: Could not allocate DMA tag " 1796103285Sikob "- error %d\n", error); 1797103285Sikob return (ENOMEM); 1798103285Sikob } 1799103285Sikob 1800103285Sikob devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB); 1801103285Sikob if (devq == NULL) 1802103285Sikob return (ENXIO); 1803103285Sikob 1804103285Sikob for( i = 0 ; i < SBP_NUM_TARGETS ; i++){ 1805103285Sikob sbp->targets[i].fwdev = NULL; 1806103285Sikob sbp->targets[i].luns = NULL; 1807103285Sikob } 1808103285Sikob 1809103285Sikob sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp, 1810103285Sikob device_get_unit(dev), 1811111615Ssimokawa /*untagged*/ 1, 1812111615Ssimokawa /*tagged*/ SBP_QUEUE_LEN, 1813111615Ssimokawa devq); 1814103285Sikob 1815103285Sikob if (sbp->sim == NULL) { 1816103285Sikob cam_simq_free(devq); 1817103285Sikob return (ENXIO); 1818103285Sikob } 1819103285Sikob 1820103285Sikob 1821111615Ssimokawa if (xpt_bus_register(sbp->sim, /*bus*/0) != CAM_SUCCESS) 1822111615Ssimokawa goto fail; 1823103285Sikob 1824111615Ssimokawa if (xpt_create_path(&sbp->path, xpt_periph, cam_sim_path(sbp->sim), 1825111615Ssimokawa CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1826111615Ssimokawa goto fail; 1827111615Ssimokawa 1828103285Sikob sbp->fwb.start_hi = SBP_BIND_HI; 1829103285Sikob sbp->fwb.start_lo = SBP_DEV2ADDR(device_get_unit(sbp->fd.dev), 0, 0); 1830103285Sikob /* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */ 1831103285Sikob sbp->fwb.addrlen = 0xffff; 1832113584Ssimokawa sbp->fwb.act_type = FWACT_XFER; 1833113584Ssimokawa /* pre-allocate xfer */ 1834113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 1835113584Ssimokawa for (i = 0; i < SBP_NUM_OCB/2; i ++) { 1836113584Ssimokawa xfer = fw_xfer_alloc_buf(M_SBP, 1837113584Ssimokawa#if NEED_RESPONSE 1838113584Ssimokawa /* send */12, 1839113584Ssimokawa#else 1840113584Ssimokawa /* send */0, 1841113584Ssimokawa#endif 1842113584Ssimokawa /* recv */SBP_RECV_LEN); 1843113584Ssimokawa xfer->act.hand = sbp_recv; 1844113584Ssimokawa#if NEED_RESPONSE 1845113584Ssimokawa xfer->fc = sbp->fd.fc; 1846113584Ssimokawa#endif 1847113584Ssimokawa xfer->sc = (caddr_t)sbp; 1848113584Ssimokawa STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); 1849113584Ssimokawa } 1850103285Sikob fw_bindadd(sbp->fd.fc, &sbp->fwb); 1851103285Sikob 1852113584Ssimokawa sbp->fd.post_busreset = sbp_post_busreset; 1853103285Sikob sbp->fd.post_explore = sbp_post_explore; 1854103285Sikob 1855111199Ssimokawa if (sbp->fd.fc->status != -1) { 1856111199Ssimokawa s = splfw(); 1857111199Ssimokawa sbp_post_explore((void *)sbp); 1858111199Ssimokawa splx(s); 1859111199Ssimokawa } 1860111199Ssimokawa 1861103285Sikob return (0); 1862111615Ssimokawafail: 1863111615Ssimokawa cam_sim_free(sbp->sim, /*free_devq*/TRUE); 1864111615Ssimokawa return (ENXIO); 1865103285Sikob} 1866103285Sikob 1867103285Sikobstatic int 1868110145Ssimokawasbp_logout_all(struct sbp_softc *sbp) 1869110145Ssimokawa{ 1870110145Ssimokawa struct sbp_target *target; 1871110145Ssimokawa struct sbp_dev *sdev; 1872110145Ssimokawa int i, j; 1873110145Ssimokawa 1874110145SsimokawaSBP_DEBUG(0) 1875110145Ssimokawa printf("sbp_logout_all\n"); 1876110145SsimokawaEND_DEBUG 1877110145Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) { 1878110145Ssimokawa target = &sbp->targets[i]; 1879110145Ssimokawa if (target->luns == NULL) 1880110145Ssimokawa continue; 1881110145Ssimokawa for (j = 0; j < target->num_lun; j++) { 1882110145Ssimokawa sdev = &target->luns[j]; 1883113584Ssimokawa callout_stop(&sdev->login_callout); 1884110336Ssimokawa if (sdev->status >= SBP_DEV_TOATTACH && 1885110336Ssimokawa sdev->status <= SBP_DEV_ATTACHED) 1886111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); 1887110145Ssimokawa } 1888110145Ssimokawa } 1889113584Ssimokawa 1890110145Ssimokawa return 0; 1891110145Ssimokawa} 1892110145Ssimokawa 1893110145Ssimokawastatic int 1894110145Ssimokawasbp_shutdown(device_t dev) 1895110145Ssimokawa{ 1896110145Ssimokawa struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 1897110145Ssimokawa 1898110145Ssimokawa sbp_logout_all(sbp); 1899110145Ssimokawa return (0); 1900110145Ssimokawa} 1901110145Ssimokawa 1902110145Ssimokawastatic int 1903103285Sikobsbp_detach(device_t dev) 1904103285Sikob{ 1905103285Sikob struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); 1906103285Sikob struct firewire_comm *fc = sbp->fd.fc; 1907113584Ssimokawa struct sbp_target *target; 1908113584Ssimokawa struct sbp_dev *sdev; 1909113584Ssimokawa struct fw_xfer *xfer, *next; 1910113584Ssimokawa int i, j; 1911103285Sikob 1912103285SikobSBP_DEBUG(0) 1913103285Sikob printf("sbp_detach\n"); 1914103285SikobEND_DEBUG 1915113584Ssimokawa 1916103285Sikob for (i = 0; i < SBP_NUM_TARGETS; i ++) 1917110145Ssimokawa sbp_cam_detach_target(&sbp->targets[i]); 1918111615Ssimokawa xpt_free_path(sbp->path); 1919103285Sikob xpt_bus_deregister(cam_sim_path(sbp->sim)); 1920110145Ssimokawa 1921110145Ssimokawa sbp_logout_all(sbp); 1922113584Ssimokawa 1923110145Ssimokawa /* XXX wait for logout completion */ 1924110145Ssimokawa tsleep(&i, FWPRI, "sbpdtc", hz/2); 1925110145Ssimokawa 1926113584Ssimokawa for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) { 1927113584Ssimokawa target = &sbp->targets[i]; 1928113584Ssimokawa if (target->luns == NULL) 1929113584Ssimokawa continue; 1930113584Ssimokawa callout_stop(&target->mgm_ocb_timeout); 1931113584Ssimokawa for (j = 0; j < target->num_lun; j++) { 1932113584Ssimokawa sdev = &target->luns[j]; 1933113584Ssimokawa if (sdev->status != SBP_DEV_DEAD) { 1934113584Ssimokawa for (i = 0; i < SBP_QUEUE_LEN; i++) 1935113584Ssimokawa bus_dmamap_destroy(sbp->dmat, 1936113584Ssimokawa sdev->ocb[i].dmamap); 1937113584Ssimokawa fwdma_free(sbp->fd.fc, &sdev->dma); 1938113584Ssimokawa } 1939113584Ssimokawa } 1940113584Ssimokawa for (xfer = STAILQ_FIRST(&target->xferlist); 1941113584Ssimokawa xfer != NULL; xfer = next) { 1942113584Ssimokawa next = STAILQ_NEXT(xfer, link); 1943113584Ssimokawa fw_xfer_free(xfer); 1944113584Ssimokawa } 1945113584Ssimokawa free(target->luns, M_SBP); 1946113584Ssimokawa } 1947113584Ssimokawa 1948113584Ssimokawa for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist); 1949113584Ssimokawa xfer != NULL; xfer = next) { 1950113584Ssimokawa next = STAILQ_NEXT(xfer, link); 1951113584Ssimokawa fw_xfer_free(xfer); 1952113584Ssimokawa } 1953113584Ssimokawa STAILQ_INIT(&sbp->fwb.xferlist); 1954110145Ssimokawa fw_bindremove(fc, &sbp->fwb); 1955113584Ssimokawa 1956103285Sikob bus_dma_tag_destroy(sbp->dmat); 1957110145Ssimokawa 1958103285Sikob return (0); 1959103285Sikob} 1960103285Sikob 1961103285Sikobstatic void 1962110145Ssimokawasbp_cam_detach_target(struct sbp_target *target) 1963103285Sikob{ 1964113584Ssimokawa struct sbp_dev *sdev; 1965103285Sikob int i; 1966103285Sikob 1967103285Sikob if (target->luns != NULL) { 1968108529SsimokawaSBP_DEBUG(0) 1969103285Sikob printf("sbp_detach_target %d\n", target->target_id); 1970108529SsimokawaEND_DEBUG 1971111615Ssimokawa callout_stop(&target->scan_callout); 1972110193Ssimokawa for (i = 0; i < target->num_lun; i++) { 1973103285Sikob sdev = &target->luns[i]; 1974113584Ssimokawa if (sdev->status == SBP_DEV_DEAD) 1975103285Sikob continue; 1976113584Ssimokawa if (sdev->status == SBP_DEV_RESET) 1977113584Ssimokawa continue; 1978110336Ssimokawa if (sdev->path) { 1979103285Sikob xpt_async(AC_LOST_DEVICE, sdev->path, NULL); 1980110336Ssimokawa xpt_free_path(sdev->path); 1981110336Ssimokawa sdev->path = NULL; 1982110336Ssimokawa } 1983103285Sikob sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE); 1984103285Sikob } 1985103285Sikob } 1986103285Sikob} 1987103285Sikob 1988103285Sikobstatic void 1989103285Sikobsbp_timeout(void *arg) 1990103285Sikob{ 1991103285Sikob struct sbp_ocb *ocb = (struct sbp_ocb *)arg; 1992103285Sikob struct sbp_dev *sdev = ocb->sdev; 1993103285Sikob 1994103285Sikob sbp_show_sdev_info(sdev, 2); 1995110336Ssimokawa printf("request timeout ... "); 1996103285Sikob 1997111615Ssimokawa if (ocb->flags == OCB_ACT_MGM) { 1998111615Ssimokawa printf("management ORB\n"); 1999111615Ssimokawa /* XXX just ignore for now */ 2000111615Ssimokawa sdev->target->mgm_ocb_cur = NULL; 2001113584Ssimokawa sbp_free_ocb(sdev, ocb); 2002111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); 2003111615Ssimokawa return; 2004111615Ssimokawa } 2005111615Ssimokawa 2006110336Ssimokawa xpt_freeze_devq(sdev->path, 1); 2007111615Ssimokawa sdev->freeze ++; 2008110336Ssimokawa sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); 2009110336Ssimokawa if (sdev->flags & SBP_DEV_TIMEOUT) { 2010110336Ssimokawa printf("target reset\n"); 2011111615Ssimokawa sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); 2012110336Ssimokawa sdev->flags &= ~SBP_DEV_TIMEOUT; 2013110336Ssimokawa } else { 2014110336Ssimokawa printf("agent reset\n"); 2015110336Ssimokawa sdev->flags |= SBP_DEV_TIMEOUT; 2016110336Ssimokawa sbp_agent_reset(sdev); 2017110336Ssimokawa } 2018103285Sikob return; 2019103285Sikob} 2020103285Sikob 2021103285Sikobstatic void 2022103285Sikobsbp_action1(struct cam_sim *sim, union ccb *ccb) 2023103285Sikob{ 2024103285Sikob 2025103285Sikob struct sbp_softc *sbp = (struct sbp_softc *)sim->softc; 2026103285Sikob struct sbp_target *target = NULL; 2027103285Sikob struct sbp_dev *sdev = NULL; 2028103285Sikob 2029103285Sikob /* target:lun -> sdev mapping */ 2030103285Sikob if (sbp != NULL 2031103285Sikob && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD 2032103285Sikob && ccb->ccb_h.target_id < SBP_NUM_TARGETS) { 2033103285Sikob target = &sbp->targets[ccb->ccb_h.target_id]; 2034103285Sikob if (target->fwdev != NULL 2035103285Sikob && ccb->ccb_h.target_lun != CAM_LUN_WILDCARD 2036103285Sikob && ccb->ccb_h.target_lun < target->num_lun) { 2037103285Sikob sdev = &target->luns[ccb->ccb_h.target_lun]; 2038103285Sikob if (sdev->status != SBP_DEV_ATTACHED && 2039103285Sikob sdev->status != SBP_DEV_PROBE) 2040103285Sikob sdev = NULL; 2041103285Sikob } 2042103285Sikob } 2043103285Sikob 2044103285SikobSBP_DEBUG(1) 2045103285Sikob if (sdev == NULL) 2046103285Sikob printf("invalid target %d lun %d\n", 2047103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2048103285SikobEND_DEBUG 2049103285Sikob 2050103285Sikob switch (ccb->ccb_h.func_code) { 2051103285Sikob case XPT_SCSI_IO: 2052103285Sikob case XPT_RESET_DEV: 2053103285Sikob case XPT_GET_TRAN_SETTINGS: 2054103285Sikob case XPT_SET_TRAN_SETTINGS: 2055103285Sikob case XPT_CALC_GEOMETRY: 2056103285Sikob if (sdev == NULL) { 2057103285SikobSBP_DEBUG(1) 2058103285Sikob printf("%s:%d:%d:func_code 0x%04x: " 2059103285Sikob "Invalid target (target needed)\n", 2060103285Sikob device_get_nameunit(sbp->fd.dev), 2061103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2062103285Sikob ccb->ccb_h.func_code); 2063103285SikobEND_DEBUG 2064103285Sikob 2065108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2066103285Sikob xpt_done(ccb); 2067103285Sikob return; 2068103285Sikob } 2069103285Sikob break; 2070103285Sikob case XPT_PATH_INQ: 2071103285Sikob case XPT_NOOP: 2072103285Sikob /* The opcodes sometimes aimed at a target (sc is valid), 2073103285Sikob * sometimes aimed at the SIM (sc is invalid and target is 2074103285Sikob * CAM_TARGET_WILDCARD) 2075103285Sikob */ 2076103285Sikob if (sbp == NULL && 2077103285Sikob ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 2078103285SikobSBP_DEBUG(0) 2079103285Sikob printf("%s:%d:%d func_code 0x%04x: " 2080103285Sikob "Invalid target (no wildcard)\n", 2081103285Sikob device_get_nameunit(sbp->fd.dev), 2082103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2083103285Sikob ccb->ccb_h.func_code); 2084103285SikobEND_DEBUG 2085108276Ssimokawa ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2086103285Sikob xpt_done(ccb); 2087103285Sikob return; 2088103285Sikob } 2089103285Sikob break; 2090103285Sikob default: 2091103285Sikob /* XXX Hm, we should check the input parameters */ 2092103285Sikob break; 2093103285Sikob } 2094103285Sikob 2095103285Sikob switch (ccb->ccb_h.func_code) { 2096103285Sikob case XPT_SCSI_IO: 2097103285Sikob { 2098103285Sikob struct ccb_scsiio *csio; 2099103285Sikob struct sbp_ocb *ocb; 2100113584Ssimokawa int speed; 2101106506Ssimokawa void *cdb; 2102103285Sikob 2103103285Sikob csio = &ccb->csio; 2104103285Sikob 2105103285SikobSBP_DEBUG(1) 2106103285Sikob printf("%s:%d:%d XPT_SCSI_IO: " 2107103285Sikob "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" 2108103285Sikob ", flags: 0x%02x, " 2109103285Sikob "%db cmd/%db data/%db sense\n", 2110103285Sikob device_get_nameunit(sbp->fd.dev), 2111103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2112103285Sikob csio->cdb_io.cdb_bytes[0], 2113103285Sikob csio->cdb_io.cdb_bytes[1], 2114103285Sikob csio->cdb_io.cdb_bytes[2], 2115103285Sikob csio->cdb_io.cdb_bytes[3], 2116103285Sikob csio->cdb_io.cdb_bytes[4], 2117103285Sikob csio->cdb_io.cdb_bytes[5], 2118103285Sikob csio->cdb_io.cdb_bytes[6], 2119103285Sikob csio->cdb_io.cdb_bytes[7], 2120103285Sikob csio->cdb_io.cdb_bytes[8], 2121103285Sikob csio->cdb_io.cdb_bytes[9], 2122103285Sikob ccb->ccb_h.flags & CAM_DIR_MASK, 2123103285Sikob csio->cdb_len, csio->dxfer_len, 2124103285Sikob csio->sense_len); 2125103285SikobEND_DEBUG 2126103285Sikob if(sdev == NULL){ 2127103285Sikob ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2128103285Sikob xpt_done(ccb); 2129103285Sikob return; 2130103285Sikob } 2131103285Sikob#if 0 2132103285Sikob /* if we are in probe stage, pass only probe commands */ 2133103285Sikob if (sdev->status == SBP_DEV_PROBE) { 2134103285Sikob char *name; 2135103285Sikob name = xpt_path_periph(ccb->ccb_h.path)->periph_name; 2136103285Sikob printf("probe stage, periph name: %s\n", name); 2137103285Sikob if (strcmp(name, "probe") != 0) { 2138103285Sikob ccb->ccb_h.status = CAM_REQUEUE_REQ; 2139103285Sikob xpt_done(ccb); 2140103285Sikob return; 2141103285Sikob } 2142103285Sikob } 2143103285Sikob#endif 2144113584Ssimokawa if ((ocb = sbp_get_ocb(sdev)) == NULL) 2145103285Sikob return; 2146113584Ssimokawa 2147103285Sikob ocb->flags = OCB_ACT_CMD; 2148103285Sikob ocb->sdev = sdev; 2149103285Sikob ocb->ccb = ccb; 2150103285Sikob ccb->ccb_h.ccb_sdev_ptr = sdev; 2151103285Sikob ocb->orb[0] = htonl(1 << 31); 2152103285Sikob ocb->orb[1] = 0; 2153103285Sikob ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS )<< 16) ); 2154113584Ssimokawa ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); 2155103285Sikob speed = min(target->fwdev->speed, max_speed); 2156103285Sikob ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) 2157103285Sikob | ORB_CMD_MAXP(speed + 7)); 2158103285Sikob if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN){ 2159103285Sikob ocb->orb[4] |= htonl(ORB_CMD_IN); 2160103285Sikob } 2161103285Sikob 2162103285Sikob if (csio->ccb_h.flags & CAM_SCATTER_VALID) 2163103285Sikob printf("sbp: CAM_SCATTER_VALID\n"); 2164103285Sikob if (csio->ccb_h.flags & CAM_DATA_PHYS) 2165103285Sikob printf("sbp: CAM_DATA_PHYS\n"); 2166103285Sikob 2167106506Ssimokawa if (csio->ccb_h.flags & CAM_CDB_POINTER) 2168106506Ssimokawa cdb = (void *)csio->cdb_io.cdb_ptr; 2169106506Ssimokawa else 2170106506Ssimokawa cdb = (void *)&csio->cdb_io.cdb_bytes; 2171106506Ssimokawa bcopy(cdb, 2172103285Sikob (void *)(uintptr_t)(volatile void *)&ocb->orb[5], 2173106506Ssimokawa csio->cdb_len); 2174103285Sikob/* 2175103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3])); 2176103285Sikobprintf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); 2177103285Sikob*/ 2178103285Sikob if (ccb->csio.dxfer_len > 0) { 2179113584Ssimokawa int s, error; 2180103285Sikob 2181103285Sikob s = splsoftvm(); 2182113584Ssimokawa error = bus_dmamap_load(/*dma tag*/sbp->dmat, 2183103285Sikob /*dma map*/ocb->dmamap, 2184103285Sikob ccb->csio.data_ptr, 2185103285Sikob ccb->csio.dxfer_len, 2186103285Sikob sbp_execute_ocb, 2187103285Sikob ocb, 2188103285Sikob /*flags*/0); 2189103285Sikob splx(s); 2190113584Ssimokawa if (error) 2191113584Ssimokawa printf("sbp: bus_dmamap_load error %d\n", error); 2192103285Sikob } else 2193103285Sikob sbp_execute_ocb(ocb, NULL, 0, 0); 2194103285Sikob break; 2195103285Sikob } 2196103285Sikob case XPT_CALC_GEOMETRY: 2197103285Sikob { 2198103285Sikob struct ccb_calc_geometry *ccg; 2199103285Sikob u_int32_t size_mb; 2200103285Sikob u_int32_t secs_per_cylinder; 2201103285Sikob int extended = 1; 2202103285Sikob ccg = &ccb->ccg; 2203103285Sikob 2204103285Sikob if (ccg->block_size == 0) { 2205103285Sikob printf("sbp_action1: block_size is 0.\n"); 2206103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2207103285Sikob xpt_done(ccb); 2208103285Sikob break; 2209103285Sikob } 2210103285SikobSBP_DEBUG(1) 2211103285Sikob printf("%s:%d:%d:%d:XPT_CALC_GEOMETRY: " 2212103285Sikob "Volume size = %d\n", 2213103285Sikob device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim), 2214103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 2215103285Sikob ccg->volume_size); 2216103285SikobEND_DEBUG 2217103285Sikob 2218103285Sikob size_mb = ccg->volume_size 2219103285Sikob / ((1024L * 1024L) / ccg->block_size); 2220103285Sikob 2221103285Sikob if (size_mb >= 1024 && extended) { 2222103285Sikob ccg->heads = 255; 2223103285Sikob ccg->secs_per_track = 63; 2224103285Sikob } else { 2225103285Sikob ccg->heads = 64; 2226103285Sikob ccg->secs_per_track = 32; 2227103285Sikob } 2228103285Sikob secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2229103285Sikob ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2230103285Sikob ccb->ccb_h.status = CAM_REQ_CMP; 2231103285Sikob xpt_done(ccb); 2232103285Sikob break; 2233103285Sikob } 2234103285Sikob case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2235103285Sikob { 2236103285Sikob 2237103285SikobSBP_DEBUG(1) 2238103285Sikob printf("%s:%d:XPT_RESET_BUS: \n", 2239103285Sikob device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); 2240103285SikobEND_DEBUG 2241103285Sikob 2242103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2243103285Sikob xpt_done(ccb); 2244103285Sikob break; 2245103285Sikob } 2246103285Sikob case XPT_PATH_INQ: /* Path routing inquiry */ 2247103285Sikob { 2248103285Sikob struct ccb_pathinq *cpi = &ccb->cpi; 2249103285Sikob 2250103285SikobSBP_DEBUG(1) 2251103285Sikob printf("%s:%d:%d XPT_PATH_INQ:.\n", 2252103285Sikob device_get_nameunit(sbp->fd.dev), 2253103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2254103285SikobEND_DEBUG 2255103285Sikob cpi->version_num = 1; /* XXX??? */ 2256111615Ssimokawa cpi->hba_inquiry = PI_TAG_ABLE; 2257103285Sikob cpi->target_sprt = 0; 2258111199Ssimokawa cpi->hba_misc = PIM_NOBUSRESET; 2259103285Sikob cpi->hba_eng_cnt = 0; 2260103285Sikob cpi->max_target = SBP_NUM_TARGETS - 1; 2261103285Sikob cpi->max_lun = SBP_NUM_LUNS - 1; 2262103285Sikob cpi->initiator_id = SBP_INITIATOR; 2263103285Sikob cpi->bus_id = sim->bus_id; 2264103285Sikob cpi->base_transfer_speed = 400 * 1000 / 8; 2265103285Sikob strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2266103285Sikob strncpy(cpi->hba_vid, "SBP", HBA_IDLEN); 2267103285Sikob strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); 2268103285Sikob cpi->unit_number = sim->unit_number; 2269103285Sikob 2270103285Sikob cpi->ccb_h.status = CAM_REQ_CMP; 2271103285Sikob xpt_done(ccb); 2272103285Sikob break; 2273103285Sikob } 2274103285Sikob case XPT_GET_TRAN_SETTINGS: 2275103285Sikob { 2276103285Sikob struct ccb_trans_settings *cts = &ccb->cts; 2277103285SikobSBP_DEBUG(1) 2278103285Sikob printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", 2279103285Sikob device_get_nameunit(sbp->fd.dev), 2280103285Sikob ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2281103285SikobEND_DEBUG 2282111615Ssimokawa /* Enable disconnect and tagged queuing */ 2283103285Sikob cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 2284111615Ssimokawa cts->flags = CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB; 2285103285Sikob 2286103285Sikob cts->ccb_h.status = CAM_REQ_CMP; 2287103285Sikob xpt_done(ccb); 2288103285Sikob break; 2289103285Sikob } 2290103285Sikob case XPT_ABORT: 2291103285Sikob ccb->ccb_h.status = CAM_UA_ABORT; 2292103285Sikob xpt_done(ccb); 2293103285Sikob break; 2294111615Ssimokawa case XPT_SET_TRAN_SETTINGS: 2295111615Ssimokawa /* XXX */ 2296103285Sikob default: 2297103285Sikob ccb->ccb_h.status = CAM_REQ_INVALID; 2298103285Sikob xpt_done(ccb); 2299103285Sikob break; 2300103285Sikob } 2301103285Sikob return; 2302103285Sikob} 2303103285Sikob 2304103285Sikobstatic void 2305103285Sikobsbp_action(struct cam_sim *sim, union ccb *ccb) 2306103285Sikob{ 2307103285Sikob int s; 2308103285Sikob 2309103285Sikob s = splfw(); 2310103285Sikob sbp_action1(sim, ccb); 2311103285Sikob splx(s); 2312103285Sikob} 2313103285Sikob 2314103285Sikobstatic void 2315103285Sikobsbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error) 2316103285Sikob{ 2317103285Sikob int i; 2318103285Sikob struct sbp_ocb *ocb; 2319103285Sikob struct sbp_ocb *prev; 2320105633Ssimokawa bus_dma_segment_t *s; 2321103285Sikob 2322103285Sikob if (error) 2323103285Sikob printf("sbp_execute_ocb: error=%d\n", error); 2324103285Sikob 2325103285Sikob ocb = (struct sbp_ocb *)arg; 2326113584Ssimokawa 2327113584SsimokawaSBP_DEBUG(1) 2328113584Ssimokawa printf("sbp_execute_ocb: seg %d", seg); 2329113584Ssimokawa for (i = 0; i < seg; i++) 2330113584Ssimokawa#if __FreeBSD_version >= 500000 2331113972Ssimokawa printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr, 2332113972Ssimokawa (uintmax_t)segments[i].ds_len); 2333113584Ssimokawa#else 2334113972Ssimokawa printf(", %x:%d", segments[i].ds_addr, segments[i].ds_len); 2335113584Ssimokawa#endif 2336113584Ssimokawa printf("\n"); 2337113584SsimokawaEND_DEBUG 2338113584Ssimokawa 2339103285Sikob if (seg == 1) { 2340103285Sikob /* direct pointer */ 2341113474Ssimokawa s = &segments[0]; 2342113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2343113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2344113474Ssimokawa ocb->orb[3] = htonl(s->ds_addr); 2345113474Ssimokawa ocb->orb[4] |= htonl(s->ds_len); 2346103285Sikob } else if(seg > 1) { 2347103285Sikob /* page table */ 2348103285Sikob for (i = 0; i < seg; i++) { 2349105633Ssimokawa s = &segments[i]; 2350108877SsimokawaSBP_DEBUG(0) 2351108877Ssimokawa /* XXX LSI Logic "< 16 byte" bug might be hit */ 2352105633Ssimokawa if (s->ds_len < 16) 2353105633Ssimokawa printf("sbp_execute_ocb: warning, " 2354108877Ssimokawa#if __FreeBSD_version >= 500000 2355106543Ssimokawa "segment length(%zd) is less than 16." 2356108877Ssimokawa#else 2357108877Ssimokawa "segment length(%d) is less than 16." 2358108877Ssimokawa#endif 2359105633Ssimokawa "(seg=%d/%d)\n", s->ds_len, i+1, seg); 2360108877SsimokawaEND_DEBUG 2361113474Ssimokawa if (s->ds_len > SBP_SEG_MAX) 2362113474Ssimokawa panic("ds_len > SBP_SEG_MAX, fix busdma code"); 2363105633Ssimokawa ocb->ind_ptr[i].hi = htonl(s->ds_len << 16); 2364105633Ssimokawa ocb->ind_ptr[i].lo = htonl(s->ds_addr); 2365103285Sikob } 2366103285Sikob ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg); 2367103285Sikob } 2368103285Sikob 2369113584Ssimokawa if (seg > 0) 2370113584Ssimokawa bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap, 2371113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2372113584Ssimokawa BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 2373103285Sikob prev = sbp_enqueue_ocb(ocb->sdev, ocb); 2374113584Ssimokawa fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE); 2375111819Ssimokawa if (prev == NULL) 2376103285Sikob sbp_orb_pointer(ocb->sdev, ocb); 2377103285Sikob} 2378103285Sikob 2379103285Sikobstatic void 2380103285Sikobsbp_poll(struct cam_sim *sim) 2381103285Sikob{ 2382103285Sikob /* should call fwohci_intr? */ 2383103285Sikob return; 2384103285Sikob} 2385103285Sikobstatic struct sbp_ocb * 2386111615Ssimokawasbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status) 2387103285Sikob{ 2388103285Sikob struct sbp_ocb *ocb; 2389103285Sikob struct sbp_ocb *next; 2390103285Sikob int s = splfw(), order = 0; 2391103285Sikob int flags; 2392103285Sikob 2393103285Sikob for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) { 2394103285Sikob next = STAILQ_NEXT(ocb, ocb); 2395103285Sikob flags = ocb->flags; 2396103285SikobSBP_DEBUG(1) 2397110336Ssimokawa sbp_show_sdev_info(sdev, 2); 2398108712Ssimokawa#if __FreeBSD_version >= 500000 2399113972Ssimokawa printf("orb: 0x%jx next: 0x%x, flags %x\n", 2400113972Ssimokawa (uintmax_t)ocb->bus_addr, 2401108712Ssimokawa#else 2402108712Ssimokawa printf("orb: 0x%x next: 0x%lx, flags %x\n", 2403113972Ssimokawa ocb->bus_addr, 2404108712Ssimokawa#endif 2405113972Ssimokawa ntohl(ocb->orb[1]), flags); 2406103285SikobEND_DEBUG 2407111615Ssimokawa if (OCB_MATCH(ocb, sbp_status)) { 2408103285Sikob /* found */ 2409111819Ssimokawa STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); 2410103285Sikob if (ocb->ccb != NULL) 2411103285Sikob untimeout(sbp_timeout, (caddr_t)ocb, 2412103285Sikob ocb->ccb->ccb_h.timeout_ch); 2413113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2414113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, 2415113584Ssimokawa ocb->dmamap, 2416113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2417113584Ssimokawa BUS_DMASYNC_POSTREAD : 2418113584Ssimokawa BUS_DMASYNC_POSTWRITE); 2419113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, 2420113584Ssimokawa ocb->dmamap); 2421103285Sikob } 2422111819Ssimokawa if (next != NULL && sbp_status->src == 1) 2423111819Ssimokawa sbp_orb_pointer(sdev, next); 2424103285Sikob break; 2425111819Ssimokawa } else 2426111819Ssimokawa order ++; 2427103285Sikob } 2428103285Sikob splx(s); 2429103285SikobSBP_DEBUG(0) 2430103285Sikob if (ocb && order > 0) { 2431103285Sikob sbp_show_sdev_info(sdev, 2); 2432103285Sikob printf("unordered execution order:%d\n", order); 2433103285Sikob } 2434103285SikobEND_DEBUG 2435103285Sikob return (ocb); 2436103285Sikob} 2437103285Sikob 2438103285Sikobstatic struct sbp_ocb * 2439103285Sikobsbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2440103285Sikob{ 2441103285Sikob int s = splfw(); 2442103285Sikob struct sbp_ocb *prev; 2443103285Sikob 2444103285SikobSBP_DEBUG(2) 2445103285Sikob sbp_show_sdev_info(sdev, 2); 2446108712Ssimokawa#if __FreeBSD_version >= 500000 2447113972Ssimokawa printf("sbp_enqueue_ocb orb=0x%jx in physical memory\n", 2448113972Ssimokawa (uintmax_t)ocb->bus_addr); 2449108712Ssimokawa#else 2450113584Ssimokawa printf("sbp_enqueue_ocb orb=0x%x in physical memory\n", ocb->bus_addr); 2451108712Ssimokawa#endif 2452103285SikobEND_DEBUG 2453103285Sikob prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb); 2454103285Sikob STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb); 2455103285Sikob 2456103285Sikob if (ocb->ccb != NULL) 2457103285Sikob ocb->ccb->ccb_h.timeout_ch = timeout(sbp_timeout, (caddr_t)ocb, 2458103285Sikob (ocb->ccb->ccb_h.timeout * hz) / 1000); 2459103285Sikob 2460110579Ssimokawa if (prev != NULL ) { 2461103285SikobSBP_DEBUG(1) 2462108712Ssimokawa#if __FreeBSD_version >= 500000 2463113972Ssimokawa printf("linking chain 0x%jx -> 0x%jx\n", 2464113972Ssimokawa (uintmax_t)prev->bus_addr, (uintmax_t)ocb->bus_addr); 2465108712Ssimokawa#else 2466113972Ssimokawa printf("linking chain 0x%x -> 0x%x\n", prev->bus_addr, ocb->bus_addr); 2467108712Ssimokawa#endif 2468103285SikobEND_DEBUG 2469113584Ssimokawa prev->orb[1] = htonl(ocb->bus_addr); 2470103285Sikob prev->orb[0] = 0; 2471103285Sikob } 2472103285Sikob splx(s); 2473103285Sikob 2474103285Sikob return prev; 2475103285Sikob} 2476103285Sikob 2477103285Sikobstatic struct sbp_ocb * 2478113584Ssimokawasbp_get_ocb(struct sbp_dev *sdev) 2479103285Sikob{ 2480103285Sikob struct sbp_ocb *ocb; 2481103285Sikob int s = splfw(); 2482113584Ssimokawa ocb = STAILQ_FIRST(&sdev->free_ocbs); 2483103285Sikob if (ocb == NULL) { 2484103285Sikob printf("ocb shortage!!!\n"); 2485103285Sikob return NULL; 2486103285Sikob } 2487113584Ssimokawa STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb); 2488103285Sikob splx(s); 2489103285Sikob ocb->ccb = NULL; 2490103285Sikob return (ocb); 2491103285Sikob} 2492103285Sikob 2493103285Sikobstatic void 2494113584Ssimokawasbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) 2495103285Sikob{ 2496103285Sikob ocb->flags = 0; 2497103285Sikob ocb->ccb = NULL; 2498113584Ssimokawa STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); 2499103285Sikob} 2500103285Sikob 2501103285Sikobstatic void 2502103285Sikobsbp_abort_ocb(struct sbp_ocb *ocb, int status) 2503103285Sikob{ 2504103285Sikob struct sbp_dev *sdev; 2505103285Sikob 2506103285Sikob sdev = ocb->sdev; 2507113584SsimokawaSBP_DEBUG(0) 2508103285Sikob sbp_show_sdev_info(sdev, 2); 2509111819Ssimokawa#if __FreeBSD_version >= 500000 2510113972Ssimokawa printf("sbp_abort_ocb 0x%jx\n", (uintmax_t)ocb->bus_addr); 2511111819Ssimokawa#else 2512113972Ssimokawa printf("sbp_abort_ocb 0x%x\n", ocb->bus_addr); 2513111819Ssimokawa#endif 2514113584SsimokawaEND_DEBUG 2515113584SsimokawaSBP_DEBUG(1) 2516105792Ssimokawa if (ocb->ccb != NULL) 2517105792Ssimokawa sbp_print_scsi_cmd(ocb); 2518103285SikobEND_DEBUG 2519113584Ssimokawa if (ntohl(ocb->orb[4]) & 0xffff) { 2520113584Ssimokawa bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap, 2521113584Ssimokawa (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? 2522113584Ssimokawa BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 2523113584Ssimokawa bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap); 2524113584Ssimokawa } 2525111819Ssimokawa if (ocb->ccb != NULL) { 2526110336Ssimokawa untimeout(sbp_timeout, (caddr_t)ocb, 2527110336Ssimokawa ocb->ccb->ccb_h.timeout_ch); 2528103285Sikob ocb->ccb->ccb_h.status = status; 2529103285Sikob xpt_done(ocb->ccb); 2530103285Sikob } 2531113584Ssimokawa sbp_free_ocb(sdev, ocb); 2532103285Sikob} 2533103285Sikob 2534103285Sikobstatic void 2535103285Sikobsbp_abort_all_ocbs(struct sbp_dev *sdev, int status) 2536103285Sikob{ 2537103285Sikob int s; 2538105792Ssimokawa struct sbp_ocb *ocb, *next; 2539105792Ssimokawa STAILQ_HEAD(, sbp_ocb) temp; 2540103285Sikob 2541103285Sikob s = splfw(); 2542105792Ssimokawa 2543105792Ssimokawa bcopy(&sdev->ocbs, &temp, sizeof(temp)); 2544105792Ssimokawa STAILQ_INIT(&sdev->ocbs); 2545105792Ssimokawa for (ocb = STAILQ_FIRST(&temp); ocb != NULL; ocb = next) { 2546105792Ssimokawa next = STAILQ_NEXT(ocb, ocb); 2547103285Sikob sbp_abort_ocb(ocb, status); 2548103285Sikob } 2549105792Ssimokawa 2550103285Sikob splx(s); 2551103285Sikob} 2552103285Sikob 2553103285Sikobstatic devclass_t sbp_devclass; 2554103285Sikob 2555103285Sikobstatic device_method_t sbp_methods[] = { 2556103285Sikob /* device interface */ 2557103285Sikob DEVMETHOD(device_identify, sbp_identify), 2558103285Sikob DEVMETHOD(device_probe, sbp_probe), 2559103285Sikob DEVMETHOD(device_attach, sbp_attach), 2560103285Sikob DEVMETHOD(device_detach, sbp_detach), 2561110145Ssimokawa DEVMETHOD(device_shutdown, sbp_shutdown), 2562103285Sikob 2563103285Sikob { 0, 0 } 2564103285Sikob}; 2565103285Sikob 2566103285Sikobstatic driver_t sbp_driver = { 2567103285Sikob "sbp", 2568103285Sikob sbp_methods, 2569103285Sikob sizeof(struct sbp_softc), 2570103285Sikob}; 2571103285SikobDRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0); 2572103285SikobMODULE_VERSION(sbp, 1); 2573103285SikobMODULE_DEPEND(sbp, firewire, 1, 1, 1); 2574103285SikobMODULE_DEPEND(sbp, cam, 1, 1, 1); 2575