1 /* 2 * Copyright (c) 2010, LSI Corp. 3 * All rights reserved. 4 * Author : Manjunath Ranganathaiah 5 * Support: freebsdraid@lsi.com 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of the <ORGANIZATION> nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/dev/tws/tws_cam.c,v 1.3 2007/05/09 04:16:32 mrangana Exp $ 35 */ 36 37 #include <dev/raid/tws/tws.h> 38 #include <dev/raid/tws/tws_services.h> 39 #include <dev/raid/tws/tws_hdm.h> 40 #include <dev/raid/tws/tws_user.h> 41 #include <bus/cam/cam.h> 42 #include <bus/cam/cam_ccb.h> 43 #include <bus/cam/cam_sim.h> 44 #include <bus/cam/cam_xpt_sim.h> 45 #include <bus/cam/cam_debug.h> 46 #include <bus/cam/cam_periph.h> 47 48 #include <bus/cam/scsi/scsi_all.h> 49 #include <bus/cam/scsi/scsi_message.h> 50 51 static int tws_cam_depth=(TWS_MAX_REQS - TWS_RESERVED_REQS); 52 static char tws_sev_str[5][8]={"","ERROR","WARNING","INFO","DEBUG"}; 53 54 static void tws_action(struct cam_sim *sim, union ccb *ccb); 55 static void tws_poll(struct cam_sim *sim); 56 static void tws_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); 57 static void tws_scsi_complete(struct tws_request *req); 58 59 60 61 void tws_unmap_request(struct tws_softc *sc, struct tws_request *req); 62 int32_t tws_map_request(struct tws_softc *sc, struct tws_request *req); 63 int tws_bus_scan(struct tws_softc *sc); 64 int tws_cam_attach(struct tws_softc *sc); 65 void tws_cam_detach(struct tws_softc *sc); 66 void tws_reset(void *arg); 67 68 static void tws_reset_cb(void *arg); 69 static void tws_reinit(void *arg); 70 static int32_t tws_execute_scsi(struct tws_softc *sc, union ccb *ccb); 71 static void tws_freeze_simq(struct tws_softc *sc); 72 static void tws_release_simq(struct tws_softc *sc); 73 static void tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs, 74 int nseg, int error); 75 static void tws_fill_sg_list(struct tws_softc *sc, void *sgl_src, 76 void *sgl_dest, u_int16_t num_sgl_entries); 77 static void tws_err_complete(struct tws_softc *sc, u_int64_t mfa); 78 static void tws_scsi_err_complete(struct tws_request *req, 79 struct tws_command_header *hdr); 80 static void tws_passthru_err_complete(struct tws_request *req, 81 struct tws_command_header *hdr); 82 83 84 static void tws_timeout(void *arg); 85 static void tws_intr_attn_aen(struct tws_softc *sc); 86 static void tws_intr_attn_error(struct tws_softc *sc); 87 static void tws_intr_resp(struct tws_softc *sc); 88 void tws_intr(void *arg); 89 void tws_cmd_complete(struct tws_request *req); 90 void tws_aen_complete(struct tws_request *req); 91 int tws_send_scsi_cmd(struct tws_softc *sc, int cmd); 92 void tws_getset_param_complete(struct tws_request *req); 93 int tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 94 u_int32_t param_size, void *data); 95 int tws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 96 u_int32_t param_size, void *data); 97 98 99 extern struct tws_request *tws_get_request(struct tws_softc *sc, 100 u_int16_t type); 101 extern void *tws_release_request(struct tws_request *req); 102 extern int tws_submit_command(struct tws_softc *sc, struct tws_request *req); 103 extern boolean tws_get_response(struct tws_softc *sc, 104 u_int16_t *req_id, u_int64_t *mfa); 105 extern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 106 u_int8_t q_type ); 107 extern struct tws_request * tws_q_remove_request(struct tws_softc *sc, 108 struct tws_request *req, u_int8_t q_type ); 109 extern void tws_send_event(struct tws_softc *sc, u_int8_t event); 110 111 extern struct tws_sense * 112 tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa); 113 114 extern void tws_fetch_aen(void *arg); 115 extern void tws_disable_db_intr(struct tws_softc *sc); 116 extern void tws_enable_db_intr(struct tws_softc *sc); 117 extern void tws_passthru_complete(struct tws_request *req); 118 extern void tws_aen_synctime_with_host(struct tws_softc *sc); 119 extern void tws_circular_aenq_insert(struct tws_softc *sc, 120 struct tws_circular_q *cq, struct tws_event_packet *aen); 121 extern int tws_use_32bit_sgls; 122 extern boolean tws_ctlr_reset(struct tws_softc *sc); 123 extern struct tws_request * tws_q_remove_tail(struct tws_softc *sc, 124 u_int8_t q_type ); 125 extern void tws_turn_off_interrupts(struct tws_softc *sc); 126 extern void tws_turn_on_interrupts(struct tws_softc *sc); 127 extern int tws_init_connect(struct tws_softc *sc, u_int16_t mc); 128 extern void tws_init_obfl_q(struct tws_softc *sc); 129 extern uint8_t tws_get_state(struct tws_softc *sc); 130 extern void tws_assert_soft_reset(struct tws_softc *sc); 131 extern boolean tws_ctlr_ready(struct tws_softc *sc); 132 extern u_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa); 133 134 135 136 int 137 tws_cam_attach(struct tws_softc *sc) 138 { 139 struct cam_devq *devq; 140 int error; 141 142 TWS_TRACE_DEBUG(sc, "entry", 0, sc); 143 /* Create a device queue for sim */ 144 145 /* 146 * if the user sets cam depth to less than 1 147 * cam may get confused 148 */ 149 if ( tws_cam_depth < 1 ) 150 tws_cam_depth = 1; 151 if ( tws_cam_depth > (tws_queue_depth - TWS_RESERVED_REQS) ) 152 tws_cam_depth = tws_queue_depth - TWS_RESERVED_REQS; 153 154 TWS_TRACE_DEBUG(sc, "depths,ctlr,cam", tws_queue_depth, tws_cam_depth); 155 156 if ((devq = cam_simq_alloc(tws_cam_depth)) == NULL) { 157 tws_log(sc, CAM_SIMQ_ALLOC); 158 return(ENOMEM); 159 } 160 161 /* 162 * Create a SIM entry. Though we can support tws_cam_depth 163 * simultaneous requests, we claim to be able to handle only 164 * (tws_cam_depth), so that we always have reserved requests 165 * packet available to service ioctls and internal commands. 166 */ 167 sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc, 168 device_get_unit(sc->tws_dev), 169 &sc->sim_lock, 170 tws_cam_depth, 1, devq); 171 /* 1, 1, devq); */ 172 cam_simq_release(devq); 173 if (sc->sim == NULL) { 174 tws_log(sc, CAM_SIM_ALLOC); 175 } 176 /* Register the bus. */ 177 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 178 if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) { 179 cam_sim_free(sc->sim); 180 sc->sim = NULL; /* so cam_detach will not try to free it */ 181 lockmgr(&sc->sim_lock, LK_RELEASE); 182 tws_log(sc, TWS_XPT_BUS_REGISTER); 183 return(ENXIO); 184 } 185 if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim), 186 CAM_TARGET_WILDCARD, 187 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 188 xpt_bus_deregister(cam_sim_path(sc->sim)); 189 cam_sim_free(sc->sim); 190 tws_log(sc, TWS_XPT_CREATE_PATH); 191 lockmgr(&sc->sim_lock, LK_RELEASE); 192 return(ENXIO); 193 } 194 if ((error = tws_bus_scan(sc))) { 195 tws_log(sc, TWS_BUS_SCAN_REQ); 196 lockmgr(&sc->sim_lock, LK_RELEASE); 197 return(error); 198 } 199 lockmgr(&sc->sim_lock, LK_RELEASE); 200 201 return(0); 202 } 203 204 void 205 tws_cam_detach(struct tws_softc *sc) 206 { 207 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 208 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 209 if (sc->path) 210 xpt_free_path(sc->path); 211 if (sc->sim) { 212 xpt_bus_deregister(cam_sim_path(sc->sim)); 213 cam_sim_free(sc->sim); 214 } 215 lockmgr(&sc->sim_lock, LK_RELEASE); 216 } 217 218 int 219 tws_bus_scan(struct tws_softc *sc) 220 { 221 struct cam_path *path; 222 union ccb *ccb; 223 224 TWS_TRACE_DEBUG(sc, "entry", sc, 0); 225 KASSERT(sc->sim, ("sim not allocated")); 226 KKASSERT(lockstatus(&sc->sim_lock, curthread) != 0); 227 228 ccb = sc->scan_ccb; 229 230 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim), 231 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 232 /* lockmgr(&sc->sim_lock, LK_RELEASE); */ 233 return(EIO); 234 } 235 xpt_setup_ccb(&ccb->ccb_h, path, 5); 236 ccb->ccb_h.func_code = XPT_SCAN_BUS; 237 ccb->ccb_h.cbfcnp = tws_bus_scan_cb; 238 ccb->crcn.flags = CAM_FLAG_NONE; 239 xpt_action(ccb); 240 241 return(0); 242 } 243 244 static void 245 tws_bus_scan_cb(struct cam_periph *periph, union ccb *ccb) 246 { 247 struct tws_softc *sc = periph->softc; 248 249 /* calling trace results in non-sleepable lock head panic 250 using printf to debug */ 251 252 if (ccb->ccb_h.status != CAM_REQ_CMP) { 253 kprintf("cam_scan failure\n"); 254 255 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 256 tws_send_event(sc, TWS_SCAN_FAILURE); 257 lockmgr(&sc->gen_lock, LK_RELEASE); 258 } 259 260 xpt_free_path(ccb->ccb_h.path); 261 } 262 263 static void 264 tws_action(struct cam_sim *sim, union ccb *ccb) 265 { 266 struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim); 267 268 switch( ccb->ccb_h.func_code ) { 269 case XPT_SCSI_IO: 270 { 271 if ( tws_execute_scsi(sc, ccb) ) 272 TWS_TRACE_DEBUG(sc, "execute scsi failed", 0, 0); 273 break; 274 } 275 case XPT_ABORT: 276 { 277 TWS_TRACE_DEBUG(sc, "abort i/o", 0, 0); 278 ccb->ccb_h.status = CAM_UA_ABORT; 279 xpt_done(ccb); 280 break; 281 } 282 case XPT_RESET_BUS: 283 { 284 TWS_TRACE_DEBUG(sc, "reset bus", sim, ccb); 285 break; 286 } 287 case XPT_SET_TRAN_SETTINGS: 288 { 289 TWS_TRACE_DEBUG(sc, "set tran settings", sim, ccb); 290 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 291 xpt_done(ccb); 292 293 break; 294 } 295 case XPT_GET_TRAN_SETTINGS: 296 { 297 TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb); 298 299 ccb->cts.protocol = PROTO_SCSI; 300 ccb->cts.protocol_version = SCSI_REV_2; 301 ccb->cts.transport = XPORT_SPI; 302 ccb->cts.transport_version = 2; 303 304 ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC; 305 ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB; 306 ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 307 ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 308 ccb->ccb_h.status = CAM_REQ_CMP; 309 xpt_done(ccb); 310 311 break; 312 } 313 case XPT_CALC_GEOMETRY: 314 { 315 TWS_TRACE_DEBUG(sc, "calc geometry(ccb,block-size)", ccb, 316 ccb->ccg.block_size); 317 cam_calc_geometry(&ccb->ccg, 1/* extended */); 318 xpt_done(ccb); 319 320 break; 321 } 322 case XPT_PATH_INQ: 323 { 324 TWS_TRACE_DEBUG(sc, "path inquiry", sim, ccb); 325 ccb->cpi.version_num = 1; 326 ccb->cpi.hba_inquiry = 0; 327 ccb->cpi.target_sprt = 0; 328 ccb->cpi.hba_misc = 0; 329 ccb->cpi.hba_eng_cnt = 0; 330 ccb->cpi.max_target = TWS_MAX_NUM_UNITS; 331 ccb->cpi.max_lun = TWS_MAX_NUM_LUNS - 1; 332 ccb->cpi.unit_number = cam_sim_unit(sim); 333 ccb->cpi.bus_id = cam_sim_bus(sim); 334 ccb->cpi.initiator_id = TWS_SCSI_INITIATOR_ID; 335 ccb->cpi.base_transfer_speed = 300000; 336 strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN); 337 strncpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN); 338 strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN); 339 ccb->cpi.transport = XPORT_SPI; 340 ccb->cpi.transport_version = 2; 341 ccb->cpi.protocol = PROTO_SCSI; 342 ccb->cpi.protocol_version = SCSI_REV_2; 343 ccb->ccb_h.status = CAM_REQ_CMP; 344 xpt_done(ccb); 345 346 break; 347 } 348 default: 349 TWS_TRACE_DEBUG(sc, "default", sim, ccb); 350 ccb->ccb_h.status = CAM_REQ_INVALID; 351 xpt_done(ccb); 352 break; 353 } 354 } 355 356 static void 357 tws_scsi_complete(struct tws_request *req) 358 { 359 struct tws_softc *sc = req->sc; 360 361 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 362 tws_q_remove_request(sc, req, TWS_BUSY_Q); 363 lockmgr(&sc->q_lock, LK_RELEASE); 364 365 callout_stop(req->ccb_ptr->ccb_h.timeout_ch); 366 tws_unmap_request(req->sc, req); 367 368 369 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 370 req->ccb_ptr->ccb_h.status = CAM_REQ_CMP; 371 xpt_done(req->ccb_ptr); 372 lockmgr(&sc->sim_lock, LK_RELEASE); 373 374 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 375 tws_q_insert_tail(sc, req, TWS_FREE_Q); 376 lockmgr(&sc->q_lock, LK_RELEASE); 377 378 } 379 380 void 381 tws_getset_param_complete(struct tws_request *req) 382 { 383 struct tws_softc *sc = req->sc; 384 385 TWS_TRACE_DEBUG(sc, "getset complete", req, req->request_id); 386 387 callout_stop(&req->thandle); 388 tws_unmap_request(sc, req); 389 390 kfree(req->data, M_TWS); 391 392 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 393 req->state = TWS_REQ_STATE_FREE; 394 lockmgr(&sc->gen_lock, LK_RELEASE); 395 396 } 397 398 void 399 tws_aen_complete(struct tws_request *req) 400 { 401 struct tws_softc *sc = req->sc; 402 struct tws_command_header *sense; 403 struct tws_event_packet event; 404 u_int16_t aen_code=0; 405 406 TWS_TRACE_DEBUG(sc, "aen complete", 0, req->request_id); 407 408 callout_stop(&req->thandle); 409 tws_unmap_request(sc, req); 410 411 sense = (struct tws_command_header *)req->data; 412 413 TWS_TRACE_DEBUG(sc,"sense code, key",sense->sense_data[0], 414 sense->sense_data[2]); 415 TWS_TRACE_DEBUG(sc,"sense rid, seve",sense->header_desc.request_id, 416 sense->status_block.res__severity); 417 TWS_TRACE_DEBUG(sc,"sense srcnum, error",sense->status_block.srcnum, 418 sense->status_block.error); 419 TWS_TRACE_DEBUG(sc,"sense shdr, ssense",sense->header_desc.size_header, 420 sense->header_desc.size_sense); 421 422 aen_code = sense->status_block.error; 423 424 switch ( aen_code ) { 425 case TWS_AEN_SYNC_TIME_WITH_HOST : 426 tws_aen_synctime_with_host(sc); 427 break; 428 case TWS_AEN_QUEUE_EMPTY : 429 break; 430 default : 431 bzero(&event, sizeof(struct tws_event_packet)); 432 event.sequence_id = sc->seq_id; 433 event.time_stamp_sec = (u_int32_t)TWS_LOCAL_TIME; 434 event.aen_code = sense->status_block.error; 435 event.severity = sense->status_block.res__severity & 0x7; 436 event.event_src = TWS_SRC_CTRL_EVENT; 437 strcpy(event.severity_str, tws_sev_str[event.severity]); 438 event.retrieved = TWS_AEN_NOT_RETRIEVED; 439 440 bcopy(sense->err_specific_desc, event.parameter_data, 441 TWS_ERROR_SPECIFIC_DESC_LEN); 442 event.parameter_data[TWS_ERROR_SPECIFIC_DESC_LEN - 1] = '\0'; 443 event.parameter_len = (u_int8_t)strlen(event.parameter_data)+1; 444 445 if ( event.parameter_len < TWS_ERROR_SPECIFIC_DESC_LEN ) { 446 event.parameter_len += ((u_int8_t)strlen(event.parameter_data + 447 event.parameter_len) + 1); 448 } 449 450 device_printf(sc->tws_dev, "%s: (0x%02X: 0x%04X): %s: %s\n", 451 event.severity_str, 452 event.event_src, 453 event.aen_code, 454 event.parameter_data + 455 (strlen(event.parameter_data) + 1), 456 event.parameter_data); 457 458 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 459 tws_circular_aenq_insert(sc, &sc->aen_q, &event); 460 sc->seq_id++; 461 lockmgr(&sc->gen_lock, LK_RELEASE); 462 break; 463 464 } 465 466 kfree(req->data, M_TWS); 467 468 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 469 req->state = TWS_REQ_STATE_FREE; 470 lockmgr(&sc->gen_lock, LK_RELEASE); 471 472 if ( aen_code != TWS_AEN_QUEUE_EMPTY ) { 473 /* timeout(tws_fetch_aen, sc, 1);*/ 474 sc->stats.num_aens++; 475 tws_fetch_aen(sc); 476 } 477 478 } 479 480 void 481 tws_cmd_complete(struct tws_request *req) 482 { 483 struct tws_softc *sc = req->sc; 484 485 callout_stop(req->ccb_ptr->ccb_h.timeout_ch); 486 tws_unmap_request(sc, req); 487 488 } 489 490 static void 491 tws_err_complete(struct tws_softc *sc, u_int64_t mfa) 492 { 493 494 struct tws_command_header *hdr; 495 struct tws_sense *sen; 496 struct tws_request *req; 497 u_int16_t req_id; 498 u_int32_t reg, status; 499 500 if ( !mfa ) { 501 TWS_TRACE_DEBUG(sc, "null mfa", 0, mfa); 502 return; 503 } else { 504 /* lookup the sense */ 505 sen = tws_find_sense_from_mfa(sc, mfa); 506 if ( sen == NULL ) { 507 TWS_TRACE_DEBUG(sc, "found null req", 0, mfa); 508 return; 509 } 510 hdr = sen->hdr; 511 TWS_TRACE_DEBUG(sc, "sen, hdr", sen, hdr); 512 req_id = hdr->header_desc.request_id; 513 req = &sc->reqs[req_id]; 514 TWS_TRACE_DEBUG(sc, "req, id", req, req_id); 515 if ( req->error_code != TWS_REQ_SUBMIT_SUCCESS ) 516 TWS_TRACE_DEBUG(sc, "submit failure?", 0, req->error_code); 517 } 518 519 switch (req->type) { 520 case TWS_PASSTHRU_REQ : 521 tws_passthru_err_complete(req, hdr); 522 break; 523 case TWS_GETSET_PARAM_REQ : 524 tws_getset_param_complete(req); 525 break; 526 case TWS_SCSI_IO_REQ : 527 tws_scsi_err_complete(req, hdr); 528 break; 529 530 } 531 532 lockmgr(&sc->io_lock, LK_EXCLUSIVE); 533 hdr->header_desc.size_header = 128; 534 reg = (u_int32_t)( mfa>>32); 535 tws_write_reg(sc, TWS_I2O0_HOBQPH, reg, 4); 536 reg = (u_int32_t)(mfa); 537 tws_write_reg(sc, TWS_I2O0_HOBQPL, reg, 4); 538 539 status = tws_read_reg(sc, TWS_I2O0_STATUS, 4); 540 if ( status & TWS_BIT13 ) { 541 TWS_TRACE_DEBUG(sc, "OBFL Overrun", status, TWS_I2O0_STATUS); 542 sc->obfl_q_overrun = true; 543 sen->posted = false; 544 } 545 lockmgr(&sc->io_lock, LK_RELEASE); 546 547 } 548 549 static void 550 tws_scsi_err_complete(struct tws_request *req, struct tws_command_header *hdr) 551 { 552 u_int8_t *sense_data; 553 struct tws_softc *sc = req->sc; 554 union ccb *ccb = req->ccb_ptr; 555 556 TWS_TRACE_DEBUG(sc, "sbe, cmd_status", hdr->status_block.error, 557 req->cmd_pkt->cmd.pkt_a.status); 558 if ( hdr->status_block.error == TWS_ERROR_LOGICAL_UNIT_NOT_SUPPORTED || 559 hdr->status_block.error == TWS_ERROR_UNIT_OFFLINE ) { 560 561 if ( ccb->ccb_h.target_lun ) { 562 TWS_TRACE_DEBUG(sc, "invalid lun error",0,0); 563 ccb->ccb_h.status |= CAM_LUN_INVALID; 564 } else { 565 TWS_TRACE_DEBUG(sc, "invalid target error",0,0); 566 ccb->ccb_h.status |= CAM_TID_INVALID; 567 } 568 569 } else { 570 TWS_TRACE_DEBUG(sc, "scsi status error",0,0); 571 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 572 if (((ccb->csio.cdb_io.cdb_bytes[0] == 0x1A) && 573 (hdr->status_block.error == TWS_ERROR_NOT_SUPPORTED))) { 574 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 575 TWS_TRACE_DEBUG(sc, "page mode not supported",0,0); 576 } 577 } 578 579 /* if there were no error simply mark complete error */ 580 if (ccb->ccb_h.status == 0) 581 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 582 583 sense_data = (u_int8_t *)&ccb->csio.sense_data; 584 if (sense_data) { 585 memcpy(sense_data, hdr->sense_data, TWS_SENSE_DATA_LENGTH ); 586 ccb->csio.sense_len = TWS_SENSE_DATA_LENGTH; 587 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 588 } 589 ccb->csio.scsi_status = req->cmd_pkt->cmd.pkt_a.status; 590 591 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 592 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 593 xpt_done(ccb); 594 lockmgr(&sc->sim_lock, LK_RELEASE); 595 596 callout_stop(req->ccb_ptr->ccb_h.timeout_ch); 597 tws_unmap_request(req->sc, req); 598 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 599 tws_q_remove_request(sc, req, TWS_BUSY_Q); 600 tws_q_insert_tail(sc, req, TWS_FREE_Q); 601 lockmgr(&sc->q_lock, LK_RELEASE); 602 603 } 604 605 static void 606 tws_passthru_err_complete(struct tws_request *req, 607 struct tws_command_header *hdr) 608 { 609 610 TWS_TRACE_DEBUG(req->sc, "entry", hdr, req->request_id); 611 req->error_code = hdr->status_block.error; 612 memcpy(&(req->cmd_pkt->hdr), hdr, sizeof(struct tws_command_header)); 613 tws_passthru_complete(req); 614 } 615 616 static void 617 tws_drain_busy_queue(struct tws_softc *sc) 618 { 619 620 struct tws_request *req; 621 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 622 623 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 624 req = tws_q_remove_tail(sc, TWS_BUSY_Q); 625 lockmgr(&sc->q_lock, LK_RELEASE); 626 while ( req ) { 627 callout_stop(req->ccb_ptr->ccb_h.timeout_ch); 628 tws_unmap_request(req->sc, req); 629 630 TWS_TRACE_DEBUG(sc, "drained", 0, req->request_id); 631 632 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 633 req->ccb_ptr->ccb_h.status = CAM_REQUEUE_REQ; 634 xpt_done(req->ccb_ptr); 635 lockmgr(&sc->sim_lock, LK_RELEASE); 636 637 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 638 tws_q_insert_tail(sc, req, TWS_FREE_Q); 639 req = tws_q_remove_tail(sc, TWS_BUSY_Q); 640 lockmgr(&sc->q_lock, LK_RELEASE); 641 } 642 643 } 644 645 static void 646 tws_drain_reserved_reqs(struct tws_softc *sc) 647 { 648 649 struct tws_request *r; 650 651 r = &sc->reqs[1]; 652 if ( r->state != TWS_REQ_STATE_FREE ) { 653 TWS_TRACE_DEBUG(sc, "drained aen req", 0, 0); 654 callout_stop(&r->thandle); 655 tws_unmap_request(sc, r); 656 kfree(r->data, M_TWS); 657 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 658 r->state = TWS_REQ_STATE_FREE; 659 lockmgr(&sc->gen_lock, LK_RELEASE); 660 } 661 r = &sc->reqs[2]; 662 if ( r->state != TWS_REQ_STATE_FREE ) { 663 TWS_TRACE_DEBUG(sc, "drained passthru req", 0, 0); 664 r->error_code = TWS_REQ_REQUEUE; 665 tws_passthru_complete(r); 666 } 667 r = &sc->reqs[3]; 668 if ( r->state != TWS_REQ_STATE_FREE ) { 669 TWS_TRACE_DEBUG(sc, "drained set param req", 0, 0); 670 tws_getset_param_complete(r); 671 } 672 673 } 674 675 static void 676 tws_drain_response_queue(struct tws_softc *sc) 677 { 678 tws_intr_resp(sc); 679 } 680 681 682 static int32_t 683 tws_execute_scsi(struct tws_softc *sc, union ccb *ccb) 684 { 685 struct tws_command_packet *cmd_pkt; 686 struct tws_request *req; 687 struct ccb_hdr *ccb_h = &(ccb->ccb_h); 688 struct ccb_scsiio *csio = &(ccb->csio); 689 int error; 690 u_int16_t lun; 691 692 KKASSERT(lockstatus(&sc->sim_lock, curthread) != 0); 693 if (ccb_h->target_id >= TWS_MAX_NUM_UNITS) { 694 TWS_TRACE_DEBUG(sc, "traget id too big", ccb_h->target_id, ccb_h->target_lun); 695 ccb_h->status |= CAM_TID_INVALID; 696 xpt_done(ccb); 697 return(0); 698 } 699 if (ccb_h->target_lun >= TWS_MAX_NUM_LUNS) { 700 TWS_TRACE_DEBUG(sc, "target lun 2 big", ccb_h->target_id, ccb_h->target_lun); 701 ccb_h->status |= CAM_LUN_INVALID; 702 xpt_done(ccb); 703 return(0); 704 } 705 706 if(ccb_h->flags & CAM_CDB_PHYS) { 707 TWS_TRACE_DEBUG(sc, "cdb phy", ccb_h->target_id, ccb_h->target_lun); 708 ccb_h->status = CAM_REQ_CMP_ERR; 709 xpt_done(ccb); 710 return(0); 711 } 712 713 /* 714 * We are going to work on this request. Mark it as enqueued (though 715 * we don't actually queue it...) 716 */ 717 ccb_h->status |= CAM_SIM_QUEUED; 718 719 req = tws_get_request(sc, TWS_SCSI_IO_REQ); 720 if ( !req ) { 721 TWS_TRACE_DEBUG(sc, "no reqs", ccb_h->target_id, ccb_h->target_lun); 722 /* tws_freeze_simq(sc); */ 723 ccb_h->status |= CAM_REQUEUE_REQ; 724 xpt_done(ccb); 725 return(0); 726 } 727 728 if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 729 if(ccb_h->flags & CAM_DIR_IN) 730 req->flags = TWS_DIR_IN; 731 else 732 req->flags = TWS_DIR_OUT; 733 } else { 734 req->flags = TWS_DIR_NONE; /* no data */ 735 } 736 737 req->type = TWS_SCSI_IO_REQ; 738 req->cb = tws_scsi_complete; 739 740 cmd_pkt = req->cmd_pkt; 741 /* cmd_pkt->hdr.header_desc.size_header = 128; */ 742 cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI; 743 cmd_pkt->cmd.pkt_a.unit = ccb_h->target_id; 744 cmd_pkt->cmd.pkt_a.status = 0; 745 cmd_pkt->cmd.pkt_a.sgl_offset = 16; 746 747 /* lower nibble */ 748 lun = ccb_h->target_lun & 0XF; 749 lun = lun << 12; 750 cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun | req->request_id; 751 /* upper nibble */ 752 lun = ccb_h->target_lun & 0XF0; 753 lun = lun << 8; 754 cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries = lun; 755 756 #ifdef TWS_DEBUG 757 if ( csio->cdb_len > 16 ) 758 TWS_TRACE(sc, "cdb len too big", ccb_h->target_id, csio->cdb_len); 759 #endif 760 761 if(ccb_h->flags & CAM_CDB_POINTER) 762 bcopy(csio->cdb_io.cdb_ptr, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len); 763 else 764 bcopy(csio->cdb_io.cdb_bytes, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len); 765 766 if (!(ccb_h->flags & CAM_DATA_PHYS)) { 767 /* Virtual data addresses. Need to convert them... */ 768 if (!(ccb_h->flags & CAM_SCATTER_VALID)) { 769 if (csio->dxfer_len > TWS_MAX_IO_SIZE) { 770 TWS_TRACE(sc, "I/O is big", csio->dxfer_len, 0); 771 tws_release_request(req); 772 ccb_h->status = CAM_REQ_TOO_BIG; 773 xpt_done(ccb); 774 return(0); 775 } 776 777 req->length = csio->dxfer_len; 778 if (req->length) { 779 req->data = csio->data_ptr; 780 /* there is 1 sgl_entrie */ 781 /* cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= 1; */ 782 } 783 } else { 784 TWS_TRACE_DEBUG(sc, "got sglist", ccb_h->target_id, ccb_h->target_lun); 785 tws_release_request(req); 786 ccb_h->status = CAM_REQ_CMP_ERR; 787 xpt_done(ccb); 788 return(0); 789 } 790 } else { 791 /* Data addresses are physical. */ 792 TWS_TRACE_DEBUG(sc, "Phy data addr", ccb_h->target_id, ccb_h->target_lun); 793 tws_release_request(req); 794 ccb_h->status = CAM_REQ_CMP_ERR; 795 ccb_h->status |= CAM_RELEASE_SIMQ; 796 ccb_h->status &= ~CAM_SIM_QUEUED; 797 xpt_done(ccb); 798 return(0); 799 } 800 /* save ccb ptr */ 801 req->ccb_ptr = ccb; 802 /* 803 * tws_map_load_data_callback will fill in the SGL, 804 * and submit the I/O. 805 */ 806 sc->stats.scsi_ios++; 807 callout_reset(ccb_h->timeout_ch, (ccb_h->timeout * hz)/1000, 808 tws_timeout, req); 809 error = tws_map_request(sc, req); 810 return(error); 811 } 812 813 814 int 815 tws_send_scsi_cmd(struct tws_softc *sc, int cmd) 816 { 817 818 struct tws_request *req; 819 struct tws_command_packet *cmd_pkt; 820 int error; 821 822 TWS_TRACE_DEBUG(sc, "entry",sc, cmd); 823 req = tws_get_request(sc, TWS_AEN_FETCH_REQ); 824 825 if ( req == NULL ) 826 return(ENOMEM); 827 828 req->type = TWS_AEN_FETCH_REQ; 829 req->cb = tws_aen_complete; 830 831 cmd_pkt = req->cmd_pkt; 832 cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI; 833 cmd_pkt->cmd.pkt_a.status = 0; 834 cmd_pkt->cmd.pkt_a.unit = 0; 835 cmd_pkt->cmd.pkt_a.sgl_offset = 16; 836 cmd_pkt->cmd.pkt_a.lun_l4__req_id = req->request_id; 837 838 cmd_pkt->cmd.pkt_a.cdb[0] = (u_int8_t)cmd; 839 cmd_pkt->cmd.pkt_a.cdb[4] = 128; 840 841 req->length = TWS_SECTOR_SIZE; 842 req->data = kmalloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT | M_ZERO); 843 if ( req->data == NULL ) 844 return(ENOMEM); 845 req->flags = TWS_DIR_IN; 846 847 callout_reset(&req->thandle, (TWS_IO_TIMEOUT * hz), tws_timeout, req); 848 error = tws_map_request(sc, req); 849 return(error); 850 851 } 852 853 int 854 tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 855 u_int32_t param_size, void *data) 856 { 857 struct tws_request *req; 858 struct tws_command_packet *cmd_pkt; 859 union tws_command_giga *cmd; 860 struct tws_getset_param *param; 861 int error; 862 863 req = tws_get_request(sc, TWS_GETSET_PARAM_REQ); 864 if ( req == NULL ) { 865 TWS_TRACE_DEBUG(sc, "null req", 0, 0); 866 return(ENOMEM); 867 } 868 869 req->length = TWS_SECTOR_SIZE; 870 req->data = kmalloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT | M_ZERO); 871 if ( req->data == NULL ) 872 return(ENOMEM); 873 param = (struct tws_getset_param *)req->data; 874 875 req->cb = tws_getset_param_complete; 876 req->flags = TWS_DIR_OUT; 877 cmd_pkt = req->cmd_pkt; 878 879 cmd = &cmd_pkt->cmd.pkt_g; 880 cmd->param.sgl_off__opcode = 881 BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_SET_PARAM); 882 cmd->param.request_id = (u_int8_t)req->request_id; 883 cmd->param.host_id__unit = 0; 884 cmd->param.param_count = 1; 885 cmd->param.size = 2; /* map routine will add sgls */ 886 887 /* Specify which parameter we want to set. */ 888 param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR); 889 param->parameter_id = (u_int8_t)(param_id); 890 param->parameter_size_bytes = (u_int16_t)param_size; 891 memcpy(param->data, data, param_size); 892 893 callout_reset(&req->thandle, (TWS_IO_TIMEOUT * hz), tws_timeout, req); 894 error = tws_map_request(sc, req); 895 return(error); 896 897 } 898 899 int 900 tws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 901 u_int32_t param_size, void *data) 902 { 903 struct tws_request *req; 904 struct tws_command_packet *cmd_pkt; 905 union tws_command_giga *cmd; 906 struct tws_getset_param *param; 907 u_int16_t reqid; 908 u_int64_t mfa; 909 int error = SUCCESS; 910 911 912 req = tws_get_request(sc, TWS_GETSET_PARAM_REQ); 913 if ( req == NULL ) { 914 TWS_TRACE_DEBUG(sc, "null req", 0, 0); 915 return(FAILURE); 916 } 917 918 req->length = TWS_SECTOR_SIZE; 919 req->data = kmalloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT | M_ZERO); 920 if ( req->data == NULL ) 921 return(FAILURE); 922 param = (struct tws_getset_param *)req->data; 923 924 req->cb = NULL; 925 req->flags = TWS_DIR_IN; 926 cmd_pkt = req->cmd_pkt; 927 928 cmd = &cmd_pkt->cmd.pkt_g; 929 cmd->param.sgl_off__opcode = 930 BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_GET_PARAM); 931 cmd->param.request_id = (u_int8_t)req->request_id; 932 cmd->param.host_id__unit = 0; 933 cmd->param.param_count = 1; 934 cmd->param.size = 2; /* map routine will add sgls */ 935 936 /* Specify which parameter we want to set. */ 937 param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR); 938 param->parameter_id = (u_int8_t)(param_id); 939 param->parameter_size_bytes = (u_int16_t)param_size; 940 941 tws_map_request(sc, req); 942 reqid = tws_poll4_response(sc, &mfa); 943 tws_unmap_request(sc, req); 944 945 if ( reqid == TWS_GETSET_PARAM_REQ ) { 946 memcpy(data, param->data, param_size); 947 } else { 948 error = FAILURE; 949 950 } 951 952 kfree(req->data, M_TWS); 953 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 954 req->state = TWS_REQ_STATE_FREE; 955 lockmgr(&sc->gen_lock, LK_RELEASE); 956 return(error); 957 958 } 959 960 void 961 tws_unmap_request(struct tws_softc *sc, struct tws_request *req) 962 { 963 964 if (req->data != NULL) { 965 if ( req->flags & TWS_DIR_IN ) 966 bus_dmamap_sync(sc->data_tag, req->dma_map, 967 BUS_DMASYNC_POSTREAD); 968 if ( req->flags & TWS_DIR_OUT ) 969 bus_dmamap_sync(sc->data_tag, req->dma_map, 970 BUS_DMASYNC_POSTWRITE); 971 lockmgr(&sc->io_lock, LK_EXCLUSIVE); 972 bus_dmamap_unload(sc->data_tag, req->dma_map); 973 lockmgr(&sc->io_lock, LK_RELEASE); 974 } 975 } 976 977 int32_t 978 tws_map_request(struct tws_softc *sc, struct tws_request *req) 979 { 980 int32_t error = 0; 981 982 983 /* If the command involves data, map that too. */ 984 if (req->data != NULL) { 985 /* 986 * Map the data buffer into bus space and build the SG list. 987 */ 988 lockmgr(&sc->io_lock, LK_EXCLUSIVE); 989 error = bus_dmamap_load(sc->data_tag, req->dma_map, 990 req->data, req->length, 991 tws_dmamap_data_load_cbfn, req, 992 BUS_DMA_WAITOK); 993 lockmgr(&sc->io_lock, LK_RELEASE); 994 995 if (error == EINPROGRESS) { 996 TWS_TRACE(sc, "in progress", 0, error); 997 /* tws_freeze_simq(sc); */ 998 error = TWS_REQ_ERR_INPROGRESS; 999 } 1000 } else { /* no data involved */ 1001 error = tws_submit_command(sc, req); 1002 } 1003 req->error_code = error; 1004 return(error); 1005 } 1006 1007 1008 static void 1009 tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs, 1010 int nseg, int error) 1011 { 1012 1013 struct tws_request *req = (struct tws_request *)arg; 1014 struct tws_softc *sc = req->sc; 1015 u_int16_t sgls = nseg; 1016 void *sgl_ptr; 1017 struct tws_cmd_generic *gcmd; 1018 1019 if ( error == EFBIG ) 1020 TWS_TRACE(sc, "not enough data segs", 0, nseg); 1021 1022 1023 if ( req->flags & TWS_DIR_IN ) 1024 bus_dmamap_sync(req->sc->data_tag, req->dma_map, 1025 BUS_DMASYNC_PREREAD); 1026 if ( req->flags & TWS_DIR_OUT ) 1027 bus_dmamap_sync(req->sc->data_tag, req->dma_map, 1028 BUS_DMASYNC_PREWRITE); 1029 if ( segs ) { 1030 if ( (req->type == TWS_PASSTHRU_REQ && 1031 GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) != 1032 TWS_FW_CMD_EXECUTE_SCSI) || 1033 req->type == TWS_GETSET_PARAM_REQ) { 1034 gcmd = &req->cmd_pkt->cmd.pkt_g.generic; 1035 sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size; 1036 gcmd->size += sgls * 1037 ((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 :2 ); 1038 tws_fill_sg_list(req->sc, segs, sgl_ptr, sgls); 1039 1040 } else { 1041 tws_fill_sg_list(req->sc, segs, 1042 (void *)req->cmd_pkt->cmd.pkt_a.sg_list, sgls); 1043 req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ; 1044 } 1045 } 1046 1047 1048 req->error_code = tws_submit_command(req->sc, req); 1049 1050 } 1051 1052 1053 static void 1054 tws_fill_sg_list(struct tws_softc *sc, void *sgl_src, void *sgl_dest, 1055 u_int16_t num_sgl_entries) 1056 { 1057 int i; 1058 1059 if ( sc->is64bit ) { 1060 struct tws_sg_desc64 *sgl_s = (struct tws_sg_desc64 *)sgl_src; 1061 1062 if ( !tws_use_32bit_sgls ) { 1063 struct tws_sg_desc64 *sgl_d = (struct tws_sg_desc64 *)sgl_dest; 1064 if ( num_sgl_entries > TWS_MAX_64BIT_SG_ELEMENTS ) 1065 TWS_TRACE(sc, "64bit sg overflow", num_sgl_entries, 0); 1066 for (i = 0; i < num_sgl_entries; i++) { 1067 sgl_d[i].address = sgl_s->address; 1068 sgl_d[i].length = sgl_s->length; 1069 sgl_d[i].flag = 0; 1070 sgl_d[i].reserved = 0; 1071 sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) + 1072 sizeof(bus_dma_segment_t)); 1073 } 1074 } else { 1075 struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest; 1076 if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS ) 1077 TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0); 1078 for (i = 0; i < num_sgl_entries; i++) { 1079 sgl_d[i].address = sgl_s->address; 1080 sgl_d[i].length = sgl_s->length; 1081 sgl_d[i].flag = 0; 1082 sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) + 1083 sizeof(bus_dma_segment_t)); 1084 } 1085 } 1086 } else { 1087 struct tws_sg_desc32 *sgl_s = (struct tws_sg_desc32 *)sgl_src; 1088 struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest; 1089 1090 if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS ) 1091 TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0); 1092 1093 1094 for (i = 0; i < num_sgl_entries; i++) { 1095 sgl_d[i].address = sgl_s[i].address; 1096 sgl_d[i].length = sgl_s[i].length; 1097 sgl_d[i].flag = 0; 1098 } 1099 } 1100 } 1101 1102 1103 void 1104 tws_intr(void *arg) 1105 { 1106 struct tws_softc *sc = (struct tws_softc *)arg; 1107 u_int32_t histat=0, db=0; 1108 1109 KASSERT(sc, ("null softc")); 1110 1111 sc->stats.num_intrs++; 1112 histat = tws_read_reg(sc, TWS_I2O0_HISTAT, 4); 1113 if ( histat & TWS_BIT2 ) { 1114 TWS_TRACE_DEBUG(sc, "door bell :)", histat, TWS_I2O0_HISTAT); 1115 db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1116 if ( db & TWS_BIT21 ) { 1117 tws_intr_attn_error(sc); 1118 return; 1119 } 1120 if ( db & TWS_BIT18 ) { 1121 tws_intr_attn_aen(sc); 1122 } 1123 } 1124 1125 if ( histat & TWS_BIT3 ) { 1126 tws_intr_resp(sc); 1127 } 1128 } 1129 1130 static void 1131 tws_intr_attn_aen(struct tws_softc *sc) 1132 { 1133 u_int32_t db=0; 1134 1135 /* maskoff db intrs untill all the aens are fetched */ 1136 /* tws_disable_db_intr(sc); */ 1137 tws_fetch_aen(sc); 1138 tws_write_reg(sc, TWS_I2O0_HOBDBC, TWS_BIT18, 4); 1139 db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1140 1141 } 1142 1143 static void 1144 tws_intr_attn_error(struct tws_softc *sc) 1145 { 1146 u_int32_t db=0; 1147 1148 TWS_TRACE(sc, "attn error", 0, 0); 1149 tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4); 1150 db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1151 device_printf(sc->tws_dev, "Micro controller error.\n"); 1152 tws_reset(sc); 1153 } 1154 1155 static void 1156 tws_intr_resp(struct tws_softc *sc) 1157 { 1158 u_int16_t req_id; 1159 u_int64_t mfa; 1160 1161 while ( tws_get_response(sc, &req_id, &mfa) ) { 1162 sc->stats.reqs_out++; 1163 if ( req_id == TWS_INVALID_REQID ) { 1164 TWS_TRACE_DEBUG(sc, "invalid req_id", mfa, req_id); 1165 sc->stats.reqs_errored++; 1166 tws_err_complete(sc, mfa); 1167 continue; 1168 } 1169 1170 sc->reqs[req_id].cb(&sc->reqs[req_id]); 1171 } 1172 1173 } 1174 1175 1176 static void 1177 tws_poll(struct cam_sim *sim) 1178 { 1179 struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim); 1180 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 1181 tws_intr(sc); 1182 } 1183 1184 static void 1185 tws_timeout(void *arg) 1186 { 1187 struct tws_request *req = (struct tws_request *)arg; 1188 struct tws_softc *sc = req->sc; 1189 1190 1191 if ( tws_get_state(sc) != TWS_RESET ) { 1192 device_printf(sc->tws_dev, "Request timed out.\n"); 1193 tws_reset(sc); 1194 } 1195 } 1196 1197 void 1198 tws_reset(void *arg) 1199 { 1200 1201 struct tws_softc *sc = (struct tws_softc *)arg; 1202 1203 if ( tws_get_state(sc) == TWS_RESET ) { 1204 return; 1205 } 1206 device_printf(sc->tws_dev, "Resetting controller\n"); 1207 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 1208 tws_send_event(sc, TWS_RESET_START); 1209 lockmgr(&sc->gen_lock, LK_RELEASE); 1210 1211 tws_turn_off_interrupts(sc); 1212 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 1213 tws_freeze_simq(sc); 1214 lockmgr(&sc->sim_lock, LK_RELEASE); 1215 1216 tws_assert_soft_reset(sc); 1217 callout_reset(&sc->reset_cb_handle, hz/10, tws_reset_cb, sc); 1218 } 1219 1220 static void 1221 tws_reset_cb(void *arg) 1222 { 1223 1224 struct tws_softc *sc = (struct tws_softc *)arg; 1225 u_int32_t reg; 1226 1227 if ( tws_get_state(sc) != TWS_RESET ) { 1228 return; 1229 } 1230 reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4); 1231 if (!( reg & TWS_BIT13 )) { 1232 callout_reset(&sc->reset_cb_handle, hz/10, tws_reset_cb, sc); 1233 return; 1234 } 1235 tws_drain_response_queue(sc); 1236 tws_drain_busy_queue(sc); 1237 tws_drain_reserved_reqs(sc); 1238 callout_reset(&sc->reinit_handle, 5*hz, tws_reinit, sc); 1239 } 1240 1241 static void 1242 tws_reinit(void *arg) 1243 { 1244 1245 struct tws_softc *sc = (struct tws_softc *)arg; 1246 static int timeout_val=0, try=2 ; 1247 1248 if ( !tws_ctlr_ready(sc) ) { 1249 timeout_val += 5; 1250 if ( timeout_val >= TWS_RESET_TIMEOUT ) { 1251 timeout_val = 0; 1252 if ( try ) 1253 tws_assert_soft_reset(sc); 1254 try--; 1255 } 1256 callout_reset(&sc->reinit_handle, 5*hz, tws_reinit, sc); 1257 return; 1258 } 1259 1260 timeout_val=0; 1261 try = 2; 1262 sc->obfl_q_overrun = false; 1263 if ( tws_init_connect(sc, tws_queue_depth) ) { 1264 TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit); 1265 } 1266 tws_init_obfl_q(sc); 1267 1268 lockmgr(&sc->sim_lock, LK_EXCLUSIVE); 1269 tws_release_simq(sc); 1270 lockmgr(&sc->sim_lock, LK_RELEASE); 1271 tws_turn_on_interrupts(sc); 1272 1273 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 1274 tws_send_event(sc, TWS_RESET_COMPLETE); 1275 lockmgr(&sc->gen_lock, LK_RELEASE); 1276 if ( sc->chan ) { 1277 sc->chan = 0; 1278 wakeup((void *)&sc->chan); 1279 } 1280 1281 } 1282 1283 1284 static void 1285 tws_freeze_simq(struct tws_softc *sc) 1286 { 1287 1288 TWS_TRACE_DEBUG(sc, "freezeing", 0, 0); 1289 KKASSERT(lockstatus(&sc->sim_lock, curthread) != 0); 1290 xpt_freeze_simq(sc->sim, 1); 1291 1292 } 1293 static void 1294 tws_release_simq(struct tws_softc *sc) 1295 { 1296 1297 TWS_TRACE_DEBUG(sc, "unfreezeing", 0, 0); 1298 KKASSERT(lockstatus(&sc->sim_lock, curthread) != 0); 1299 xpt_release_simq(sc->sim, 1); 1300 1301 } 1302 1303 1304 TUNABLE_INT("hw.tws.cam_depth", &tws_cam_depth); 1305