1c3aac50fSPeter Wemm /* $FreeBSD$ */ 26054c3f6SMatt Jacob /* 36054c3f6SMatt Jacob * Platform (FreeBSD) dependent common attachment code for Qlogic adapters. 46054c3f6SMatt Jacob * 56054c3f6SMatt Jacob *--------------------------------------- 602ab3379SMatt Jacob * Copyright (c) 1997, 1998, 1999 by Matthew Jacob 76054c3f6SMatt Jacob * NASA/Ames Research Center 86054c3f6SMatt Jacob * All rights reserved. 96054c3f6SMatt Jacob *--------------------------------------- 106054c3f6SMatt Jacob * 116054c3f6SMatt Jacob * Redistribution and use in source and binary forms, with or without 126054c3f6SMatt Jacob * modification, are permitted provided that the following conditions 136054c3f6SMatt Jacob * are met: 146054c3f6SMatt Jacob * 1. Redistributions of source code must retain the above copyright 156054c3f6SMatt Jacob * notice immediately at the beginning of the file, without modification, 166054c3f6SMatt Jacob * this list of conditions, and the following disclaimer. 176054c3f6SMatt Jacob * 2. Redistributions in binary form must reproduce the above copyright 186054c3f6SMatt Jacob * notice, this list of conditions and the following disclaimer in the 196054c3f6SMatt Jacob * documentation and/or other materials provided with the distribution. 206054c3f6SMatt Jacob * 3. The name of the author may not be used to endorse or promote products 216054c3f6SMatt Jacob * derived from this software without specific prior written permission. 226054c3f6SMatt Jacob * 236054c3f6SMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 246054c3f6SMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 256054c3f6SMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 266054c3f6SMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 276054c3f6SMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 286054c3f6SMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 296054c3f6SMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 306054c3f6SMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 316054c3f6SMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 326054c3f6SMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 336054c3f6SMatt Jacob * SUCH DAMAGE. 346054c3f6SMatt Jacob */ 356054c3f6SMatt Jacob #include <dev/isp/isp_freebsd.h> 366054c3f6SMatt Jacob 370470d791SMatt Jacob static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *); 380470d791SMatt Jacob static void isp_poll(struct cam_sim *); 390470d791SMatt Jacob static void isp_relsim(void *); 40cc8df88bSMatt Jacob static timeout_t isp_timeout; 41d81ba9d5SMatt Jacob static void isp_action(struct cam_sim *, union ccb *); 420470d791SMatt Jacob 43cc8df88bSMatt Jacob 44d81ba9d5SMatt Jacob static struct ispsoftc *isplist = NULL; 450470d791SMatt Jacob /* #define ISP_LUN0_ONLY 1 */ 4622e1dc85SMatt Jacob #ifdef DEBUG 4722e1dc85SMatt Jacob int isp_debug = 2; 4822e1dc85SMatt Jacob #elif defined(CAMDEBUG) || defined(DIAGNOSTIC) 49ab6c4b31SMatt Jacob int isp_debug = 1; 50ab6c4b31SMatt Jacob #else 51ab6c4b31SMatt Jacob int isp_debug = 0; 520470d791SMatt Jacob #endif 53478f8a96SJustin T. Gibbs 54478f8a96SJustin T. Gibbs void 55c3055363SMatt Jacob isp_attach(struct ispsoftc *isp) 56478f8a96SJustin T. Gibbs { 57ea6f23cdSMatt Jacob int primary, secondary; 58478f8a96SJustin T. Gibbs struct ccb_setasync csa; 59478f8a96SJustin T. Gibbs struct cam_devq *devq; 60ea6f23cdSMatt Jacob struct cam_sim *sim; 61ea6f23cdSMatt Jacob struct cam_path *path; 62478f8a96SJustin T. Gibbs 63478f8a96SJustin T. Gibbs /* 64ea6f23cdSMatt Jacob * Establish (in case of 12X0) which bus is the primary. 65ea6f23cdSMatt Jacob */ 66ea6f23cdSMatt Jacob 67ea6f23cdSMatt Jacob primary = 0; 68ea6f23cdSMatt Jacob secondary = 1; 69ea6f23cdSMatt Jacob 70ea6f23cdSMatt Jacob /* 71ea6f23cdSMatt Jacob * Create the device queue for our SIM(s). 72478f8a96SJustin T. Gibbs */ 73ab6c4b31SMatt Jacob devq = cam_simq_alloc(isp->isp_maxcmds); 74478f8a96SJustin T. Gibbs if (devq == NULL) { 75478f8a96SJustin T. Gibbs return; 76478f8a96SJustin T. Gibbs } 77478f8a96SJustin T. Gibbs 78478f8a96SJustin T. Gibbs /* 79ea6f23cdSMatt Jacob * Construct our SIM entry. 80478f8a96SJustin T. Gibbs */ 81ea6f23cdSMatt Jacob sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, 82ab6c4b31SMatt Jacob isp->isp_unit, 1, isp->isp_maxcmds, devq); 83ea6f23cdSMatt Jacob if (sim == NULL) { 84478f8a96SJustin T. Gibbs cam_simq_free(devq); 85478f8a96SJustin T. Gibbs return; 86478f8a96SJustin T. Gibbs } 87ea6f23cdSMatt Jacob if (xpt_bus_register(sim, primary) != CAM_SUCCESS) { 88ea6f23cdSMatt Jacob cam_sim_free(sim, TRUE); 89478f8a96SJustin T. Gibbs return; 90478f8a96SJustin T. Gibbs } 91478f8a96SJustin T. Gibbs 92ea6f23cdSMatt Jacob if (xpt_create_path(&path, NULL, cam_sim_path(sim), 93478f8a96SJustin T. Gibbs CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 94ea6f23cdSMatt Jacob xpt_bus_deregister(cam_sim_path(sim)); 95ea6f23cdSMatt Jacob cam_sim_free(sim, TRUE); 96478f8a96SJustin T. Gibbs return; 97478f8a96SJustin T. Gibbs } 98478f8a96SJustin T. Gibbs 99ea6f23cdSMatt Jacob xpt_setup_ccb(&csa.ccb_h, path, 5); 100478f8a96SJustin T. Gibbs csa.ccb_h.func_code = XPT_SASYNC_CB; 101478f8a96SJustin T. Gibbs csa.event_enable = AC_LOST_DEVICE; 102cbf57b47SMatt Jacob csa.callback = isp_cam_async; 103ea6f23cdSMatt Jacob csa.callback_arg = sim; 104478f8a96SJustin T. Gibbs xpt_action((union ccb *)&csa); 105ea6f23cdSMatt Jacob isp->isp_sim = sim; 106ea6f23cdSMatt Jacob isp->isp_path = path; 107478f8a96SJustin T. Gibbs 108ea6f23cdSMatt Jacob /* 109ea6f23cdSMatt Jacob * If we have a second channel, construct SIM entry for that. 110ea6f23cdSMatt Jacob */ 11122e1dc85SMatt Jacob if (IS_DUALBUS(isp)) { 112ea6f23cdSMatt Jacob sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, 113ab6c4b31SMatt Jacob isp->isp_unit, 1, isp->isp_maxcmds, devq); 114ea6f23cdSMatt Jacob if (sim == NULL) { 115ea6f23cdSMatt Jacob xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 116ea6f23cdSMatt Jacob xpt_free_path(isp->isp_path); 117ea6f23cdSMatt Jacob cam_simq_free(devq); 118ea6f23cdSMatt Jacob return; 119ea6f23cdSMatt Jacob } 120ea6f23cdSMatt Jacob if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) { 121ea6f23cdSMatt Jacob xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 122ea6f23cdSMatt Jacob xpt_free_path(isp->isp_path); 123ea6f23cdSMatt Jacob cam_sim_free(sim, TRUE); 124ea6f23cdSMatt Jacob return; 125ea6f23cdSMatt Jacob } 126ea6f23cdSMatt Jacob 127ea6f23cdSMatt Jacob if (xpt_create_path(&path, NULL, cam_sim_path(sim), 128ea6f23cdSMatt Jacob CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 129ea6f23cdSMatt Jacob xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 130ea6f23cdSMatt Jacob xpt_free_path(isp->isp_path); 131ea6f23cdSMatt Jacob xpt_bus_deregister(cam_sim_path(sim)); 132ea6f23cdSMatt Jacob cam_sim_free(sim, TRUE); 133ea6f23cdSMatt Jacob return; 134ea6f23cdSMatt Jacob } 135ea6f23cdSMatt Jacob 136ea6f23cdSMatt Jacob xpt_setup_ccb(&csa.ccb_h, path, 5); 137ea6f23cdSMatt Jacob csa.ccb_h.func_code = XPT_SASYNC_CB; 138ea6f23cdSMatt Jacob csa.event_enable = AC_LOST_DEVICE; 139ea6f23cdSMatt Jacob csa.callback = isp_cam_async; 140ea6f23cdSMatt Jacob csa.callback_arg = sim; 141ea6f23cdSMatt Jacob xpt_action((union ccb *)&csa); 142ea6f23cdSMatt Jacob isp->isp_sim2 = sim; 143ea6f23cdSMatt Jacob isp->isp_path2 = path; 144ea6f23cdSMatt Jacob } 145478f8a96SJustin T. Gibbs isp->isp_state = ISP_RUNSTATE; 146d81ba9d5SMatt Jacob if (isplist == NULL) { 147d81ba9d5SMatt Jacob isplist = isp; 148d81ba9d5SMatt Jacob } else { 149d81ba9d5SMatt Jacob struct ispsoftc *tmp = isplist; 150d81ba9d5SMatt Jacob while (tmp->isp_osinfo.next) { 151d81ba9d5SMatt Jacob tmp = tmp->isp_osinfo.next; 152d81ba9d5SMatt Jacob } 153d81ba9d5SMatt Jacob tmp->isp_osinfo.next = isp; 154478f8a96SJustin T. Gibbs } 1550470d791SMatt Jacob } 156478f8a96SJustin T. Gibbs 157d81ba9d5SMatt Jacob 158d81ba9d5SMatt Jacob /* 159d81ba9d5SMatt Jacob * Put the target mode functions here, because some are inlines 160d81ba9d5SMatt Jacob */ 161d81ba9d5SMatt Jacob 162d81ba9d5SMatt Jacob #ifdef ISP_TARGET_MODE 163d81ba9d5SMatt Jacob #include "targbh.h" 164d81ba9d5SMatt Jacob 165d81ba9d5SMatt Jacob static __inline int is_lun_enabled(struct ispsoftc *, lun_id_t); 166d81ba9d5SMatt Jacob static __inline int are_any_luns_enabled(struct ispsoftc *); 167d81ba9d5SMatt Jacob static __inline tstate_t *get_lun_statep(struct ispsoftc *, lun_id_t); 168d81ba9d5SMatt Jacob static __inline void rls_lun_statep(struct ispsoftc *, tstate_t *); 169d81ba9d5SMatt Jacob static __inline int isp_psema_sig_rqe(struct ispsoftc *); 170d81ba9d5SMatt Jacob static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *, int); 171d81ba9d5SMatt Jacob static __inline void isp_cv_signal_rqe(struct ispsoftc *, int); 172d81ba9d5SMatt Jacob static __inline void isp_vsema_rqe(struct ispsoftc *); 173d81ba9d5SMatt Jacob static cam_status 174d81ba9d5SMatt Jacob create_lun_state(struct ispsoftc *, struct cam_path *, tstate_t **); 175d81ba9d5SMatt Jacob static void destroy_lun_state(struct ispsoftc *, tstate_t *); 176d81ba9d5SMatt Jacob static void isp_en_lun(struct ispsoftc *, union ccb *); 177d81ba9d5SMatt Jacob static cam_status isp_abort_tgt_ccb(struct ispsoftc *, union ccb *); 178d81ba9d5SMatt Jacob static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *); 179d81ba9d5SMatt Jacob 180d81ba9d5SMatt Jacob 181d81ba9d5SMatt Jacob static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *); 182d81ba9d5SMatt Jacob static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *); 183d81ba9d5SMatt Jacob static int isp_handle_platform_ctio(struct ispsoftc *, void *); 184d81ba9d5SMatt Jacob 185d81ba9d5SMatt Jacob static __inline int 186d81ba9d5SMatt Jacob is_lun_enabled(struct ispsoftc *isp, lun_id_t lun) 187d81ba9d5SMatt Jacob { 188d81ba9d5SMatt Jacob tstate_t *tptr; 189d81ba9d5SMatt Jacob int s = splsoftcam(); 190d81ba9d5SMatt Jacob if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) { 191d81ba9d5SMatt Jacob splx(s); 192d81ba9d5SMatt Jacob return (0); 193d81ba9d5SMatt Jacob } 194d81ba9d5SMatt Jacob do { 195d81ba9d5SMatt Jacob if (tptr->lun == (lun_id_t) lun) { 196d81ba9d5SMatt Jacob splx(s); 197d81ba9d5SMatt Jacob return (1); 198d81ba9d5SMatt Jacob } 199d81ba9d5SMatt Jacob } while ((tptr = tptr->next) != NULL); 200d81ba9d5SMatt Jacob splx(s); 201d81ba9d5SMatt Jacob return (0); 202d81ba9d5SMatt Jacob } 203d81ba9d5SMatt Jacob 204d81ba9d5SMatt Jacob static __inline int 205d81ba9d5SMatt Jacob are_any_luns_enabled(struct ispsoftc *isp) 206d81ba9d5SMatt Jacob { 207d81ba9d5SMatt Jacob int i; 208d81ba9d5SMatt Jacob for (i = 0; i < LUN_HASH_SIZE; i++) { 209d81ba9d5SMatt Jacob if (isp->isp_osinfo.lun_hash[i]) { 210d81ba9d5SMatt Jacob return (1); 211d81ba9d5SMatt Jacob } 212d81ba9d5SMatt Jacob } 213d81ba9d5SMatt Jacob return (0); 214d81ba9d5SMatt Jacob } 215d81ba9d5SMatt Jacob 216d81ba9d5SMatt Jacob static __inline tstate_t * 217d81ba9d5SMatt Jacob get_lun_statep(struct ispsoftc *isp, lun_id_t lun) 218d81ba9d5SMatt Jacob { 219d81ba9d5SMatt Jacob tstate_t *tptr; 220d81ba9d5SMatt Jacob int s; 221d81ba9d5SMatt Jacob 222d81ba9d5SMatt Jacob s = splsoftcam(); 223d81ba9d5SMatt Jacob if (lun == CAM_LUN_WILDCARD) { 224d81ba9d5SMatt Jacob tptr = &isp->isp_osinfo.tsdflt; 225d81ba9d5SMatt Jacob tptr->hold++; 226d81ba9d5SMatt Jacob splx(s); 227d81ba9d5SMatt Jacob return (tptr); 228d81ba9d5SMatt Jacob } else { 229d81ba9d5SMatt Jacob tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]; 230d81ba9d5SMatt Jacob } 231d81ba9d5SMatt Jacob if (tptr == NULL) { 232d81ba9d5SMatt Jacob splx(s); 233d81ba9d5SMatt Jacob return (NULL); 234d81ba9d5SMatt Jacob } 235d81ba9d5SMatt Jacob 236d81ba9d5SMatt Jacob do { 237d81ba9d5SMatt Jacob if (tptr->lun == lun) { 238d81ba9d5SMatt Jacob tptr->hold++; 239d81ba9d5SMatt Jacob splx(s); 240d81ba9d5SMatt Jacob return (tptr); 241d81ba9d5SMatt Jacob } 242d81ba9d5SMatt Jacob } while ((tptr = tptr->next) != NULL); 243d81ba9d5SMatt Jacob splx(s); 244d81ba9d5SMatt Jacob return (tptr); 245d81ba9d5SMatt Jacob } 246d81ba9d5SMatt Jacob 247d81ba9d5SMatt Jacob static __inline void 248d81ba9d5SMatt Jacob rls_lun_statep(struct ispsoftc *isp, tstate_t *tptr) 249d81ba9d5SMatt Jacob { 250d81ba9d5SMatt Jacob if (tptr->hold) 251d81ba9d5SMatt Jacob tptr->hold--; 252d81ba9d5SMatt Jacob } 253d81ba9d5SMatt Jacob 254d81ba9d5SMatt Jacob static __inline int 255d81ba9d5SMatt Jacob isp_psema_sig_rqe(struct ispsoftc *isp) 256d81ba9d5SMatt Jacob { 257d81ba9d5SMatt Jacob int s = splcam(); 258d81ba9d5SMatt Jacob while (isp->isp_osinfo.tmflags & TM_BUSY) { 259d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags |= TM_WANTED; 260d81ba9d5SMatt Jacob if (tsleep(&isp->isp_osinfo.tmflags, PRIBIO|PCATCH, "i0", 0)) { 261d81ba9d5SMatt Jacob splx(s); 262d81ba9d5SMatt Jacob return (-1); 263d81ba9d5SMatt Jacob } 264d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags |= TM_BUSY; 265d81ba9d5SMatt Jacob } 266d81ba9d5SMatt Jacob splx(s); 267d81ba9d5SMatt Jacob return (0); 268d81ba9d5SMatt Jacob } 269d81ba9d5SMatt Jacob 270d81ba9d5SMatt Jacob static __inline int 271d81ba9d5SMatt Jacob isp_cv_wait_timed_rqe(struct ispsoftc *isp, int timo) 272d81ba9d5SMatt Jacob { 273d81ba9d5SMatt Jacob int s = splcam(); 274d81ba9d5SMatt Jacob if (tsleep(&isp->isp_osinfo.rstatus, PRIBIO, "qt1", timo)) { 275d81ba9d5SMatt Jacob splx(s); 276d81ba9d5SMatt Jacob return (-1); 277d81ba9d5SMatt Jacob } 278d81ba9d5SMatt Jacob splx(s); 279d81ba9d5SMatt Jacob return (0); 280d81ba9d5SMatt Jacob } 281d81ba9d5SMatt Jacob 282d81ba9d5SMatt Jacob static __inline void 283d81ba9d5SMatt Jacob isp_cv_signal_rqe(struct ispsoftc *isp, int status) 284d81ba9d5SMatt Jacob { 285d81ba9d5SMatt Jacob isp->isp_osinfo.rstatus = status; 286d81ba9d5SMatt Jacob wakeup(&isp->isp_osinfo.rstatus); 287d81ba9d5SMatt Jacob } 288d81ba9d5SMatt Jacob 289d81ba9d5SMatt Jacob static __inline void 290d81ba9d5SMatt Jacob isp_vsema_rqe(struct ispsoftc *isp) 291d81ba9d5SMatt Jacob { 292d81ba9d5SMatt Jacob int s = splcam(); 293d81ba9d5SMatt Jacob if (isp->isp_osinfo.tmflags & TM_WANTED) { 294d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags &= ~TM_WANTED; 295d81ba9d5SMatt Jacob wakeup(&isp->isp_osinfo.tmflags); 296d81ba9d5SMatt Jacob } 297d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags &= ~TM_BUSY; 298d81ba9d5SMatt Jacob splx(s); 299d81ba9d5SMatt Jacob } 300d81ba9d5SMatt Jacob 301d81ba9d5SMatt Jacob static cam_status 302d81ba9d5SMatt Jacob create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt) 303d81ba9d5SMatt Jacob { 304d81ba9d5SMatt Jacob int s; 305d81ba9d5SMatt Jacob cam_status status; 306d81ba9d5SMatt Jacob lun_id_t lun; 307d81ba9d5SMatt Jacob tstate_t *tptr, *new; 308d81ba9d5SMatt Jacob 309d81ba9d5SMatt Jacob lun = xpt_path_lun_id(path); 310d81ba9d5SMatt Jacob if (lun < 0) { 311d81ba9d5SMatt Jacob return (CAM_LUN_INVALID); 312d81ba9d5SMatt Jacob } 313d81ba9d5SMatt Jacob if (is_lun_enabled(isp, lun)) { 314d81ba9d5SMatt Jacob return (CAM_LUN_ALRDY_ENA); 315d81ba9d5SMatt Jacob } 316d81ba9d5SMatt Jacob new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT); 317d81ba9d5SMatt Jacob if (new == NULL) { 318d81ba9d5SMatt Jacob return (CAM_RESRC_UNAVAIL); 319d81ba9d5SMatt Jacob } 320d81ba9d5SMatt Jacob bzero(new, sizeof (tstate_t)); 321d81ba9d5SMatt Jacob 322d81ba9d5SMatt Jacob status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path), 323d81ba9d5SMatt Jacob xpt_path_target_id(path), xpt_path_lun_id(path)); 324d81ba9d5SMatt Jacob if (status != CAM_REQ_CMP) { 325d81ba9d5SMatt Jacob free(new, M_DEVBUF); 326d81ba9d5SMatt Jacob return (status); 327d81ba9d5SMatt Jacob } 328d81ba9d5SMatt Jacob new->lun = lun; 329d81ba9d5SMatt Jacob SLIST_INIT(&new->atios); 330d81ba9d5SMatt Jacob SLIST_INIT(&new->inots); 331d81ba9d5SMatt Jacob new->hold = 1; 332d81ba9d5SMatt Jacob 333d81ba9d5SMatt Jacob s = splsoftcam(); 334d81ba9d5SMatt Jacob if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) { 335d81ba9d5SMatt Jacob isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)] = new; 336d81ba9d5SMatt Jacob } else { 337d81ba9d5SMatt Jacob while (tptr->next) 338d81ba9d5SMatt Jacob tptr = tptr->next; 339d81ba9d5SMatt Jacob tptr->next = new; 340d81ba9d5SMatt Jacob } 341d81ba9d5SMatt Jacob splx(s); 342d81ba9d5SMatt Jacob *rslt = new; 343d81ba9d5SMatt Jacob return (CAM_REQ_CMP); 344d81ba9d5SMatt Jacob } 345d81ba9d5SMatt Jacob 346d81ba9d5SMatt Jacob static __inline void 347d81ba9d5SMatt Jacob destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr) 348d81ba9d5SMatt Jacob { 349d81ba9d5SMatt Jacob tstate_t *lw, *pw; 350d81ba9d5SMatt Jacob int s; 351d81ba9d5SMatt Jacob 352d81ba9d5SMatt Jacob s = splsoftcam(); 353d81ba9d5SMatt Jacob if (tptr->hold) { 354d81ba9d5SMatt Jacob splx(s); 355d81ba9d5SMatt Jacob return; 356d81ba9d5SMatt Jacob } 357d81ba9d5SMatt Jacob pw = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)]; 358d81ba9d5SMatt Jacob if (pw == NULL) { 359d81ba9d5SMatt Jacob splx(s); 360d81ba9d5SMatt Jacob return; 361d81ba9d5SMatt Jacob } else if (pw->lun == tptr->lun) { 362d81ba9d5SMatt Jacob isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)] = pw->next; 363d81ba9d5SMatt Jacob } else { 364d81ba9d5SMatt Jacob lw = pw; 365d81ba9d5SMatt Jacob pw = lw->next; 366d81ba9d5SMatt Jacob while (pw) { 367d81ba9d5SMatt Jacob if (pw->lun == tptr->lun) { 368d81ba9d5SMatt Jacob lw->next = pw->next; 369d81ba9d5SMatt Jacob break; 370d81ba9d5SMatt Jacob } 371d81ba9d5SMatt Jacob lw = pw; 372d81ba9d5SMatt Jacob pw = pw->next; 373d81ba9d5SMatt Jacob } 374d81ba9d5SMatt Jacob if (pw == NULL) { 375d81ba9d5SMatt Jacob splx(s); 376d81ba9d5SMatt Jacob return; 377d81ba9d5SMatt Jacob } 378d81ba9d5SMatt Jacob } 379d81ba9d5SMatt Jacob free(tptr, M_DEVBUF); 380d81ba9d5SMatt Jacob splx(s); 381d81ba9d5SMatt Jacob } 382d81ba9d5SMatt Jacob 383d81ba9d5SMatt Jacob static void 384d81ba9d5SMatt Jacob isp_en_lun(struct ispsoftc *isp, union ccb *ccb) 385d81ba9d5SMatt Jacob { 386d81ba9d5SMatt Jacob const char *lfmt = "Lun now %sabled for target mode\n"; 387d81ba9d5SMatt Jacob struct ccb_en_lun *cel = &ccb->cel; 388d81ba9d5SMatt Jacob tstate_t *tptr; 389d81ba9d5SMatt Jacob u_int16_t rstat; 390d81ba9d5SMatt Jacob int bus, s; 391d81ba9d5SMatt Jacob lun_id_t lun; 392d81ba9d5SMatt Jacob target_id_t tgt; 393d81ba9d5SMatt Jacob 394d81ba9d5SMatt Jacob 395d81ba9d5SMatt Jacob bus = XS_CHANNEL(ccb); 396d81ba9d5SMatt Jacob tgt = ccb->ccb_h.target_id; 397d81ba9d5SMatt Jacob lun = ccb->ccb_h.target_lun; 398d81ba9d5SMatt Jacob 399d81ba9d5SMatt Jacob /* 400d81ba9d5SMatt Jacob * First, check to see if we're enabling on fibre channel 401d81ba9d5SMatt Jacob * and don't yet have a notion of who the heck we are (no 402d81ba9d5SMatt Jacob * loop yet). We do this by 403d81ba9d5SMatt Jacob */ 404d81ba9d5SMatt Jacob if (IS_FC(isp) && cel->enable && 405d81ba9d5SMatt Jacob (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) { 406d81ba9d5SMatt Jacob int rv; 407d81ba9d5SMatt Jacob fcparam *fcp = isp->isp_param; 408d81ba9d5SMatt Jacob 409d81ba9d5SMatt Jacob s = splcam(); 410d81ba9d5SMatt Jacob rv = isp_control(isp, ISPCTL_FCLINK_TEST, NULL); 411d81ba9d5SMatt Jacob (void) splx(s); 412d81ba9d5SMatt Jacob if (rv || fcp->isp_fwstate != FW_READY) { 413d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 414d81ba9d5SMatt Jacob printf("link status not good yet\n"); 415d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 416d81ba9d5SMatt Jacob return; 417d81ba9d5SMatt Jacob } 418d81ba9d5SMatt Jacob s = splcam(); 419d81ba9d5SMatt Jacob rv = isp_control(isp, ISPCTL_PDB_SYNC, NULL); 420d81ba9d5SMatt Jacob (void) splx(s); 421d81ba9d5SMatt Jacob if (rv || fcp->isp_loopstate != LOOP_READY) { 422d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 423d81ba9d5SMatt Jacob printf("could not get a good port database\n"); 424d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 425d81ba9d5SMatt Jacob return; 426d81ba9d5SMatt Jacob } 427d81ba9d5SMatt Jacob } 428d81ba9d5SMatt Jacob 429d81ba9d5SMatt Jacob 430d81ba9d5SMatt Jacob /* 431d81ba9d5SMatt Jacob * Next check to see whether this is a target/lun wildcard action. 432d81ba9d5SMatt Jacob * 433d81ba9d5SMatt Jacob * If so, we enable/disable target mode but don't do any lun enabling. 434d81ba9d5SMatt Jacob */ 435d81ba9d5SMatt Jacob if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) { 436d81ba9d5SMatt Jacob int av; 437d81ba9d5SMatt Jacob tptr = &isp->isp_osinfo.tsdflt; 438d81ba9d5SMatt Jacob if (cel->enable) { 439d81ba9d5SMatt Jacob if (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) { 440d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; 441d81ba9d5SMatt Jacob return; 442d81ba9d5SMatt Jacob } 443d81ba9d5SMatt Jacob ccb->ccb_h.status = 444d81ba9d5SMatt Jacob xpt_create_path(&tptr->owner, NULL, 445d81ba9d5SMatt Jacob xpt_path_path_id(ccb->ccb_h.path), 446d81ba9d5SMatt Jacob xpt_path_target_id(ccb->ccb_h.path), 447d81ba9d5SMatt Jacob xpt_path_lun_id(ccb->ccb_h.path)); 448d81ba9d5SMatt Jacob if (ccb->ccb_h.status != CAM_REQ_CMP) { 449d81ba9d5SMatt Jacob return; 450d81ba9d5SMatt Jacob } 451d81ba9d5SMatt Jacob SLIST_INIT(&tptr->atios); 452d81ba9d5SMatt Jacob SLIST_INIT(&tptr->inots); 453d81ba9d5SMatt Jacob av = 1; 454d81ba9d5SMatt Jacob s = splcam(); 455d81ba9d5SMatt Jacob av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); 456d81ba9d5SMatt Jacob if (av) { 457d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 458d81ba9d5SMatt Jacob xpt_free_path(tptr->owner); 459d81ba9d5SMatt Jacob splx(s); 460d81ba9d5SMatt Jacob return; 461d81ba9d5SMatt Jacob } 462d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED; 463d81ba9d5SMatt Jacob splx(s); 464d81ba9d5SMatt Jacob } else { 465d81ba9d5SMatt Jacob if ((isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) { 466d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 467d81ba9d5SMatt Jacob return; 468d81ba9d5SMatt Jacob } 469d81ba9d5SMatt Jacob if (are_any_luns_enabled(isp)) { 470d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_SCSI_BUSY; 471d81ba9d5SMatt Jacob return; 472d81ba9d5SMatt Jacob } 473d81ba9d5SMatt Jacob av = 0; 474d81ba9d5SMatt Jacob s = splcam(); 475d81ba9d5SMatt Jacob av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); 476d81ba9d5SMatt Jacob if (av) { 477d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 478d81ba9d5SMatt Jacob splx(s); 479d81ba9d5SMatt Jacob return; 480d81ba9d5SMatt Jacob } 481d81ba9d5SMatt Jacob isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED; 482d81ba9d5SMatt Jacob splx(s); 483d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP; 484d81ba9d5SMatt Jacob } 485d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 486d81ba9d5SMatt Jacob printf(lfmt, (cel->enable) ? "en" : "dis"); 487d81ba9d5SMatt Jacob return; 488d81ba9d5SMatt Jacob } 489d81ba9d5SMatt Jacob 490d81ba9d5SMatt Jacob /* 491d81ba9d5SMatt Jacob * Do some sanity checking first. 492d81ba9d5SMatt Jacob */ 493d81ba9d5SMatt Jacob 494d81ba9d5SMatt Jacob if (IS_SCSI(isp)) { 495d81ba9d5SMatt Jacob if (lun < 0 || lun >= 32) { 496d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 497d81ba9d5SMatt Jacob return; 498d81ba9d5SMatt Jacob } 499d81ba9d5SMatt Jacob if (tgt != CAM_TARGET_WILDCARD && 500d81ba9d5SMatt Jacob tgt != ((sdparam *) isp->isp_param)->isp_initiator_id) { 501d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_TID_INVALID; 502d81ba9d5SMatt Jacob return; 503d81ba9d5SMatt Jacob } 504d81ba9d5SMatt Jacob } else { 505d81ba9d5SMatt Jacob #ifdef ISP2100_SCCLUN 506d81ba9d5SMatt Jacob if (lun < 0 || lun >= 65536) { 507d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 508d81ba9d5SMatt Jacob return; 50992a1e549SMatt Jacob } 510d81ba9d5SMatt Jacob #else 511d81ba9d5SMatt Jacob if (lun < 0 || lun >= 16) { 512d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 513d81ba9d5SMatt Jacob return; 514d81ba9d5SMatt Jacob } 515d81ba9d5SMatt Jacob #endif 516d81ba9d5SMatt Jacob if (tgt != CAM_TARGET_WILDCARD && 517d81ba9d5SMatt Jacob tgt != ((fcparam *) isp->isp_param)->isp_loopid) { 518d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_TID_INVALID; 519d81ba9d5SMatt Jacob return; 520d81ba9d5SMatt Jacob } 521d81ba9d5SMatt Jacob } 522d81ba9d5SMatt Jacob 523d81ba9d5SMatt Jacob 524d81ba9d5SMatt Jacob if (cel->enable) { 525d81ba9d5SMatt Jacob ccb->ccb_h.status = 526d81ba9d5SMatt Jacob create_lun_state(isp, ccb->ccb_h.path, &tptr); 527d81ba9d5SMatt Jacob if (ccb->ccb_h.status != CAM_REQ_CMP) { 528d81ba9d5SMatt Jacob return; 529d81ba9d5SMatt Jacob } 530d81ba9d5SMatt Jacob } else { 531d81ba9d5SMatt Jacob tptr = get_lun_statep(isp, lun); 532d81ba9d5SMatt Jacob if (tptr == NULL) { 533d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 534d81ba9d5SMatt Jacob return; 535d81ba9d5SMatt Jacob } 536d81ba9d5SMatt Jacob } 537d81ba9d5SMatt Jacob 538d81ba9d5SMatt Jacob if (isp_psema_sig_rqe(isp)) { 539d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 540d81ba9d5SMatt Jacob if (cel->enable) 541d81ba9d5SMatt Jacob destroy_lun_state(isp, tptr); 542d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 543d81ba9d5SMatt Jacob return; 544d81ba9d5SMatt Jacob } 545d81ba9d5SMatt Jacob 546d81ba9d5SMatt Jacob s = splcam(); 547d81ba9d5SMatt Jacob if (cel->enable) { 548d81ba9d5SMatt Jacob u_int32_t seq = isp->isp_osinfo.rollinfo++; 549d81ba9d5SMatt Jacob rstat = LUN_ERR; 550d81ba9d5SMatt Jacob if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) { 551d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 552d81ba9d5SMatt Jacob printf("isp_lun_cmd failed\n"); 553d81ba9d5SMatt Jacob goto out; 554d81ba9d5SMatt Jacob } 555d81ba9d5SMatt Jacob if (isp_cv_wait_timed_rqe(isp, 30 * hz)) { 556d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 557d81ba9d5SMatt Jacob printf("wait for ENABLE LUN timed out\n"); 558d81ba9d5SMatt Jacob goto out; 559d81ba9d5SMatt Jacob } 560d81ba9d5SMatt Jacob rstat = isp->isp_osinfo.rstatus; 561d81ba9d5SMatt Jacob if (rstat != LUN_OK) { 562d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 563d81ba9d5SMatt Jacob printf("ENABLE LUN returned 0x%x\n", rstat); 564d81ba9d5SMatt Jacob goto out; 565d81ba9d5SMatt Jacob } 566d81ba9d5SMatt Jacob } else { 567d81ba9d5SMatt Jacob u_int32_t seq; 568d81ba9d5SMatt Jacob 569d81ba9d5SMatt Jacob seq = isp->isp_osinfo.rollinfo++; 570d81ba9d5SMatt Jacob rstat = LUN_ERR; 571d81ba9d5SMatt Jacob 572d81ba9d5SMatt Jacob if (isp_lun_cmd(isp, -RQSTYPE_MODIFY_LUN, bus, tgt, lun, seq)) { 573d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 574d81ba9d5SMatt Jacob printf("isp_lun_cmd failed\n"); 575d81ba9d5SMatt Jacob goto out; 576d81ba9d5SMatt Jacob } 577d81ba9d5SMatt Jacob if (isp_cv_wait_timed_rqe(isp, 30 * hz)) { 578d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 579d81ba9d5SMatt Jacob printf("wait for MODIFY LUN timed out\n"); 580d81ba9d5SMatt Jacob goto out; 581d81ba9d5SMatt Jacob } 582d81ba9d5SMatt Jacob rstat = isp->isp_osinfo.rstatus; 583d81ba9d5SMatt Jacob if (rstat != LUN_OK) { 584d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 585d81ba9d5SMatt Jacob printf("MODIFY LUN returned 0x%x\n", rstat); 586d81ba9d5SMatt Jacob goto out; 587d81ba9d5SMatt Jacob } 588d81ba9d5SMatt Jacob rstat = LUN_ERR; 589d81ba9d5SMatt Jacob seq = isp->isp_osinfo.rollinfo++; 590d81ba9d5SMatt Jacob 591d81ba9d5SMatt Jacob if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, bus, tgt, lun, seq)) { 592d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 593d81ba9d5SMatt Jacob printf("isp_lun_cmd failed\n"); 594d81ba9d5SMatt Jacob goto out; 595d81ba9d5SMatt Jacob } 596d81ba9d5SMatt Jacob if (isp_cv_wait_timed_rqe(isp, 30 * hz)) { 597d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 598d81ba9d5SMatt Jacob printf("wait for ENABLE LUN timed out\n"); 599d81ba9d5SMatt Jacob goto out; 600d81ba9d5SMatt Jacob } 601d81ba9d5SMatt Jacob rstat = isp->isp_osinfo.rstatus; 602d81ba9d5SMatt Jacob if (rstat != LUN_OK) { 603d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 604d81ba9d5SMatt Jacob printf("ENABLE LUN returned 0x%x\n", rstat); 605d81ba9d5SMatt Jacob goto out; 606d81ba9d5SMatt Jacob } 607d81ba9d5SMatt Jacob } 608d81ba9d5SMatt Jacob out: 609d81ba9d5SMatt Jacob isp_vsema_rqe(isp); 610d81ba9d5SMatt Jacob splx(s); 611d81ba9d5SMatt Jacob 612d81ba9d5SMatt Jacob if (rstat != LUN_OK) { 613d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 614d81ba9d5SMatt Jacob printf("lun %sable failed\n", (cel->enable) ? "en" : "dis"); 615d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP_ERR; 616d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 617d81ba9d5SMatt Jacob if (cel->enable) 618d81ba9d5SMatt Jacob destroy_lun_state(isp, tptr); 619d81ba9d5SMatt Jacob } else { 620d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 621d81ba9d5SMatt Jacob printf(lfmt, (cel->enable) ? "en" : "dis"); 622d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 623d81ba9d5SMatt Jacob if (cel->enable == 0) { 624d81ba9d5SMatt Jacob destroy_lun_state(isp, tptr); 625d81ba9d5SMatt Jacob } 626d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_CMP; 627d81ba9d5SMatt Jacob } 628d81ba9d5SMatt Jacob } 629d81ba9d5SMatt Jacob 630d81ba9d5SMatt Jacob static cam_status 631d81ba9d5SMatt Jacob isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb) 632d81ba9d5SMatt Jacob { 633d81ba9d5SMatt Jacob tstate_t *tptr; 634d81ba9d5SMatt Jacob struct ccb_hdr_slist *lp; 635d81ba9d5SMatt Jacob struct ccb_hdr *curelm; 636d81ba9d5SMatt Jacob int found; 637d81ba9d5SMatt Jacob union ccb *accb = ccb->cab.abort_ccb; 638d81ba9d5SMatt Jacob 639d81ba9d5SMatt Jacob if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) { 640d81ba9d5SMatt Jacob if (IS_FC(isp) && (accb->ccb_h.target_id != 641d81ba9d5SMatt Jacob ((fcparam *) isp->isp_param)->isp_loopid)) { 642d81ba9d5SMatt Jacob return (CAM_PATH_INVALID); 643d81ba9d5SMatt Jacob } else if (IS_SCSI(isp) && (accb->ccb_h.target_id != 644d81ba9d5SMatt Jacob ((sdparam *) isp->isp_param)->isp_initiator_id)) { 645d81ba9d5SMatt Jacob return (CAM_PATH_INVALID); 646d81ba9d5SMatt Jacob } 647d81ba9d5SMatt Jacob } 648d81ba9d5SMatt Jacob tptr = get_lun_statep(isp, accb->ccb_h.target_lun); 649d81ba9d5SMatt Jacob if (tptr == NULL) { 650d81ba9d5SMatt Jacob return (CAM_PATH_INVALID); 651d81ba9d5SMatt Jacob } 652d81ba9d5SMatt Jacob if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 653d81ba9d5SMatt Jacob lp = &tptr->atios; 654d81ba9d5SMatt Jacob } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) { 655d81ba9d5SMatt Jacob lp = &tptr->inots; 656d81ba9d5SMatt Jacob } else { 657d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 658d81ba9d5SMatt Jacob return (CAM_UA_ABORT); 659d81ba9d5SMatt Jacob } 660d81ba9d5SMatt Jacob curelm = SLIST_FIRST(lp); 661d81ba9d5SMatt Jacob found = 0; 662d81ba9d5SMatt Jacob if (curelm == &accb->ccb_h) { 663d81ba9d5SMatt Jacob found = 1; 664d81ba9d5SMatt Jacob SLIST_REMOVE_HEAD(lp, sim_links.sle); 665d81ba9d5SMatt Jacob } else { 666d81ba9d5SMatt Jacob while(curelm != NULL) { 667d81ba9d5SMatt Jacob struct ccb_hdr *nextelm; 668d81ba9d5SMatt Jacob 669d81ba9d5SMatt Jacob nextelm = SLIST_NEXT(curelm, sim_links.sle); 670d81ba9d5SMatt Jacob if (nextelm == &accb->ccb_h) { 671d81ba9d5SMatt Jacob found = 1; 672d81ba9d5SMatt Jacob SLIST_NEXT(curelm, sim_links.sle) = 673d81ba9d5SMatt Jacob SLIST_NEXT(nextelm, sim_links.sle); 674d81ba9d5SMatt Jacob break; 675d81ba9d5SMatt Jacob } 676d81ba9d5SMatt Jacob curelm = nextelm; 677d81ba9d5SMatt Jacob } 678d81ba9d5SMatt Jacob } 679d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 680d81ba9d5SMatt Jacob if (found) { 681d81ba9d5SMatt Jacob accb->ccb_h.status = CAM_REQ_ABORTED; 682d81ba9d5SMatt Jacob return (CAM_REQ_CMP); 683d81ba9d5SMatt Jacob } 684d81ba9d5SMatt Jacob return(CAM_PATH_INVALID); 685d81ba9d5SMatt Jacob } 686d81ba9d5SMatt Jacob 687d81ba9d5SMatt Jacob static cam_status 688d81ba9d5SMatt Jacob isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) 689d81ba9d5SMatt Jacob { 690d81ba9d5SMatt Jacob void *qe; 69100a8e174SMatt Jacob struct ccb_scsiio *cso = &ccb->csio; 692d81ba9d5SMatt Jacob u_int32_t *hp, save_handle; 693d81ba9d5SMatt Jacob u_int16_t iptr, optr; 694d81ba9d5SMatt Jacob 695d81ba9d5SMatt Jacob if (isp_getrqentry(isp, &iptr, &optr, &qe)) { 69692a1e549SMatt Jacob xpt_print_path(ccb->ccb_h.path); 69792a1e549SMatt Jacob printf("Request Queue Overflow in isp_target_start_ctio\n"); 698d81ba9d5SMatt Jacob return (CAM_RESRC_UNAVAIL); 699d81ba9d5SMatt Jacob } 70092a1e549SMatt Jacob bzero(qe, QENTRY_LEN); 701d81ba9d5SMatt Jacob 702d81ba9d5SMatt Jacob /* 703d81ba9d5SMatt Jacob * We're either moving data or completing a command here. 704d81ba9d5SMatt Jacob */ 705d81ba9d5SMatt Jacob 706d81ba9d5SMatt Jacob if (IS_FC(isp)) { 707d81ba9d5SMatt Jacob ct2_entry_t *cto = qe; 70800a8e174SMatt Jacob u_int16_t *ssptr = NULL; 70900a8e174SMatt Jacob 710d81ba9d5SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 711d81ba9d5SMatt Jacob cto->ct_header.rqs_entry_count = 1; 71200a8e174SMatt Jacob cto->ct_iid = cso->init_id; 71392a1e549SMatt Jacob #ifndef ISP2100_SCCLUN 714d81ba9d5SMatt Jacob cto->ct_lun = ccb->ccb_h.target_lun; 715d81ba9d5SMatt Jacob #endif 71600a8e174SMatt Jacob cto->ct_rxid = cso->tag_id; 71700a8e174SMatt Jacob cto->ct_flags = CT2_CCINCR; 71800a8e174SMatt Jacob if (cso->dxfer_len == 0) { 71900a8e174SMatt Jacob cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA; 72000a8e174SMatt Jacob KASSERT(ccb->ccb_h.flags & CAM_SEND_STATUS, 72100a8e174SMatt Jacob ("a CTIO with no data and no status?")); 72200a8e174SMatt Jacob cto->ct_flags |= CT2_SENDSTATUS; 72300a8e174SMatt Jacob ssptr = &cto->rsp.m1.ct_scsi_status; 72400a8e174SMatt Jacob *ssptr = cso->scsi_status; 72500a8e174SMatt Jacob if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) { 72600a8e174SMatt Jacob int m = min(cso->sense_len, MAXRESPLEN); 72700a8e174SMatt Jacob bcopy(&cso->sense_data, cto->rsp.m1.ct_resp, m); 72800a8e174SMatt Jacob cto->rsp.m1.ct_senselen = m; 72900a8e174SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; 73000a8e174SMatt Jacob } 73100a8e174SMatt Jacob } else { 73200a8e174SMatt Jacob cto->ct_flags |= CT2_FLAG_MODE0; 73300a8e174SMatt Jacob if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 73400a8e174SMatt Jacob cto->ct_flags |= CT2_DATA_IN; 73500a8e174SMatt Jacob } else { 73600a8e174SMatt Jacob cto->ct_flags |= CT2_DATA_OUT; 737d81ba9d5SMatt Jacob } 738d81ba9d5SMatt Jacob if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 73900a8e174SMatt Jacob ssptr = &cto->rsp.m0.ct_scsi_status; 740d81ba9d5SMatt Jacob cto->ct_flags |= CT2_SENDSTATUS; 74100a8e174SMatt Jacob cto->rsp.m0.ct_scsi_status = cso->scsi_status; 742d81ba9d5SMatt Jacob } 74300a8e174SMatt Jacob ccb->ccb_h.flags &= ~CAM_SEND_SENSE; 74400a8e174SMatt Jacob } 74500a8e174SMatt Jacob if (ssptr && cso->resid) { 74600a8e174SMatt Jacob cto->ct_resid = cso->resid; 74700a8e174SMatt Jacob if (cso->resid < 0) 74800a8e174SMatt Jacob *ssptr |= CT2_DATA_OVER; 74900a8e174SMatt Jacob else 75000a8e174SMatt Jacob *ssptr |= CT2_DATA_UNDER; 75100a8e174SMatt Jacob } 752d667c06cSMatt Jacob if (isp_tdebug > 1 && ssptr && 75300a8e174SMatt Jacob (cso->scsi_status != SCSI_STATUS_OK || cso->resid)) { 75492a1e549SMatt Jacob printf("%s:CTIO2 RX_ID 0x%x SCSI STATUS 0x%x " 75592a1e549SMatt Jacob "resid %d\n", isp->isp_name, cto->ct_rxid, 75600a8e174SMatt Jacob cso->scsi_status, cso->resid); 757d81ba9d5SMatt Jacob } 758d81ba9d5SMatt Jacob hp = &cto->ct_reserved; 759d81ba9d5SMatt Jacob } else { 760d81ba9d5SMatt Jacob ct_entry_t *cto = qe; 76100a8e174SMatt Jacob 762d81ba9d5SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 763d81ba9d5SMatt Jacob cto->ct_header.rqs_entry_count = 1; 76400a8e174SMatt Jacob cto->ct_iid = cso->init_id; 765d81ba9d5SMatt Jacob cto->ct_tgt = ccb->ccb_h.target_id; 766d81ba9d5SMatt Jacob cto->ct_lun = ccb->ccb_h.target_lun; 76700a8e174SMatt Jacob cto->ct_tag_type = cso->tag_action; 76800a8e174SMatt Jacob cto->ct_tag_val = cso->tag_id; 769d81ba9d5SMatt Jacob cto->ct_flags = CT_CCINCR; 77000a8e174SMatt Jacob if (cso->dxfer_len) { 771d81ba9d5SMatt Jacob cto->ct_flags |= CT_NO_DATA; 77200a8e174SMatt Jacob } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 77300a8e174SMatt Jacob cto->ct_flags |= CT_DATA_IN; 77400a8e174SMatt Jacob } else { 77500a8e174SMatt Jacob cto->ct_flags |= CT_DATA_OUT; 776d81ba9d5SMatt Jacob } 777d81ba9d5SMatt Jacob if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 778d81ba9d5SMatt Jacob cto->ct_flags |= CT_SENDSTATUS; 77900a8e174SMatt Jacob cto->ct_scsi_status = cso->scsi_status; 78000a8e174SMatt Jacob cto->ct_resid = cso->resid; 781d81ba9d5SMatt Jacob } 782d667c06cSMatt Jacob if (isp_tdebug > 1 && 78300a8e174SMatt Jacob (cso->scsi_status != SCSI_STATUS_OK || cso->resid)) { 78492a1e549SMatt Jacob printf("%s:CTIO SCSI STATUS 0x%x resid %d\n", 78500a8e174SMatt Jacob isp->isp_name, cso->scsi_status, cso->resid); 78692a1e549SMatt Jacob } 787d81ba9d5SMatt Jacob hp = &cto->ct_reserved; 78800a8e174SMatt Jacob ccb->ccb_h.flags &= ~CAM_SEND_SENSE; 789d81ba9d5SMatt Jacob } 790d81ba9d5SMatt Jacob 791d81ba9d5SMatt Jacob if (isp_save_xs(isp, (ISP_SCSI_XFER_T *)ccb, hp)) { 79292a1e549SMatt Jacob xpt_print_path(ccb->ccb_h.path); 79392a1e549SMatt Jacob printf("No XFLIST pointers for isp_target_start_ctio\n"); 794d81ba9d5SMatt Jacob return (CAM_RESRC_UNAVAIL); 795d81ba9d5SMatt Jacob } 796d81ba9d5SMatt Jacob 797d81ba9d5SMatt Jacob 798d81ba9d5SMatt Jacob /* 799d81ba9d5SMatt Jacob * Call the dma setup routines for this entry (and any subsequent 800d81ba9d5SMatt Jacob * CTIOs) if there's data to move, and then tell the f/w it's got 801d81ba9d5SMatt Jacob * new things to play with. As with ispscsicmd's usage of DMA setup, 802d81ba9d5SMatt Jacob * any swizzling is done in the machine dependent layer. Because 803d81ba9d5SMatt Jacob * of this, we put the request onto the queue area first in native 804d81ba9d5SMatt Jacob * format. 805d81ba9d5SMatt Jacob */ 806d81ba9d5SMatt Jacob 807d81ba9d5SMatt Jacob save_handle = *hp; 80800a8e174SMatt Jacob switch (ISP_DMASETUP(isp, cso, qe, &iptr, optr)) { 809d81ba9d5SMatt Jacob case CMD_QUEUED: 810d81ba9d5SMatt Jacob MemoryBarrier(); 811d81ba9d5SMatt Jacob ISP_ADD_REQUEST(isp, iptr); 812d81ba9d5SMatt Jacob return (CAM_REQ_INPROG); 813d81ba9d5SMatt Jacob 814d81ba9d5SMatt Jacob case CMD_EAGAIN: 815d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 816d81ba9d5SMatt Jacob isp_destroy_handle(isp, save_handle); 817d81ba9d5SMatt Jacob return (CAM_RESRC_UNAVAIL); 818d81ba9d5SMatt Jacob 819d81ba9d5SMatt Jacob default: 820d81ba9d5SMatt Jacob isp_destroy_handle(isp, save_handle); 821d81ba9d5SMatt Jacob return (ccb->ccb_h.spriv_field0); 822d81ba9d5SMatt Jacob } 823d81ba9d5SMatt Jacob } 824d81ba9d5SMatt Jacob 825d81ba9d5SMatt Jacob /* 826d81ba9d5SMatt Jacob * Handle ATIO stuff that the generic code can't. 827d81ba9d5SMatt Jacob * This means handling CDBs. 828d81ba9d5SMatt Jacob */ 829d81ba9d5SMatt Jacob 830d81ba9d5SMatt Jacob static int 831d81ba9d5SMatt Jacob isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) 832d81ba9d5SMatt Jacob { 833d81ba9d5SMatt Jacob tstate_t *tptr; 834d81ba9d5SMatt Jacob int status; 835d81ba9d5SMatt Jacob struct ccb_accept_tio *atiop; 836d81ba9d5SMatt Jacob 837d81ba9d5SMatt Jacob /* 838d81ba9d5SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) 839d81ba9d5SMatt Jacob * indicates why this ATIO was sent to us. 840d81ba9d5SMatt Jacob * 841d81ba9d5SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 842d81ba9d5SMatt Jacob * 843d81ba9d5SMatt Jacob * If the DISCONNECTS DISABLED bit is set in the flags field, 844d81ba9d5SMatt Jacob * we're still connected on the SCSI bus - i.e. the initiator 845d81ba9d5SMatt Jacob * did not set DiscPriv in the identify message. We don't care 846d81ba9d5SMatt Jacob * about this so it's ignored. 847d81ba9d5SMatt Jacob */ 848d81ba9d5SMatt Jacob status = aep->at_status; 849d81ba9d5SMatt Jacob if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) { 850d81ba9d5SMatt Jacob /* 851d81ba9d5SMatt Jacob * Bus Phase Sequence error. We should have sense data 852d81ba9d5SMatt Jacob * suggested by the f/w. I'm not sure quite yet what 853d81ba9d5SMatt Jacob * to do about this for CAM. 854d81ba9d5SMatt Jacob */ 855d81ba9d5SMatt Jacob printf("%s: PHASE ERROR\n", isp->isp_name); 856d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 857d81ba9d5SMatt Jacob return (0); 858d81ba9d5SMatt Jacob } 859d81ba9d5SMatt Jacob if ((status & ~QLTM_SVALID) != AT_CDB) { 860d81ba9d5SMatt Jacob printf("%s: bogus atio (0x%x) leaked to platform\n", 861d81ba9d5SMatt Jacob isp->isp_name, status); 862d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 863d81ba9d5SMatt Jacob return (0); 864d81ba9d5SMatt Jacob } 865d81ba9d5SMatt Jacob 866d81ba9d5SMatt Jacob tptr = get_lun_statep(isp, aep->at_lun); 867d81ba9d5SMatt Jacob if (tptr == NULL) { 868d81ba9d5SMatt Jacob tptr = get_lun_statep(isp, CAM_LUN_WILDCARD); 869d81ba9d5SMatt Jacob } 870d81ba9d5SMatt Jacob 871d81ba9d5SMatt Jacob if (tptr == NULL) { 872d81ba9d5SMatt Jacob /* 873d81ba9d5SMatt Jacob * Because we can't autofeed sense data back with 874d81ba9d5SMatt Jacob * a command for parallel SCSI, we can't give back 875d81ba9d5SMatt Jacob * a CHECK CONDITION. We'll give back a BUSY status 876d81ba9d5SMatt Jacob * instead. This works out okay because the only 877d81ba9d5SMatt Jacob * time we should, in fact, get this, is in the 878d81ba9d5SMatt Jacob * case that somebody configured us without the 879d81ba9d5SMatt Jacob * blackhole driver, so they get what they deserve. 880d81ba9d5SMatt Jacob */ 881d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 882d81ba9d5SMatt Jacob return (0); 883d81ba9d5SMatt Jacob } 884d81ba9d5SMatt Jacob 885d81ba9d5SMatt Jacob atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios); 886d81ba9d5SMatt Jacob if (atiop == NULL) { 887d81ba9d5SMatt Jacob /* 888d81ba9d5SMatt Jacob * Because we can't autofeed sense data back with 889d81ba9d5SMatt Jacob * a command for parallel SCSI, we can't give back 890d81ba9d5SMatt Jacob * a CHECK CONDITION. We'll give back a QUEUE FULL status 891d81ba9d5SMatt Jacob * instead. This works out okay because the only time we 892d81ba9d5SMatt Jacob * should, in fact, get this, is in the case that we've 893d81ba9d5SMatt Jacob * run out of ATIOS. 894d81ba9d5SMatt Jacob */ 895d81ba9d5SMatt Jacob xpt_print_path(tptr->owner); 896d81ba9d5SMatt Jacob printf("no ATIOS for lun %d from initiator %d\n", 897d81ba9d5SMatt Jacob aep->at_lun, aep->at_iid); 898d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 899d81ba9d5SMatt Jacob if (aep->at_flags & AT_TQAE) 900d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0); 901d81ba9d5SMatt Jacob else 902d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 903d81ba9d5SMatt Jacob return (0); 904d81ba9d5SMatt Jacob } 905d81ba9d5SMatt Jacob SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); 906d81ba9d5SMatt Jacob if (tptr == &isp->isp_osinfo.tsdflt) { 907d81ba9d5SMatt Jacob atiop->ccb_h.target_id = aep->at_tgt; 908d81ba9d5SMatt Jacob atiop->ccb_h.target_lun = aep->at_lun; 909d81ba9d5SMatt Jacob } 910d81ba9d5SMatt Jacob if (aep->at_flags & AT_NODISC) { 911d81ba9d5SMatt Jacob xpt_print_path(tptr->owner); 912d81ba9d5SMatt Jacob printf("incoming command that cannot disconnect\n"); 913d81ba9d5SMatt Jacob } 914d81ba9d5SMatt Jacob 915d81ba9d5SMatt Jacob 916d81ba9d5SMatt Jacob atiop->init_id = aep->at_iid; 917d81ba9d5SMatt Jacob atiop->cdb_len = aep->at_cdblen; 918d81ba9d5SMatt Jacob MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen); 919d81ba9d5SMatt Jacob atiop->ccb_h.status = CAM_CDB_RECVD; 920d81ba9d5SMatt Jacob if ((atiop->tag_action = aep->at_tag_type) != 0) { 921d81ba9d5SMatt Jacob atiop->tag_id = aep->at_tag_val; 922d81ba9d5SMatt Jacob atiop->ccb_h.status |= CAM_TAG_ACTION_VALID; 923d81ba9d5SMatt Jacob } 924d81ba9d5SMatt Jacob xpt_done((union ccb*)atiop); 925d667c06cSMatt Jacob if (isp_tdebug > 1) { 92692a1e549SMatt Jacob printf("%s:ATIO CDB=0x%x iid%d->lun%d tag 0x%x ttype 0x%x\n", 92792a1e549SMatt Jacob isp->isp_name, aep->at_cdb[0] & 0xff, aep->at_iid, 92892a1e549SMatt Jacob aep->at_lun, aep->at_tag_val & 0xff, aep->at_tag_type); 929d81ba9d5SMatt Jacob } 930d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 931d81ba9d5SMatt Jacob return (0); 932d81ba9d5SMatt Jacob } 933d81ba9d5SMatt Jacob 934d81ba9d5SMatt Jacob static int 935d81ba9d5SMatt Jacob isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep) 936d81ba9d5SMatt Jacob { 93792a1e549SMatt Jacob lun_id_t lun; 938d81ba9d5SMatt Jacob tstate_t *tptr; 939d81ba9d5SMatt Jacob struct ccb_accept_tio *atiop; 940d81ba9d5SMatt Jacob 941d81ba9d5SMatt Jacob /* 942d81ba9d5SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) 943d81ba9d5SMatt Jacob * indicates why this ATIO was sent to us. 944d81ba9d5SMatt Jacob * 945d81ba9d5SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 946d81ba9d5SMatt Jacob */ 947d81ba9d5SMatt Jacob if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) { 948d81ba9d5SMatt Jacob printf("%s: bogus atio (0x%x) leaked to platform\n", 949d81ba9d5SMatt Jacob isp->isp_name, aep->at_status); 950d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 951d81ba9d5SMatt Jacob return (0); 952d81ba9d5SMatt Jacob } 953d81ba9d5SMatt Jacob 95492a1e549SMatt Jacob #ifdef ISP2100_SCCLUN 95592a1e549SMatt Jacob lun = aep->at_scclun; 95692a1e549SMatt Jacob #else 95792a1e549SMatt Jacob lun = aep->at_lun; 95892a1e549SMatt Jacob #endif 95992a1e549SMatt Jacob tptr = get_lun_statep(isp, lun); 960d81ba9d5SMatt Jacob if (tptr == NULL) { 961d81ba9d5SMatt Jacob tptr = get_lun_statep(isp, CAM_LUN_WILDCARD); 962d81ba9d5SMatt Jacob } 963d81ba9d5SMatt Jacob 964d81ba9d5SMatt Jacob if (tptr == NULL) { 965d81ba9d5SMatt Jacob #if 0 966d81ba9d5SMatt Jacob /* XXX WE REALLY NEED A HARDWIRED SENSE/INQ CTIO TO USE XXX */ 96700a8e174SMatt Jacob u_int32_t ccode = SCSI_STATUS_CHECK_COND | ECMD_SVALID; 968d81ba9d5SMatt Jacob #if NTARGBH > 0 969d81ba9d5SMatt Jacob /* Not Ready, Unit Not Self-Configured yet.... */ 970d81ba9d5SMatt Jacob ccode |= (SSD_KEY_NOT_READY << 8) | (0x3E << 24); 971d81ba9d5SMatt Jacob #else 972d81ba9d5SMatt Jacob /* Illegal Request, Unit Not Self-Configured yet.... */ 973d81ba9d5SMatt Jacob ccode |= (SSD_KEY_ILLEGAL_REQUEST << 8) | (0x25 << 24); 974d81ba9d5SMatt Jacob #endif 975d81ba9d5SMatt Jacob #else 976d81ba9d5SMatt Jacob u_int32_t ccode = SCSI_STATUS_BUSY; 977d81ba9d5SMatt Jacob #endif 978d81ba9d5SMatt Jacob 979d81ba9d5SMatt Jacob /* 980d81ba9d5SMatt Jacob * Because we can't autofeed sense data back with 981d81ba9d5SMatt Jacob * a command for parallel SCSI, we can't give back 982d81ba9d5SMatt Jacob * a CHECK CONDITION. We'll give back a BUSY status 983d81ba9d5SMatt Jacob * instead. This works out okay because the only 984d81ba9d5SMatt Jacob * time we should, in fact, get this, is in the 985d81ba9d5SMatt Jacob * case that somebody configured us without the 986d81ba9d5SMatt Jacob * blackhole driver, so they get what they deserve. 987d81ba9d5SMatt Jacob */ 988d81ba9d5SMatt Jacob isp_endcmd(isp, aep, ccode, 0); 989d81ba9d5SMatt Jacob return (0); 990d81ba9d5SMatt Jacob } 991d81ba9d5SMatt Jacob 992d81ba9d5SMatt Jacob atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios); 993d81ba9d5SMatt Jacob if (atiop == NULL) { 994d81ba9d5SMatt Jacob /* 995d81ba9d5SMatt Jacob * Because we can't autofeed sense data back with 996d81ba9d5SMatt Jacob * a command for parallel SCSI, we can't give back 997d81ba9d5SMatt Jacob * a CHECK CONDITION. We'll give back a QUEUE FULL status 998d81ba9d5SMatt Jacob * instead. This works out okay because the only time we 999d81ba9d5SMatt Jacob * should, in fact, get this, is in the case that we've 1000d81ba9d5SMatt Jacob * run out of ATIOS. 1001d81ba9d5SMatt Jacob */ 1002d81ba9d5SMatt Jacob xpt_print_path(tptr->owner); 1003d81ba9d5SMatt Jacob printf("no ATIOS for lun %d from initiator %d\n", 100492a1e549SMatt Jacob lun, aep->at_iid); 1005d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 1006d81ba9d5SMatt Jacob if (aep->at_flags & AT_TQAE) 1007d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0); 1008d81ba9d5SMatt Jacob else 1009d81ba9d5SMatt Jacob isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); 1010d81ba9d5SMatt Jacob return (0); 1011d81ba9d5SMatt Jacob } 1012d81ba9d5SMatt Jacob SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); 1013d81ba9d5SMatt Jacob if (tptr == &isp->isp_osinfo.tsdflt) { 1014d81ba9d5SMatt Jacob atiop->ccb_h.target_id = 1015d81ba9d5SMatt Jacob ((fcparam *)isp->isp_param)->isp_loopid; 101692a1e549SMatt Jacob atiop->ccb_h.target_lun = lun; 1017d81ba9d5SMatt Jacob } 1018d81ba9d5SMatt Jacob atiop->init_id = aep->at_iid; 1019d81ba9d5SMatt Jacob atiop->cdb_len = ATIO2_CDBLEN; 1020d81ba9d5SMatt Jacob MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN); 1021d81ba9d5SMatt Jacob atiop->ccb_h.status = CAM_CDB_RECVD; 1022d81ba9d5SMatt Jacob atiop->tag_id = aep->at_rxid; 1023d81ba9d5SMatt Jacob switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) { 1024d81ba9d5SMatt Jacob case ATIO2_TC_ATTR_SIMPLEQ: 1025d81ba9d5SMatt Jacob atiop->tag_action = MSG_SIMPLE_Q_TAG; 1026d81ba9d5SMatt Jacob break; 1027d81ba9d5SMatt Jacob case ATIO2_TC_ATTR_HEADOFQ: 1028d81ba9d5SMatt Jacob atiop->tag_action = MSG_HEAD_OF_Q_TAG; 1029d81ba9d5SMatt Jacob break; 1030d81ba9d5SMatt Jacob case ATIO2_TC_ATTR_ORDERED: 1031d81ba9d5SMatt Jacob atiop->tag_action = MSG_ORDERED_Q_TAG; 1032d81ba9d5SMatt Jacob break; 1033d81ba9d5SMatt Jacob case ATIO2_TC_ATTR_ACAQ: /* ?? */ 1034d81ba9d5SMatt Jacob case ATIO2_TC_ATTR_UNTAGGED: 1035d81ba9d5SMatt Jacob default: 1036d81ba9d5SMatt Jacob atiop->tag_action = 0; 1037d81ba9d5SMatt Jacob break; 1038d81ba9d5SMatt Jacob } 1039d81ba9d5SMatt Jacob if (atiop->tag_action != 0) { 1040d81ba9d5SMatt Jacob atiop->ccb_h.status |= CAM_TAG_ACTION_VALID; 1041d81ba9d5SMatt Jacob } 1042d81ba9d5SMatt Jacob xpt_done((union ccb*)atiop); 1043d667c06cSMatt Jacob if (isp_tdebug > 1) { 104492a1e549SMatt Jacob printf("%s:ATIO2 RX_ID 0x%x CDB=0x%x iid%d->lun%d tattr 0x%x\n", 104592a1e549SMatt Jacob isp->isp_name, aep->at_rxid & 0xffff, aep->at_cdb[0] & 0xff, 104692a1e549SMatt Jacob aep->at_iid, lun, aep->at_taskflags); 1047d81ba9d5SMatt Jacob } 1048d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 1049d81ba9d5SMatt Jacob return (0); 1050d81ba9d5SMatt Jacob } 1051d81ba9d5SMatt Jacob 1052d81ba9d5SMatt Jacob static int 1053d81ba9d5SMatt Jacob isp_handle_platform_ctio(struct ispsoftc *isp, void * arg) 1054d81ba9d5SMatt Jacob { 1055d81ba9d5SMatt Jacob union ccb *ccb; 1056d81ba9d5SMatt Jacob int sentstatus, ok; 1057d81ba9d5SMatt Jacob 1058d81ba9d5SMatt Jacob /* 1059d81ba9d5SMatt Jacob * CTIO and CTIO2 are close enough.... 1060d81ba9d5SMatt Jacob */ 1061d81ba9d5SMatt Jacob 1062d81ba9d5SMatt Jacob ccb = (union ccb *) isp_find_xs(isp, ((ct_entry_t *)arg)->ct_reserved); 1063d81ba9d5SMatt Jacob KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio")); 1064d81ba9d5SMatt Jacob isp_destroy_handle(isp, ((ct_entry_t *)arg)->ct_reserved); 1065d81ba9d5SMatt Jacob 1066d81ba9d5SMatt Jacob if (IS_FC(isp)) { 1067d81ba9d5SMatt Jacob ct2_entry_t *ct = arg; 1068d81ba9d5SMatt Jacob sentstatus = ct->ct_flags & CT2_SENDSTATUS; 1069d81ba9d5SMatt Jacob ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK; 107000a8e174SMatt Jacob if (ok && ccb->ccb_h.flags & CAM_SEND_SENSE) { 107100a8e174SMatt Jacob ccb->ccb_h.status |= CAM_SENT_SENSE; 107200a8e174SMatt Jacob } 1073d667c06cSMatt Jacob if (isp_tdebug > 1) { 107400a8e174SMatt Jacob printf("%s:CTIO2 RX_ID 0x%x sts 0x%x flg 0x%x sns " 107500a8e174SMatt Jacob "%d FIN\n", isp->isp_name, ct->ct_rxid, 107600a8e174SMatt Jacob ct->ct_status, ct->ct_flags, 107700a8e174SMatt Jacob (ccb->ccb_h.status & CAM_SENT_SENSE) != 0); 1078d81ba9d5SMatt Jacob } 1079d81ba9d5SMatt Jacob } else { 1080d81ba9d5SMatt Jacob ct_entry_t *ct = arg; 1081d81ba9d5SMatt Jacob sentstatus = ct->ct_flags & CT_SENDSTATUS; 1082d81ba9d5SMatt Jacob ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK; 1083d667c06cSMatt Jacob if (isp_tdebug > 1) { 108400a8e174SMatt Jacob printf("%s:CTIO tag 0x%x sts 0x%x flg 0x%x FIN\n", 1085d81ba9d5SMatt Jacob isp->isp_name, ct->ct_tag_val, ct->ct_status, 1086d81ba9d5SMatt Jacob ct->ct_flags); 1087d81ba9d5SMatt Jacob } 1088d81ba9d5SMatt Jacob } 1089d81ba9d5SMatt Jacob 1090d81ba9d5SMatt Jacob /* 1091d81ba9d5SMatt Jacob * We're here either because data transfers are done (and 1092d81ba9d5SMatt Jacob * it's time to send a final status CTIO) or because the final 1093d81ba9d5SMatt Jacob * status CTIO is done. We don't get called for all intermediate 1094d81ba9d5SMatt Jacob * CTIOs that happen for a large data transfer. 1095d81ba9d5SMatt Jacob * 1096d81ba9d5SMatt Jacob * In any case, for this platform, the upper layers figure out 1097d81ba9d5SMatt Jacob * what to do next, so all we do here is collect status and 1098d81ba9d5SMatt Jacob * pass information along. 1099d81ba9d5SMatt Jacob */ 1100d81ba9d5SMatt Jacob 1101d81ba9d5SMatt Jacob if (sentstatus) { 1102d81ba9d5SMatt Jacob /* 1103d81ba9d5SMatt Jacob * Data transfer done. See if all went okay. 1104d81ba9d5SMatt Jacob */ 1105d81ba9d5SMatt Jacob if (ok) { 1106d81ba9d5SMatt Jacob ccb->csio.resid = 0; 1107d81ba9d5SMatt Jacob } else { 1108d81ba9d5SMatt Jacob ccb->csio.resid = ccb->csio.dxfer_len; 1109d81ba9d5SMatt Jacob } 1110d81ba9d5SMatt Jacob } 1111d81ba9d5SMatt Jacob 1112d81ba9d5SMatt Jacob 1113d81ba9d5SMatt Jacob if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 1114d81ba9d5SMatt Jacob ccb->ccb_h.status |= CAM_REQ_CMP; 1115d81ba9d5SMatt Jacob } 1116d81ba9d5SMatt Jacob ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1117d81ba9d5SMatt Jacob if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) { 1118d81ba9d5SMatt Jacob isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE; 1119d81ba9d5SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 1120d81ba9d5SMatt Jacob if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 1121d81ba9d5SMatt Jacob IDPRINTF(3, ("%s: isp_done -> relsimq\n", 1122d81ba9d5SMatt Jacob isp->isp_name)); 1123d81ba9d5SMatt Jacob ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1124d81ba9d5SMatt Jacob } else { 1125d81ba9d5SMatt Jacob IDPRINTF(3, ("%s: isp_done -> devq frozen\n", 1126d81ba9d5SMatt Jacob isp->isp_name)); 1127d81ba9d5SMatt Jacob } 1128d81ba9d5SMatt Jacob } else { 1129d81ba9d5SMatt Jacob IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n", 1130d81ba9d5SMatt Jacob isp->isp_name, isp->isp_osinfo.simqfrozen)); 1131d81ba9d5SMatt Jacob } 1132d81ba9d5SMatt Jacob } 1133d81ba9d5SMatt Jacob xpt_done(ccb); 1134d81ba9d5SMatt Jacob return (0); 1135d81ba9d5SMatt Jacob } 1136d81ba9d5SMatt Jacob #endif 1137d81ba9d5SMatt Jacob 1138478f8a96SJustin T. Gibbs static void 1139cbf57b47SMatt Jacob isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg) 1140478f8a96SJustin T. Gibbs { 1141478f8a96SJustin T. Gibbs struct cam_sim *sim; 1142478f8a96SJustin T. Gibbs struct ispsoftc *isp; 1143478f8a96SJustin T. Gibbs 1144478f8a96SJustin T. Gibbs sim = (struct cam_sim *)cbarg; 1145478f8a96SJustin T. Gibbs isp = (struct ispsoftc *) cam_sim_softc(sim); 1146478f8a96SJustin T. Gibbs switch (code) { 1147478f8a96SJustin T. Gibbs case AC_LOST_DEVICE: 1148ab6c4b31SMatt Jacob if (IS_SCSI(isp)) { 1149478f8a96SJustin T. Gibbs u_int16_t oflags, nflags; 1150478f8a96SJustin T. Gibbs sdparam *sdp = isp->isp_param; 1151f9e908dcSMatt Jacob int s, rvf, tgt; 1152478f8a96SJustin T. Gibbs 1153f9e908dcSMatt Jacob tgt = xpt_path_target_id(path); 1154f9e908dcSMatt Jacob rvf = ISP_FW_REVX(isp->isp_fwrev); 1155ea6f23cdSMatt Jacob s = splcam(); 1156ea6f23cdSMatt Jacob sdp += cam_sim_bus(sim); 1157ea6f23cdSMatt Jacob isp->isp_update |= (1 << cam_sim_bus(sim)); 1158478f8a96SJustin T. Gibbs nflags = DPARM_SAFE_DFLT; 1159f9e908dcSMatt Jacob if (rvf >= ISP_FW_REV(7, 55, 0) || 1160f9e908dcSMatt Jacob (ISP_FW_REV(4, 55, 0) <= rvf && 1161f9e908dcSMatt Jacob (rvf < ISP_FW_REV(5, 0, 0)))) { 1162478f8a96SJustin T. Gibbs nflags |= DPARM_NARROW | DPARM_ASYNC; 1163478f8a96SJustin T. Gibbs } 1164478f8a96SJustin T. Gibbs oflags = sdp->isp_devparam[tgt].dev_flags; 1165478f8a96SJustin T. Gibbs sdp->isp_devparam[tgt].dev_flags = nflags; 1166478f8a96SJustin T. Gibbs sdp->isp_devparam[tgt].dev_update = 1; 1167478f8a96SJustin T. Gibbs (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); 1168478f8a96SJustin T. Gibbs sdp->isp_devparam[tgt].dev_flags = oflags; 1169ea6f23cdSMatt Jacob (void) splx(s); 1170478f8a96SJustin T. Gibbs } 1171478f8a96SJustin T. Gibbs break; 1172478f8a96SJustin T. Gibbs default: 11730470d791SMatt Jacob printf("%s: isp_attach Async Code 0x%x\n", isp->isp_name, code); 1174478f8a96SJustin T. Gibbs break; 1175478f8a96SJustin T. Gibbs } 1176478f8a96SJustin T. Gibbs } 1177478f8a96SJustin T. Gibbs 1178478f8a96SJustin T. Gibbs static void 1179c3055363SMatt Jacob isp_poll(struct cam_sim *sim) 1180478f8a96SJustin T. Gibbs { 1181478f8a96SJustin T. Gibbs isp_intr((struct ispsoftc *) cam_sim_softc(sim)); 1182478f8a96SJustin T. Gibbs } 1183478f8a96SJustin T. Gibbs 11840470d791SMatt Jacob static void 11850470d791SMatt Jacob isp_relsim(void *arg) 11860470d791SMatt Jacob { 11870470d791SMatt Jacob struct ispsoftc *isp = arg; 11880470d791SMatt Jacob int s = splcam(); 11890470d791SMatt Jacob if (isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED) { 11900470d791SMatt Jacob int wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED; 11910470d791SMatt Jacob isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_TIMED; 11920470d791SMatt Jacob if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { 11930470d791SMatt Jacob xpt_release_simq(isp->isp_sim, 1); 11940470d791SMatt Jacob IDPRINTF(3, ("%s: timed relsimq\n", isp->isp_name)); 11950470d791SMatt Jacob } 11960470d791SMatt Jacob } 11970470d791SMatt Jacob splx(s); 11980470d791SMatt Jacob } 1199ab6c4b31SMatt Jacob 1200478f8a96SJustin T. Gibbs static void 1201cc8df88bSMatt Jacob isp_timeout(void *arg) 1202cc8df88bSMatt Jacob { 1203cc8df88bSMatt Jacob ISP_SCSI_XFER_T *xs = arg; 1204cc8df88bSMatt Jacob struct ispsoftc *isp = XS_ISP(xs); 1205cc8df88bSMatt Jacob u_int32_t handle; 1206cc8df88bSMatt Jacob int s = splcam(); 1207cc8df88bSMatt Jacob /* 1208cc8df88bSMatt Jacob * We've decide this command is dead. Make sure we're not trying 1209cc8df88bSMatt Jacob * to kill a command that's already dead by getting it's handle. 1210cc8df88bSMatt Jacob */ 1211cc8df88bSMatt Jacob handle = isp_find_handle(isp, xs); 1212cc8df88bSMatt Jacob if (handle) { 1213cc8df88bSMatt Jacob isp_destroy_handle(isp, handle); 1214cc8df88bSMatt Jacob xpt_print_path(xs->ccb_h.path); 1215cc8df88bSMatt Jacob printf("watchdog timeout (handle 0x%x)\n", handle); 1216cc8df88bSMatt Jacob XS_SETERR(xs, CAM_CMD_TIMEOUT); 1217cc8df88bSMatt Jacob isp_done(xs); 1218cc8df88bSMatt Jacob } 1219cc8df88bSMatt Jacob (void) splx(s); 1220cc8df88bSMatt Jacob } 1221cc8df88bSMatt Jacob 1222cc8df88bSMatt Jacob static void 1223c3055363SMatt Jacob isp_action(struct cam_sim *sim, union ccb *ccb) 1224478f8a96SJustin T. Gibbs { 1225ab6c4b31SMatt Jacob int s, bus, tgt, error; 1226478f8a96SJustin T. Gibbs struct ispsoftc *isp; 12274663e367SJustin T. Gibbs struct ccb_trans_settings *cts; 1228478f8a96SJustin T. Gibbs 1229478f8a96SJustin T. Gibbs CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); 1230478f8a96SJustin T. Gibbs 1231478f8a96SJustin T. Gibbs isp = (struct ispsoftc *)cam_sim_softc(sim); 1232478f8a96SJustin T. Gibbs ccb->ccb_h.sim_priv.entries[0].field = 0; 1233478f8a96SJustin T. Gibbs ccb->ccb_h.sim_priv.entries[1].ptr = isp; 12340470d791SMatt Jacob if (isp->isp_state != ISP_RUNSTATE && 12350470d791SMatt Jacob ccb->ccb_h.func_code == XPT_SCSI_IO) { 123657c801f5SMatt Jacob s = splcam(); 123757c801f5SMatt Jacob DISABLE_INTS(isp); 123857c801f5SMatt Jacob isp_init(isp); 123957c801f5SMatt Jacob if (isp->isp_state != ISP_INITSTATE) { 124057c801f5SMatt Jacob (void) splx(s); 124157c801f5SMatt Jacob /* 124257c801f5SMatt Jacob * Lie. Say it was a selection timeout. 124357c801f5SMatt Jacob */ 124457c801f5SMatt Jacob ccb->ccb_h.status = CAM_SEL_TIMEOUT; 12450470d791SMatt Jacob ccb->ccb_h.status |= CAM_DEV_QFRZN; 12460470d791SMatt Jacob xpt_freeze_devq(ccb->ccb_h.path, 1); 124757c801f5SMatt Jacob xpt_done(ccb); 124857c801f5SMatt Jacob return; 124957c801f5SMatt Jacob } 125057c801f5SMatt Jacob isp->isp_state = ISP_RUNSTATE; 125157c801f5SMatt Jacob ENABLE_INTS(isp); 125257c801f5SMatt Jacob (void) splx(s); 125357c801f5SMatt Jacob } 1254478f8a96SJustin T. Gibbs IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name, 1255478f8a96SJustin T. Gibbs ccb->ccb_h.func_code)); 1256478f8a96SJustin T. Gibbs 1257478f8a96SJustin T. Gibbs switch (ccb->ccb_h.func_code) { 1258478f8a96SJustin T. Gibbs case XPT_SCSI_IO: /* Execute the requested I/O operation */ 1259478f8a96SJustin T. Gibbs /* 1260478f8a96SJustin T. Gibbs * Do a couple of preliminary checks... 1261478f8a96SJustin T. Gibbs */ 1262478f8a96SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 1263478f8a96SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { 1264478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_INVALID; 1265478f8a96SJustin T. Gibbs xpt_done(ccb); 1266478f8a96SJustin T. Gibbs break; 1267478f8a96SJustin T. Gibbs } 1268478f8a96SJustin T. Gibbs } 12690470d791SMatt Jacob #ifdef DIAGNOSTIC 12700470d791SMatt Jacob if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) { 1271478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_PATH_INVALID; 12720470d791SMatt Jacob } else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) { 1273478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_PATH_INVALID; 1274478f8a96SJustin T. Gibbs } 1275478f8a96SJustin T. Gibbs if (ccb->ccb_h.status == CAM_PATH_INVALID) { 1276478f8a96SJustin T. Gibbs printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n", 1277478f8a96SJustin T. Gibbs isp->isp_name, ccb->ccb_h.target_id, 1278478f8a96SJustin T. Gibbs ccb->ccb_h.target_lun); 1279478f8a96SJustin T. Gibbs xpt_done(ccb); 1280478f8a96SJustin T. Gibbs break; 1281478f8a96SJustin T. Gibbs } 12820470d791SMatt Jacob #endif 12830470d791SMatt Jacob ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK; 1284478f8a96SJustin T. Gibbs s = splcam(); 1285c3055363SMatt Jacob DISABLE_INTS(isp); 12860470d791SMatt Jacob error = ispscsicmd((ISP_SCSI_XFER_T *) ccb); 12870470d791SMatt Jacob ENABLE_INTS(isp); 12880470d791SMatt Jacob splx(s); 12890470d791SMatt Jacob switch (error) { 1290478f8a96SJustin T. Gibbs case CMD_QUEUED: 1291478f8a96SJustin T. Gibbs ccb->ccb_h.status |= CAM_SIM_QUEUED; 1292cc8df88bSMatt Jacob if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { 1293cc8df88bSMatt Jacob if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) 1294cc8df88bSMatt Jacob ccb->ccb_h.timeout = 5 * 1000; 1295cc8df88bSMatt Jacob ccb->ccb_h.timeout_ch = 1296cc8df88bSMatt Jacob timeout(isp_timeout, (caddr_t)ccb, 1297cc8df88bSMatt Jacob (ccb->ccb_h.timeout * hz) / 1000); 1298cc8df88bSMatt Jacob } 1299478f8a96SJustin T. Gibbs break; 13000470d791SMatt Jacob case CMD_RQLATER: 13010470d791SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 13020470d791SMatt Jacob IDPRINTF(3, ("%s: RQLATER freeze simq\n", 13030470d791SMatt Jacob isp->isp_name)); 13040470d791SMatt Jacob isp->isp_osinfo.simqfrozen |= SIMQFRZ_TIMED; 13050470d791SMatt Jacob timeout(isp_relsim, isp, 500); 1306478f8a96SJustin T. Gibbs xpt_freeze_simq(sim, 1); 130700f50ce8SMatt Jacob } 1308478f8a96SJustin T. Gibbs ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1309478f8a96SJustin T. Gibbs ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1310478f8a96SJustin T. Gibbs xpt_done(ccb); 1311478f8a96SJustin T. Gibbs break; 13120470d791SMatt Jacob case CMD_EAGAIN: 13130470d791SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 13140470d791SMatt Jacob xpt_freeze_simq(sim, 1); 13150470d791SMatt Jacob IDPRINTF(3, ("%s: EAGAIN freeze simq\n", 13160470d791SMatt Jacob isp->isp_name)); 1317478f8a96SJustin T. Gibbs } 13180470d791SMatt Jacob isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; 13190470d791SMatt Jacob ccb->ccb_h.status &= ~CAM_STATUS_MASK; 13200470d791SMatt Jacob ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1321478f8a96SJustin T. Gibbs xpt_done(ccb); 1322478f8a96SJustin T. Gibbs break; 13230470d791SMatt Jacob case CMD_COMPLETE: 13240470d791SMatt Jacob isp_done((struct ccb_scsiio *) ccb); 13250470d791SMatt Jacob break; 13260470d791SMatt Jacob default: 13270470d791SMatt Jacob printf("%s: What's this? 0x%x at %d in file %s\n", 13280470d791SMatt Jacob isp->isp_name, error, __LINE__, __FILE__); 13290470d791SMatt Jacob ccb->ccb_h.status &= ~CAM_STATUS_MASK; 13300470d791SMatt Jacob ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 13310470d791SMatt Jacob xpt_done(ccb); 1332478f8a96SJustin T. Gibbs } 1333478f8a96SJustin T. Gibbs break; 1334478f8a96SJustin T. Gibbs 1335d81ba9d5SMatt Jacob #ifdef ISP_TARGET_MODE 1336478f8a96SJustin T. Gibbs case XPT_EN_LUN: /* Enable LUN as a target */ 1337d81ba9d5SMatt Jacob isp_en_lun(isp, ccb); 1338478f8a96SJustin T. Gibbs xpt_done(ccb); 1339478f8a96SJustin T. Gibbs break; 1340478f8a96SJustin T. Gibbs 1341d81ba9d5SMatt Jacob case XPT_NOTIFY_ACK: /* recycle notify ack */ 1342d81ba9d5SMatt Jacob case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */ 1343d81ba9d5SMatt Jacob case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */ 1344d81ba9d5SMatt Jacob { 1345d81ba9d5SMatt Jacob tstate_t *tptr = get_lun_statep(isp, ccb->ccb_h.target_lun); 1346d81ba9d5SMatt Jacob if (tptr == NULL) { 1347d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_LUN_INVALID; 1348d81ba9d5SMatt Jacob xpt_done(ccb); 1349d81ba9d5SMatt Jacob break; 1350d81ba9d5SMatt Jacob } 1351d81ba9d5SMatt Jacob s = splsoftcam(); 1352d81ba9d5SMatt Jacob if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 1353d81ba9d5SMatt Jacob SLIST_INSERT_HEAD(&tptr->atios, 1354d81ba9d5SMatt Jacob &ccb->ccb_h, sim_links.sle); 1355d81ba9d5SMatt Jacob } else { 1356d81ba9d5SMatt Jacob SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, 1357d81ba9d5SMatt Jacob sim_links.sle); 1358d81ba9d5SMatt Jacob } 1359d81ba9d5SMatt Jacob splx(s); 1360d81ba9d5SMatt Jacob rls_lun_statep(isp, tptr); 1361d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_INPROG; 1362d81ba9d5SMatt Jacob break; 1363d81ba9d5SMatt Jacob } 1364d81ba9d5SMatt Jacob case XPT_CONT_TARGET_IO: 1365d81ba9d5SMatt Jacob { 1366d81ba9d5SMatt Jacob s = splcam(); 1367d81ba9d5SMatt Jacob ccb->ccb_h.status = isp_target_start_ctio(isp, ccb); 1368d81ba9d5SMatt Jacob if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1369d81ba9d5SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 1370d81ba9d5SMatt Jacob xpt_freeze_simq(sim, 1); 1371d81ba9d5SMatt Jacob xpt_print_path(ccb->ccb_h.path); 1372d81ba9d5SMatt Jacob printf("XPT_CONT_TARGET_IO freeze simq\n"); 1373d81ba9d5SMatt Jacob } 1374d81ba9d5SMatt Jacob isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; 1375d81ba9d5SMatt Jacob ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1376d81ba9d5SMatt Jacob ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1377d81ba9d5SMatt Jacob xpt_done(ccb); 1378d81ba9d5SMatt Jacob } else { 1379d81ba9d5SMatt Jacob ccb->ccb_h.status |= CAM_SIM_QUEUED; 1380d81ba9d5SMatt Jacob } 1381d81ba9d5SMatt Jacob splx(s); 1382d81ba9d5SMatt Jacob break; 1383d81ba9d5SMatt Jacob } 1384d81ba9d5SMatt Jacob #endif 1385478f8a96SJustin T. Gibbs case XPT_RESET_DEV: /* BDR the specified SCSI device */ 1386d81ba9d5SMatt Jacob 1387d81ba9d5SMatt Jacob bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)); 1388d81ba9d5SMatt Jacob tgt = ccb->ccb_h.target_id; 1389d81ba9d5SMatt Jacob tgt |= (bus << 16); 1390d81ba9d5SMatt Jacob 1391478f8a96SJustin T. Gibbs s = splcam(); 1392ea6f23cdSMatt Jacob error = isp_control(isp, ISPCTL_RESET_DEV, &tgt); 1393478f8a96SJustin T. Gibbs (void) splx(s); 1394478f8a96SJustin T. Gibbs if (error) { 1395478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1396478f8a96SJustin T. Gibbs } else { 1397478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 1398478f8a96SJustin T. Gibbs } 1399478f8a96SJustin T. Gibbs xpt_done(ccb); 1400478f8a96SJustin T. Gibbs break; 1401478f8a96SJustin T. Gibbs case XPT_ABORT: /* Abort the specified CCB */ 1402d81ba9d5SMatt Jacob { 1403d81ba9d5SMatt Jacob union ccb *accb = ccb->cab.abort_ccb; 1404d81ba9d5SMatt Jacob switch (accb->ccb_h.func_code) { 1405d81ba9d5SMatt Jacob #ifdef ISP_TARGET_MODE 1406d81ba9d5SMatt Jacob case XPT_ACCEPT_TARGET_IO: 1407d81ba9d5SMatt Jacob case XPT_IMMED_NOTIFY: 1408d81ba9d5SMatt Jacob ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb); 1409d81ba9d5SMatt Jacob break; 1410d81ba9d5SMatt Jacob case XPT_CONT_TARGET_IO: 1411d81ba9d5SMatt Jacob PRINTF("%s: cannot abort CTIOs yet\n", isp->isp_name); 1412d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_UA_ABORT; 1413d81ba9d5SMatt Jacob break; 1414d81ba9d5SMatt Jacob #endif 1415d81ba9d5SMatt Jacob case XPT_SCSI_IO: 1416478f8a96SJustin T. Gibbs s = splcam(); 1417478f8a96SJustin T. Gibbs error = isp_control(isp, ISPCTL_ABORT_CMD, ccb); 1418478f8a96SJustin T. Gibbs (void) splx(s); 1419478f8a96SJustin T. Gibbs if (error) { 1420d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_UA_ABORT; 1421478f8a96SJustin T. Gibbs } else { 1422478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 1423478f8a96SJustin T. Gibbs } 1424d81ba9d5SMatt Jacob break; 1425d81ba9d5SMatt Jacob default: 1426d81ba9d5SMatt Jacob ccb->ccb_h.status = CAM_REQ_INVALID; 1427d81ba9d5SMatt Jacob break; 1428d81ba9d5SMatt Jacob } 1429478f8a96SJustin T. Gibbs xpt_done(ccb); 1430478f8a96SJustin T. Gibbs break; 1431d81ba9d5SMatt Jacob } 1432478f8a96SJustin T. Gibbs case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ 1433478f8a96SJustin T. Gibbs 1434478f8a96SJustin T. Gibbs cts = &ccb->cts; 1435478f8a96SJustin T. Gibbs tgt = cts->ccb_h.target_id; 1436478f8a96SJustin T. Gibbs s = splcam(); 1437ab6c4b31SMatt Jacob if (IS_SCSI(isp)) { 1438478f8a96SJustin T. Gibbs sdparam *sdp = isp->isp_param; 1439478f8a96SJustin T. Gibbs u_int16_t *dptr; 1440d81ba9d5SMatt Jacob 1441d81ba9d5SMatt Jacob bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); 1442478f8a96SJustin T. Gibbs 1443ea6f23cdSMatt Jacob sdp += bus; 1444478f8a96SJustin T. Gibbs #if 0 1445478f8a96SJustin T. Gibbs if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) 1446478f8a96SJustin T. Gibbs dptr = &sdp->isp_devparam[tgt].cur_dflags; 1447478f8a96SJustin T. Gibbs else 1448478f8a96SJustin T. Gibbs dptr = &sdp->isp_devparam[tgt].dev_flags; 1449478f8a96SJustin T. Gibbs #else 1450478f8a96SJustin T. Gibbs /* 1451478f8a96SJustin T. Gibbs * We always update (internally) from dev_flags 1452478f8a96SJustin T. Gibbs * so any request to change settings just gets 1453478f8a96SJustin T. Gibbs * vectored to that location. 1454478f8a96SJustin T. Gibbs */ 1455478f8a96SJustin T. Gibbs dptr = &sdp->isp_devparam[tgt].dev_flags; 1456478f8a96SJustin T. Gibbs #endif 1457478f8a96SJustin T. Gibbs 1458478f8a96SJustin T. Gibbs /* 1459478f8a96SJustin T. Gibbs * Note that these operations affect the 14604394c92fSMatt Jacob * the goal flags (dev_flags)- not 1461478f8a96SJustin T. Gibbs * the current state flags. Then we mark 1462478f8a96SJustin T. Gibbs * things so that the next operation to 1463478f8a96SJustin T. Gibbs * this HBA will cause the update to occur. 1464478f8a96SJustin T. Gibbs */ 1465478f8a96SJustin T. Gibbs if (cts->valid & CCB_TRANS_DISC_VALID) { 1466478f8a96SJustin T. Gibbs if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) { 1467478f8a96SJustin T. Gibbs *dptr |= DPARM_DISC; 1468478f8a96SJustin T. Gibbs } else { 1469478f8a96SJustin T. Gibbs *dptr &= ~DPARM_DISC; 1470478f8a96SJustin T. Gibbs } 1471478f8a96SJustin T. Gibbs } 1472478f8a96SJustin T. Gibbs if (cts->valid & CCB_TRANS_TQ_VALID) { 1473478f8a96SJustin T. Gibbs if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) { 1474478f8a96SJustin T. Gibbs *dptr |= DPARM_TQING; 1475478f8a96SJustin T. Gibbs } else { 1476478f8a96SJustin T. Gibbs *dptr &= ~DPARM_TQING; 1477478f8a96SJustin T. Gibbs } 1478478f8a96SJustin T. Gibbs } 1479478f8a96SJustin T. Gibbs if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { 1480478f8a96SJustin T. Gibbs switch (cts->bus_width) { 1481478f8a96SJustin T. Gibbs case MSG_EXT_WDTR_BUS_16_BIT: 1482478f8a96SJustin T. Gibbs *dptr |= DPARM_WIDE; 1483478f8a96SJustin T. Gibbs break; 1484478f8a96SJustin T. Gibbs default: 1485478f8a96SJustin T. Gibbs *dptr &= ~DPARM_WIDE; 1486478f8a96SJustin T. Gibbs } 1487478f8a96SJustin T. Gibbs } 1488478f8a96SJustin T. Gibbs /* 1489478f8a96SJustin T. Gibbs * Any SYNC RATE of nonzero and SYNC_OFFSET 1490478f8a96SJustin T. Gibbs * of nonzero will cause us to go to the 1491478f8a96SJustin T. Gibbs * selected (from NVRAM) maximum value for 1492478f8a96SJustin T. Gibbs * this device. At a later point, we'll 1493478f8a96SJustin T. Gibbs * allow finer control. 1494478f8a96SJustin T. Gibbs */ 1495478f8a96SJustin T. Gibbs if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && 1496478f8a96SJustin T. Gibbs (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) && 1497478f8a96SJustin T. Gibbs (cts->sync_offset > 0)) { 1498478f8a96SJustin T. Gibbs *dptr |= DPARM_SYNC; 1499478f8a96SJustin T. Gibbs } else { 1500478f8a96SJustin T. Gibbs *dptr &= ~DPARM_SYNC; 1501478f8a96SJustin T. Gibbs } 1502ab6c4b31SMatt Jacob *dptr |= DPARM_SAFE_DFLT; 150383ae4407SMatt Jacob if (bootverbose || isp->isp_dblev >= 3) 150483ae4407SMatt Jacob printf("%s: %d.%d set %s period 0x%x offset " 150583ae4407SMatt Jacob "0x%x flags 0x%x\n", isp->isp_name, bus, 150683ae4407SMatt Jacob tgt, 15074394c92fSMatt Jacob (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? 15084394c92fSMatt Jacob "current" : "user", 15092b052931SMatt Jacob sdp->isp_devparam[tgt].sync_period, 15102b052931SMatt Jacob sdp->isp_devparam[tgt].sync_offset, 151183ae4407SMatt Jacob sdp->isp_devparam[tgt].dev_flags); 1512478f8a96SJustin T. Gibbs sdp->isp_devparam[tgt].dev_update = 1; 1513ea6f23cdSMatt Jacob isp->isp_update |= (1 << bus); 1514478f8a96SJustin T. Gibbs } 1515478f8a96SJustin T. Gibbs (void) splx(s); 1516478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 1517478f8a96SJustin T. Gibbs xpt_done(ccb); 1518478f8a96SJustin T. Gibbs break; 1519478f8a96SJustin T. Gibbs 1520478f8a96SJustin T. Gibbs case XPT_GET_TRAN_SETTINGS: 1521478f8a96SJustin T. Gibbs 1522478f8a96SJustin T. Gibbs cts = &ccb->cts; 1523478f8a96SJustin T. Gibbs tgt = cts->ccb_h.target_id; 1524ab6c4b31SMatt Jacob if (IS_FC(isp)) { 1525478f8a96SJustin T. Gibbs /* 1526478f8a96SJustin T. Gibbs * a lot of normal SCSI things don't make sense. 1527478f8a96SJustin T. Gibbs */ 1528478f8a96SJustin T. Gibbs cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB; 1529478f8a96SJustin T. Gibbs cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 1530478f8a96SJustin T. Gibbs /* 1531478f8a96SJustin T. Gibbs * How do you measure the width of a high 1532478f8a96SJustin T. Gibbs * speed serial bus? Well, in bytes. 1533478f8a96SJustin T. Gibbs * 1534478f8a96SJustin T. Gibbs * Offset and period make no sense, though, so we set 1535478f8a96SJustin T. Gibbs * (above) a 'base' transfer speed to be gigabit. 1536478f8a96SJustin T. Gibbs */ 1537478f8a96SJustin T. Gibbs cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 1538478f8a96SJustin T. Gibbs } else { 1539478f8a96SJustin T. Gibbs sdparam *sdp = isp->isp_param; 15404394c92fSMatt Jacob u_int16_t dval, pval, oval; 1541ea6f23cdSMatt Jacob int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); 1542478f8a96SJustin T. Gibbs 1543ea6f23cdSMatt Jacob sdp += bus; 15444394c92fSMatt Jacob if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) { 154583ae4407SMatt Jacob s = splcam(); 154683ae4407SMatt Jacob sdp->isp_devparam[tgt].dev_refresh = 1; 154783ae4407SMatt Jacob isp->isp_update |= (1 << bus); 154883ae4407SMatt Jacob (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, 154983ae4407SMatt Jacob NULL); 155083ae4407SMatt Jacob (void) splx(s); 1551478f8a96SJustin T. Gibbs dval = sdp->isp_devparam[tgt].cur_dflags; 15524394c92fSMatt Jacob oval = sdp->isp_devparam[tgt].cur_offset; 15534394c92fSMatt Jacob pval = sdp->isp_devparam[tgt].cur_period; 15544394c92fSMatt Jacob } else { 1555478f8a96SJustin T. Gibbs dval = sdp->isp_devparam[tgt].dev_flags; 15564394c92fSMatt Jacob oval = sdp->isp_devparam[tgt].sync_offset; 15574394c92fSMatt Jacob pval = sdp->isp_devparam[tgt].sync_period; 15584394c92fSMatt Jacob } 1559478f8a96SJustin T. Gibbs 1560478f8a96SJustin T. Gibbs s = splcam(); 1561478f8a96SJustin T. Gibbs cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); 1562478f8a96SJustin T. Gibbs 1563478f8a96SJustin T. Gibbs if (dval & DPARM_DISC) { 1564478f8a96SJustin T. Gibbs cts->flags |= CCB_TRANS_DISC_ENB; 1565478f8a96SJustin T. Gibbs } 1566478f8a96SJustin T. Gibbs if (dval & DPARM_TQING) { 1567478f8a96SJustin T. Gibbs cts->flags |= CCB_TRANS_TAG_ENB; 1568478f8a96SJustin T. Gibbs } 1569478f8a96SJustin T. Gibbs if (dval & DPARM_WIDE) { 1570478f8a96SJustin T. Gibbs cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 1571478f8a96SJustin T. Gibbs } else { 1572478f8a96SJustin T. Gibbs cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 1573478f8a96SJustin T. Gibbs } 1574478f8a96SJustin T. Gibbs cts->valid = CCB_TRANS_BUS_WIDTH_VALID | 1575478f8a96SJustin T. Gibbs CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 1576478f8a96SJustin T. Gibbs 15774394c92fSMatt Jacob if ((dval & DPARM_SYNC) && oval != 0) { 15784394c92fSMatt Jacob cts->sync_period = pval; 15794394c92fSMatt Jacob cts->sync_offset = oval; 1580478f8a96SJustin T. Gibbs cts->valid |= 1581478f8a96SJustin T. Gibbs CCB_TRANS_SYNC_RATE_VALID | 1582478f8a96SJustin T. Gibbs CCB_TRANS_SYNC_OFFSET_VALID; 1583478f8a96SJustin T. Gibbs } 1584478f8a96SJustin T. Gibbs splx(s); 158583ae4407SMatt Jacob if (bootverbose || isp->isp_dblev >= 3) 158683ae4407SMatt Jacob printf("%s: %d.%d get %s period 0x%x offset " 158783ae4407SMatt Jacob "0x%x flags 0x%x\n", isp->isp_name, bus, 158883ae4407SMatt Jacob tgt, 15894394c92fSMatt Jacob (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? 159083ae4407SMatt Jacob "current" : "user", pval, oval, dval); 1591478f8a96SJustin T. Gibbs } 1592478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 1593478f8a96SJustin T. Gibbs xpt_done(ccb); 1594478f8a96SJustin T. Gibbs break; 1595478f8a96SJustin T. Gibbs 1596478f8a96SJustin T. Gibbs case XPT_CALC_GEOMETRY: 1597478f8a96SJustin T. Gibbs { 1598478f8a96SJustin T. Gibbs struct ccb_calc_geometry *ccg; 1599478f8a96SJustin T. Gibbs u_int32_t secs_per_cylinder; 1600478f8a96SJustin T. Gibbs u_int32_t size_mb; 1601478f8a96SJustin T. Gibbs 1602478f8a96SJustin T. Gibbs ccg = &ccb->ccg; 1603478f8a96SJustin T. Gibbs if (ccg->block_size == 0) { 1604478f8a96SJustin T. Gibbs printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n", 1605478f8a96SJustin T. Gibbs isp->isp_name, ccg->ccb_h.target_id, 1606478f8a96SJustin T. Gibbs ccg->ccb_h.target_lun); 1607478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_INVALID; 1608478f8a96SJustin T. Gibbs xpt_done(ccb); 1609478f8a96SJustin T. Gibbs break; 1610478f8a96SJustin T. Gibbs } 1611478f8a96SJustin T. Gibbs size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size); 1612478f8a96SJustin T. Gibbs if (size_mb > 1024) { 1613478f8a96SJustin T. Gibbs ccg->heads = 255; 1614478f8a96SJustin T. Gibbs ccg->secs_per_track = 63; 1615478f8a96SJustin T. Gibbs } else { 1616478f8a96SJustin T. Gibbs ccg->heads = 64; 1617478f8a96SJustin T. Gibbs ccg->secs_per_track = 32; 1618478f8a96SJustin T. Gibbs } 1619478f8a96SJustin T. Gibbs secs_per_cylinder = ccg->heads * ccg->secs_per_track; 1620478f8a96SJustin T. Gibbs ccg->cylinders = ccg->volume_size / secs_per_cylinder; 1621478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 1622478f8a96SJustin T. Gibbs xpt_done(ccb); 1623478f8a96SJustin T. Gibbs break; 1624478f8a96SJustin T. Gibbs } 1625478f8a96SJustin T. Gibbs case XPT_RESET_BUS: /* Reset the specified bus */ 1626ab6c4b31SMatt Jacob bus = cam_sim_bus(sim); 1627478f8a96SJustin T. Gibbs s = splcam(); 1628ab6c4b31SMatt Jacob error = isp_control(isp, ISPCTL_RESET_BUS, &bus); 1629478f8a96SJustin T. Gibbs (void) splx(s); 1630478f8a96SJustin T. Gibbs if (error) 1631478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP_ERR; 16322b052931SMatt Jacob else { 1633ea6f23cdSMatt Jacob if (cam_sim_bus(sim) && isp->isp_path2 != NULL) 1634ea6f23cdSMatt Jacob xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); 1635ea6f23cdSMatt Jacob else if (isp->isp_path != NULL) 16362b052931SMatt Jacob xpt_async(AC_BUS_RESET, isp->isp_path, NULL); 1637478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_CMP; 16382b052931SMatt Jacob } 1639478f8a96SJustin T. Gibbs xpt_done(ccb); 1640478f8a96SJustin T. Gibbs break; 1641478f8a96SJustin T. Gibbs 1642478f8a96SJustin T. Gibbs case XPT_TERM_IO: /* Terminate the I/O process */ 1643478f8a96SJustin T. Gibbs /* Does this need to be implemented? */ 1644478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_INVALID; 1645478f8a96SJustin T. Gibbs xpt_done(ccb); 1646478f8a96SJustin T. Gibbs break; 1647478f8a96SJustin T. Gibbs 1648478f8a96SJustin T. Gibbs case XPT_PATH_INQ: /* Path routing inquiry */ 1649478f8a96SJustin T. Gibbs { 1650478f8a96SJustin T. Gibbs struct ccb_pathinq *cpi = &ccb->cpi; 1651478f8a96SJustin T. Gibbs 1652478f8a96SJustin T. Gibbs cpi->version_num = 1; 1653d81ba9d5SMatt Jacob #ifdef ISP_TARGET_MODE 1654d81ba9d5SMatt Jacob cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; 1655d81ba9d5SMatt Jacob #else 1656478f8a96SJustin T. Gibbs cpi->target_sprt = 0; 1657d81ba9d5SMatt Jacob #endif 1658478f8a96SJustin T. Gibbs cpi->hba_eng_cnt = 0; 16590470d791SMatt Jacob cpi->max_target = ISP_MAX_TARGETS(isp) - 1; 16600470d791SMatt Jacob cpi->max_lun = ISP_MAX_LUNS(isp) - 1; 16610470d791SMatt Jacob cpi->bus_id = cam_sim_bus(sim); 16624394c92fSMatt Jacob if (IS_FC(isp)) { 16634394c92fSMatt Jacob cpi->hba_misc = PIM_NOBUSRESET; 16640470d791SMatt Jacob /* 16650470d791SMatt Jacob * Because our loop ID can shift from time to time, 16660470d791SMatt Jacob * make our initiator ID out of range of our bus. 16670470d791SMatt Jacob */ 16680470d791SMatt Jacob cpi->initiator_id = cpi->max_target + 1; 16690470d791SMatt Jacob 16709deea857SKenneth D. Merry /* 16719deea857SKenneth D. Merry * Set base transfer capabilities for Fibre Channel. 16729deea857SKenneth D. Merry * Technically not correct because we don't know 16739deea857SKenneth D. Merry * what media we're running on top of- but we'll 16749deea857SKenneth D. Merry * look good if we always say 100MB/s. 16759deea857SKenneth D. Merry */ 16769deea857SKenneth D. Merry cpi->base_transfer_speed = 100000; 16770470d791SMatt Jacob cpi->hba_inquiry = PI_TAG_ABLE; 1678478f8a96SJustin T. Gibbs } else { 1679ea6f23cdSMatt Jacob sdparam *sdp = isp->isp_param; 1680ea6f23cdSMatt Jacob sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path)); 16810470d791SMatt Jacob cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 16824394c92fSMatt Jacob cpi->hba_misc = 0; 1683ea6f23cdSMatt Jacob cpi->initiator_id = sdp->isp_initiator_id; 16849deea857SKenneth D. Merry cpi->base_transfer_speed = 3300; 1685478f8a96SJustin T. Gibbs } 1686478f8a96SJustin T. Gibbs strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1687478f8a96SJustin T. Gibbs strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN); 1688478f8a96SJustin T. Gibbs strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1689478f8a96SJustin T. Gibbs cpi->unit_number = cam_sim_unit(sim); 1690478f8a96SJustin T. Gibbs cpi->ccb_h.status = CAM_REQ_CMP; 1691478f8a96SJustin T. Gibbs xpt_done(ccb); 1692478f8a96SJustin T. Gibbs break; 1693478f8a96SJustin T. Gibbs } 1694478f8a96SJustin T. Gibbs default: 1695478f8a96SJustin T. Gibbs ccb->ccb_h.status = CAM_REQ_INVALID; 1696478f8a96SJustin T. Gibbs xpt_done(ccb); 1697478f8a96SJustin T. Gibbs break; 1698478f8a96SJustin T. Gibbs } 1699478f8a96SJustin T. Gibbs } 1700d3a9eb2eSMatt Jacob 1701d3a9eb2eSMatt Jacob #define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB) 1702d3a9eb2eSMatt Jacob void 1703c3055363SMatt Jacob isp_done(struct ccb_scsiio *sccb) 1704d3a9eb2eSMatt Jacob { 1705d3a9eb2eSMatt Jacob struct ispsoftc *isp = XS_ISP(sccb); 1706d3a9eb2eSMatt Jacob 1707d3a9eb2eSMatt Jacob if (XS_NOERR(sccb)) 1708d3a9eb2eSMatt Jacob XS_SETERR(sccb, CAM_REQ_CMP); 1709d3a9eb2eSMatt Jacob sccb->ccb_h.status &= ~CAM_STATUS_MASK; 1710d3a9eb2eSMatt Jacob sccb->ccb_h.status |= sccb->ccb_h.spriv_field0; 1711d3a9eb2eSMatt Jacob if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && 1712d3a9eb2eSMatt Jacob (sccb->scsi_status != SCSI_STATUS_OK)) { 1713d3a9eb2eSMatt Jacob sccb->ccb_h.status &= ~CAM_STATUS_MASK; 171492a1e549SMatt Jacob if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) && 171592a1e549SMatt Jacob (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) { 171692a1e549SMatt Jacob sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL; 171792a1e549SMatt Jacob } else { 1718d3a9eb2eSMatt Jacob sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1719d3a9eb2eSMatt Jacob } 172092a1e549SMatt Jacob } 17210470d791SMatt Jacob sccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1722d3a9eb2eSMatt Jacob if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1723d3a9eb2eSMatt Jacob if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 1724d3a9eb2eSMatt Jacob sccb->ccb_h.status |= CAM_DEV_QFRZN; 17250470d791SMatt Jacob xpt_freeze_devq(sccb->ccb_h.path, 1); 17260470d791SMatt Jacob if (sccb->scsi_status != SCSI_STATUS_OK) 17270470d791SMatt Jacob IDPRINTF(3, ("%s: fdevq %d.%d %x %x\n", 17280470d791SMatt Jacob isp->isp_name, sccb->ccb_h.target_id, 17290470d791SMatt Jacob sccb->ccb_h.target_lun, sccb->ccb_h.status, 17300470d791SMatt Jacob sccb->scsi_status)); 1731d3a9eb2eSMatt Jacob } 1732d3a9eb2eSMatt Jacob } 17330470d791SMatt Jacob /* 17340470d791SMatt Jacob * If we were frozen waiting resources, clear that we were frozen 17350470d791SMatt Jacob * waiting for resources. If we are no longer frozen, and the devq 17360470d791SMatt Jacob * isn't frozen, mark the completing CCB to have the XPT layer 17370470d791SMatt Jacob * release the simq. 17380470d791SMatt Jacob */ 173957c801f5SMatt Jacob if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) { 174057c801f5SMatt Jacob isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE; 17410470d791SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 17420470d791SMatt Jacob if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 17430470d791SMatt Jacob IDPRINTF(3, ("%s: isp_done -> relsimq\n", 17440470d791SMatt Jacob isp->isp_name)); 1745d3a9eb2eSMatt Jacob sccb->ccb_h.status |= CAM_RELEASE_SIMQ; 17460470d791SMatt Jacob } else { 17470470d791SMatt Jacob IDPRINTF(3, ("%s: isp_done -> devq frozen\n", 17480470d791SMatt Jacob isp->isp_name)); 1749d3a9eb2eSMatt Jacob } 17500470d791SMatt Jacob } else { 17510470d791SMatt Jacob IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n", 17520470d791SMatt Jacob isp->isp_name, isp->isp_osinfo.simqfrozen)); 17530470d791SMatt Jacob } 17540470d791SMatt Jacob } 1755d3a9eb2eSMatt Jacob if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) && 1756d3a9eb2eSMatt Jacob (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1757d3a9eb2eSMatt Jacob xpt_print_path(sccb->ccb_h.path); 1758d3a9eb2eSMatt Jacob printf("cam completion status 0x%x\n", sccb->ccb_h.status); 1759d3a9eb2eSMatt Jacob } 1760cc8df88bSMatt Jacob untimeout(isp_timeout, (caddr_t)sccb, sccb->ccb_h.timeout_ch); 1761d3a9eb2eSMatt Jacob xpt_done((union ccb *) sccb); 1762d3a9eb2eSMatt Jacob } 1763d3a9eb2eSMatt Jacob 1764cbf57b47SMatt Jacob int 17650470d791SMatt Jacob isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) 1766cbf57b47SMatt Jacob { 1767ea6f23cdSMatt Jacob int bus, rv = 0; 1768cbf57b47SMatt Jacob switch (cmd) { 1769cbf57b47SMatt Jacob case ISPASYNC_NEW_TGT_PARAMS: 17700470d791SMatt Jacob { 1771cbf57b47SMatt Jacob int flags, tgt; 1772cbf57b47SMatt Jacob sdparam *sdp = isp->isp_param; 1773cbf57b47SMatt Jacob struct ccb_trans_settings neg; 1774cbf57b47SMatt Jacob struct cam_path *tmppath; 1775cbf57b47SMatt Jacob 1776cbf57b47SMatt Jacob tgt = *((int *)arg); 1777ea6f23cdSMatt Jacob bus = (tgt >> 16) & 0xffff; 1778ea6f23cdSMatt Jacob tgt &= 0xffff; 1779ea6f23cdSMatt Jacob sdp += bus; 1780cbf57b47SMatt Jacob if (xpt_create_path(&tmppath, NULL, 1781ea6f23cdSMatt Jacob cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim), 1782ea6f23cdSMatt Jacob tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1783cbf57b47SMatt Jacob xpt_print_path(isp->isp_path); 1784cbf57b47SMatt Jacob printf("isp_async cannot make temp path for " 1785ea6f23cdSMatt Jacob "target %d bus %d\n", tgt, bus); 1786cbf57b47SMatt Jacob rv = -1; 1787cbf57b47SMatt Jacob break; 1788cbf57b47SMatt Jacob } 17894394c92fSMatt Jacob flags = sdp->isp_devparam[tgt].cur_dflags; 1790cbf57b47SMatt Jacob neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 1791cbf57b47SMatt Jacob if (flags & DPARM_DISC) { 1792cbf57b47SMatt Jacob neg.flags |= CCB_TRANS_DISC_ENB; 1793cbf57b47SMatt Jacob } 1794cbf57b47SMatt Jacob if (flags & DPARM_TQING) { 1795cbf57b47SMatt Jacob neg.flags |= CCB_TRANS_TAG_ENB; 1796cbf57b47SMatt Jacob } 1797cbf57b47SMatt Jacob neg.valid |= CCB_TRANS_BUS_WIDTH_VALID; 1798cbf57b47SMatt Jacob neg.bus_width = (flags & DPARM_WIDE)? 1799cbf57b47SMatt Jacob MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT; 18004394c92fSMatt Jacob neg.sync_period = sdp->isp_devparam[tgt].cur_period; 18014394c92fSMatt Jacob neg.sync_offset = sdp->isp_devparam[tgt].cur_offset; 1802cbf57b47SMatt Jacob if (flags & DPARM_SYNC) { 18034394c92fSMatt Jacob neg.valid |= 18044394c92fSMatt Jacob CCB_TRANS_SYNC_RATE_VALID | 1805cbf57b47SMatt Jacob CCB_TRANS_SYNC_OFFSET_VALID; 1806cbf57b47SMatt Jacob } 1807ea6f23cdSMatt Jacob IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period " 1808ea6f23cdSMatt Jacob "0x%x offset 0x%x flags 0x%x\n", isp->isp_name, 1809ea6f23cdSMatt Jacob bus, tgt, neg.sync_period, neg.sync_offset, flags)); 1810cbf57b47SMatt Jacob xpt_setup_ccb(&neg.ccb_h, tmppath, 1); 1811cbf57b47SMatt Jacob xpt_async(AC_TRANSFER_NEG, tmppath, &neg); 1812cbf57b47SMatt Jacob xpt_free_path(tmppath); 1813cbf57b47SMatt Jacob break; 18140470d791SMatt Jacob } 181557c801f5SMatt Jacob case ISPASYNC_BUS_RESET: 1816ea6f23cdSMatt Jacob bus = *((int *)arg); 1817ea6f23cdSMatt Jacob printf("%s: SCSI bus reset on bus %d detected\n", 1818ea6f23cdSMatt Jacob isp->isp_name, bus); 1819ea6f23cdSMatt Jacob if (bus > 0 && isp->isp_path2) { 1820ea6f23cdSMatt Jacob xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); 1821ea6f23cdSMatt Jacob } else if (isp->isp_path) { 182257c801f5SMatt Jacob xpt_async(AC_BUS_RESET, isp->isp_path, NULL); 182357c801f5SMatt Jacob } 182457c801f5SMatt Jacob break; 182557c801f5SMatt Jacob case ISPASYNC_LOOP_DOWN: 182657c801f5SMatt Jacob if (isp->isp_path) { 18270470d791SMatt Jacob if (isp->isp_osinfo.simqfrozen == 0) { 18280470d791SMatt Jacob IDPRINTF(3, ("%s: loop down freeze simq\n", 18290470d791SMatt Jacob isp->isp_name)); 183057c801f5SMatt Jacob xpt_freeze_simq(isp->isp_sim, 1); 18310470d791SMatt Jacob } 183257c801f5SMatt Jacob isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; 183357c801f5SMatt Jacob } 183457c801f5SMatt Jacob printf("%s: Loop DOWN\n", isp->isp_name); 183557c801f5SMatt Jacob break; 183657c801f5SMatt Jacob case ISPASYNC_LOOP_UP: 183757c801f5SMatt Jacob if (isp->isp_path) { 18380470d791SMatt Jacob int wasfrozen = 18390470d791SMatt Jacob isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; 184057c801f5SMatt Jacob isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; 18410470d791SMatt Jacob if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { 18420470d791SMatt Jacob xpt_release_simq(isp->isp_sim, 1); 18430470d791SMatt Jacob IDPRINTF(3, ("%s: loop up release simq\n", 18440470d791SMatt Jacob isp->isp_name)); 184557c801f5SMatt Jacob } 184657c801f5SMatt Jacob } 184757c801f5SMatt Jacob printf("%s: Loop UP\n", isp->isp_name); 184857c801f5SMatt Jacob break; 184902ab3379SMatt Jacob case ISPASYNC_PDB_CHANGED: 18500470d791SMatt Jacob { 185102ab3379SMatt Jacob const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x " 185202ab3379SMatt Jacob "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n"; 185302ab3379SMatt Jacob const static char *roles[4] = { 18540470d791SMatt Jacob "(none)", "Target", "Initiator", "Target/Initiator" 185557c801f5SMatt Jacob }; 185602ab3379SMatt Jacob char *ptr; 185702ab3379SMatt Jacob fcparam *fcp = isp->isp_param; 185802ab3379SMatt Jacob int tgt = *((int *) arg); 185902ab3379SMatt Jacob struct lportdb *lp = &fcp->portdb[tgt]; 186002ab3379SMatt Jacob 186102ab3379SMatt Jacob if (lp->valid) { 186202ab3379SMatt Jacob ptr = "arrived"; 186302ab3379SMatt Jacob } else { 186402ab3379SMatt Jacob ptr = "disappeared"; 186502ab3379SMatt Jacob } 186602ab3379SMatt Jacob printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid, 186702ab3379SMatt Jacob roles[lp->roles & 0x3], ptr, 186802ab3379SMatt Jacob (u_int32_t) (lp->port_wwn >> 32), 186902ab3379SMatt Jacob (u_int32_t) (lp->port_wwn & 0xffffffffLL), 187002ab3379SMatt Jacob (u_int32_t) (lp->node_wwn >> 32), 187102ab3379SMatt Jacob (u_int32_t) (lp->node_wwn & 0xffffffffLL)); 18724394c92fSMatt Jacob break; 18734394c92fSMatt Jacob } 187457c801f5SMatt Jacob case ISPASYNC_CHANGE_NOTIFY: 187557c801f5SMatt Jacob printf("%s: Name Server Database Changed\n", isp->isp_name); 187657c801f5SMatt Jacob break; 18770470d791SMatt Jacob #ifdef ISP2100_FABRIC 187802ab3379SMatt Jacob case ISPASYNC_FABRIC_DEV: 187902ab3379SMatt Jacob { 188002ab3379SMatt Jacob int target; 188102ab3379SMatt Jacob struct lportdb *lp; 188240cfc8feSMatt Jacob char *pt; 188340cfc8feSMatt Jacob sns_ganrsp_t *resp = (sns_ganrsp_t *) arg; 188402ab3379SMatt Jacob u_int32_t portid; 188540cfc8feSMatt Jacob u_int64_t wwpn, wwnn; 188602ab3379SMatt Jacob fcparam *fcp = isp->isp_param; 188702ab3379SMatt Jacob 188802ab3379SMatt Jacob rv = -1; 188902ab3379SMatt Jacob 189002ab3379SMatt Jacob portid = 189102ab3379SMatt Jacob (((u_int32_t) resp->snscb_port_id[0]) << 16) | 189202ab3379SMatt Jacob (((u_int32_t) resp->snscb_port_id[1]) << 8) | 189302ab3379SMatt Jacob (((u_int32_t) resp->snscb_port_id[2])); 189440cfc8feSMatt Jacob 189540cfc8feSMatt Jacob wwpn = 189602ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[0]) << 56) | 189702ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[1]) << 48) | 189802ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[2]) << 40) | 189902ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[3]) << 32) | 190002ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[4]) << 24) | 190102ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[5]) << 16) | 190202ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[6]) << 8) | 190302ab3379SMatt Jacob (((u_int64_t)resp->snscb_portname[7])); 190440cfc8feSMatt Jacob 190540cfc8feSMatt Jacob wwnn = 190640cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[0]) << 56) | 190740cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[1]) << 48) | 190840cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[2]) << 40) | 190940cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[3]) << 32) | 191040cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[4]) << 24) | 191140cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[5]) << 16) | 191240cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[6]) << 8) | 191340cfc8feSMatt Jacob (((u_int64_t)resp->snscb_nodename[7])); 191440cfc8feSMatt Jacob if (portid == 0 || wwpn == 0) { 191502ab3379SMatt Jacob rv = 0; 191602ab3379SMatt Jacob break; 191702ab3379SMatt Jacob } 191840cfc8feSMatt Jacob 191940cfc8feSMatt Jacob switch (resp->snscb_port_type) { 192040cfc8feSMatt Jacob case 1: 192140cfc8feSMatt Jacob pt = " N_Port"; 192240cfc8feSMatt Jacob break; 192340cfc8feSMatt Jacob case 2: 192440cfc8feSMatt Jacob pt = " NL_Port"; 192540cfc8feSMatt Jacob break; 192640cfc8feSMatt Jacob case 3: 192740cfc8feSMatt Jacob pt = "F/NL_Port"; 192840cfc8feSMatt Jacob break; 192940cfc8feSMatt Jacob case 0x7f: 193040cfc8feSMatt Jacob pt = " Nx_Port"; 193140cfc8feSMatt Jacob break; 193240cfc8feSMatt Jacob case 0x81: 193340cfc8feSMatt Jacob pt = " F_port"; 193440cfc8feSMatt Jacob break; 193540cfc8feSMatt Jacob case 0x82: 193640cfc8feSMatt Jacob pt = " FL_Port"; 193740cfc8feSMatt Jacob break; 193840cfc8feSMatt Jacob case 0x84: 193940cfc8feSMatt Jacob pt = " E_port"; 194040cfc8feSMatt Jacob break; 194140cfc8feSMatt Jacob default: 194240cfc8feSMatt Jacob pt = "?"; 194340cfc8feSMatt Jacob break; 194440cfc8feSMatt Jacob } 194540cfc8feSMatt Jacob CFGPRINTF("%s: %s @ 0x%x, Node 0x%08x%08x Port %08x%08x\n", 194640cfc8feSMatt Jacob isp->isp_name, pt, portid, 194740cfc8feSMatt Jacob ((u_int32_t) (wwnn >> 32)), ((u_int32_t) wwnn), 194840cfc8feSMatt Jacob ((u_int32_t) (wwpn >> 32)), ((u_int32_t) wwpn)); 194940cfc8feSMatt Jacob #if 0 195040cfc8feSMatt Jacob if ((resp->snscb_fc4_types[1] & 0x1) == 0) { 195140cfc8feSMatt Jacob rv = 0; 195240cfc8feSMatt Jacob printf("Types 0..3: 0x%x 0x%x 0x%x 0x%x\n", 195340cfc8feSMatt Jacob resp->snscb_fc4_types[0], resp->snscb_fc4_types[1], 195440cfc8feSMatt Jacob resp->snscb_fc4_types[3], resp->snscb_fc4_types[3]); 195540cfc8feSMatt Jacob break; 195640cfc8feSMatt Jacob } 195740cfc8feSMatt Jacob #endif 195802ab3379SMatt Jacob for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { 195902ab3379SMatt Jacob lp = &fcp->portdb[target]; 196040cfc8feSMatt Jacob if (lp->port_wwn == wwpn && lp->node_wwn == wwnn) 196102ab3379SMatt Jacob break; 196202ab3379SMatt Jacob } 196302ab3379SMatt Jacob if (target < MAX_FC_TARG) { 196402ab3379SMatt Jacob rv = 0; 196502ab3379SMatt Jacob break; 196602ab3379SMatt Jacob } 196702ab3379SMatt Jacob for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { 196802ab3379SMatt Jacob lp = &fcp->portdb[target]; 196902ab3379SMatt Jacob if (lp->port_wwn == 0) 197002ab3379SMatt Jacob break; 197102ab3379SMatt Jacob } 197202ab3379SMatt Jacob if (target == MAX_FC_TARG) { 197302ab3379SMatt Jacob printf("%s: no more space for fabric devices\n", 197402ab3379SMatt Jacob isp->isp_name); 197502ab3379SMatt Jacob break; 197602ab3379SMatt Jacob } 197740cfc8feSMatt Jacob lp->node_wwn = wwnn; 197840cfc8feSMatt Jacob lp->port_wwn = wwpn; 197902ab3379SMatt Jacob lp->portid = portid; 198002ab3379SMatt Jacob rv = 0; 198102ab3379SMatt Jacob break; 198202ab3379SMatt Jacob } 198302ab3379SMatt Jacob #endif 1984d81ba9d5SMatt Jacob #ifdef ISP_TARGET_MODE 1985d81ba9d5SMatt Jacob case ISPASYNC_TARGET_MESSAGE: 1986d81ba9d5SMatt Jacob { 1987d81ba9d5SMatt Jacob tmd_msg_t *mp = arg; 1988d667c06cSMatt Jacob ITDEBUG(2, ("%s: bus %d iid %d tgt %d lun %d ttype %x tval %x" 198900a8e174SMatt Jacob " msg[0]=0x%x\n", isp->isp_name, mp->nt_bus, 199000a8e174SMatt Jacob (int) mp->nt_iid, (int) mp->nt_tgt, (int) mp->nt_lun, 199100a8e174SMatt Jacob mp->nt_tagtype, mp->nt_tagval, mp->nt_msg[0])); 1992d81ba9d5SMatt Jacob break; 1993d81ba9d5SMatt Jacob } 1994d81ba9d5SMatt Jacob case ISPASYNC_TARGET_EVENT: 1995d81ba9d5SMatt Jacob { 1996d81ba9d5SMatt Jacob tmd_event_t *ep = arg; 1997d667c06cSMatt Jacob ITDEBUG(2, ("%s: bus %d event code 0x%x\n", isp->isp_name, 1998d81ba9d5SMatt Jacob ep->ev_bus, ep->ev_event)); 1999d81ba9d5SMatt Jacob break; 2000d81ba9d5SMatt Jacob } 2001d81ba9d5SMatt Jacob case ISPASYNC_TARGET_ACTION: 2002d81ba9d5SMatt Jacob switch (((isphdr_t *)arg)->rqs_entry_type) { 2003cbf57b47SMatt Jacob default: 2004d81ba9d5SMatt Jacob printf("%s: event 0x%x for unhandled target action\n", 2005d81ba9d5SMatt Jacob isp->isp_name, ((isphdr_t *)arg)->rqs_entry_type); 2006d81ba9d5SMatt Jacob break; 2007d81ba9d5SMatt Jacob case RQSTYPE_ATIO: 2008d81ba9d5SMatt Jacob rv = isp_handle_platform_atio(isp, (at_entry_t *) arg); 2009d81ba9d5SMatt Jacob break; 2010d81ba9d5SMatt Jacob case RQSTYPE_ATIO2: 2011d81ba9d5SMatt Jacob rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg); 2012d81ba9d5SMatt Jacob break; 2013d81ba9d5SMatt Jacob case RQSTYPE_CTIO2: 2014d81ba9d5SMatt Jacob case RQSTYPE_CTIO: 2015d81ba9d5SMatt Jacob rv = isp_handle_platform_ctio(isp, arg); 2016d81ba9d5SMatt Jacob break; 2017d81ba9d5SMatt Jacob case RQSTYPE_ENABLE_LUN: 2018d81ba9d5SMatt Jacob case RQSTYPE_MODIFY_LUN: 2019d81ba9d5SMatt Jacob isp_cv_signal_rqe(isp, ((lun_entry_t *)arg)->le_status); 2020d81ba9d5SMatt Jacob break; 2021d81ba9d5SMatt Jacob } 2022d81ba9d5SMatt Jacob break; 2023d81ba9d5SMatt Jacob #endif 2024d81ba9d5SMatt Jacob default: 2025d81ba9d5SMatt Jacob PRINTF("%s: unknown isp_async event %d\n", isp->isp_name, cmd); 202602ab3379SMatt Jacob rv = -1; 2027cbf57b47SMatt Jacob break; 2028cbf57b47SMatt Jacob } 2029cbf57b47SMatt Jacob return (rv); 2030cbf57b47SMatt Jacob } 2031cbf57b47SMatt Jacob 203292718a7fSMatt Jacob 203392718a7fSMatt Jacob /* 203492718a7fSMatt Jacob * Locks are held before coming here. 203592718a7fSMatt Jacob */ 203692718a7fSMatt Jacob void 203792718a7fSMatt Jacob isp_uninit(struct ispsoftc *isp) 203892718a7fSMatt Jacob { 2039ea6f23cdSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); 204092718a7fSMatt Jacob DISABLE_INTS(isp); 204192718a7fSMatt Jacob } 2042