tws_hdm.c revision 272000
1226026Sdelphij/* 2226026Sdelphij * Copyright (c) 2010, LSI Corp. 3226026Sdelphij * All rights reserved. 4226026Sdelphij * Author : Manjunath Ranganathaiah 5226026Sdelphij * Support: freebsdraid@lsi.com 6226026Sdelphij * 7226026Sdelphij * Redistribution and use in source and binary forms, with or without 8226026Sdelphij * modification, are permitted provided that the following conditions 9226026Sdelphij * are met: 10226026Sdelphij * 11226026Sdelphij * 1. Redistributions of source code must retain the above copyright 12226026Sdelphij * notice, this list of conditions and the following disclaimer. 13226026Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 14226026Sdelphij * notice, this list of conditions and the following disclaimer in 15226026Sdelphij * the documentation and/or other materials provided with the 16226026Sdelphij * distribution. 17226026Sdelphij * 3. Neither the name of the <ORGANIZATION> nor the names of its 18226026Sdelphij * contributors may be used to endorse or promote products derived 19226026Sdelphij * from this software without specific prior written permission. 20226026Sdelphij * 21226026Sdelphij * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22226026Sdelphij * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23226026Sdelphij * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24226026Sdelphij * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25226026Sdelphij * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26226026Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27226026Sdelphij * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28226026Sdelphij * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29226026Sdelphij * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30226026Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31226026Sdelphij * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32226026Sdelphij * POSSIBILITY OF SUCH DAMAGE. 33226026Sdelphij * 34226026Sdelphij * $FreeBSD: head/sys/dev/tws/tws_hdm.c 272000 2014-09-22 20:38:01Z jhb $ 35226026Sdelphij */ 36226026Sdelphij 37226026Sdelphij 38226026Sdelphij#include <dev/tws/tws.h> 39226026Sdelphij#include <dev/tws/tws_services.h> 40226026Sdelphij#include <dev/tws/tws_hdm.h> 41226026Sdelphij 42226026Sdelphij 43226026Sdelphijint tws_use_32bit_sgls=0; 44226026Sdelphijextern u_int64_t mfa_base; 45226026Sdelphijextern struct tws_request *tws_get_request(struct tws_softc *sc, 46226026Sdelphij u_int16_t type); 47226026Sdelphijextern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 48226026Sdelphij u_int8_t q_type ); 49226026Sdelphijextern struct tws_request * tws_q_remove_request(struct tws_softc *sc, 50226026Sdelphij struct tws_request *req, u_int8_t q_type ); 51226026Sdelphij 52226026Sdelphijextern void tws_cmd_complete(struct tws_request *req); 53226026Sdelphijextern void tws_print_stats(void *arg); 54226026Sdelphijextern int tws_send_scsi_cmd(struct tws_softc *sc, int cmd); 55226026Sdelphijextern int tws_set_param(struct tws_softc *sc, u_int32_t table_id, 56226026Sdelphij u_int32_t param_id, u_int32_t param_size, void *data); 57226026Sdelphijextern int tws_get_param(struct tws_softc *sc, u_int32_t table_id, 58226026Sdelphij u_int32_t param_id, u_int32_t param_size, void *data); 59226026Sdelphijextern void tws_reset(void *arg); 60226026Sdelphij 61226026Sdelphijint tws_init_connect(struct tws_softc *sc, u_int16_t mc); 62226026Sdelphijint tws_init_ctlr(struct tws_softc *sc); 63226026Sdelphijint tws_submit_command(struct tws_softc *sc, struct tws_request *req); 64226026Sdelphijvoid tws_nop_cmd(void *arg); 65226026Sdelphiju_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa); 66226026Sdelphijboolean tws_get_response(struct tws_softc *sc, u_int16_t *req_id, 67226026Sdelphij u_int64_t *mfa); 68226026Sdelphijboolean tws_ctlr_ready(struct tws_softc *sc); 69226026Sdelphijvoid tws_turn_on_interrupts(struct tws_softc *sc); 70226026Sdelphijvoid tws_turn_off_interrupts(struct tws_softc *sc); 71226026Sdelphijboolean tws_ctlr_reset(struct tws_softc *sc); 72226026Sdelphijvoid tws_assert_soft_reset(struct tws_softc *sc); 73226026Sdelphij 74226026Sdelphijint tws_send_generic_cmd(struct tws_softc *sc, u_int8_t opcode); 75226026Sdelphijvoid tws_fetch_aen(void *arg); 76226026Sdelphijvoid tws_disable_db_intr(struct tws_softc *sc); 77226026Sdelphijvoid tws_enable_db_intr(struct tws_softc *sc); 78226026Sdelphijvoid tws_aen_synctime_with_host(struct tws_softc *sc); 79226026Sdelphijvoid tws_init_obfl_q(struct tws_softc *sc); 80226026Sdelphijvoid tws_display_ctlr_info(struct tws_softc *sc); 81226026Sdelphij 82226026Sdelphijint 83226026Sdelphijtws_init_ctlr(struct tws_softc *sc) 84226026Sdelphij{ 85226026Sdelphij u_int64_t reg; 86226026Sdelphij u_int32_t regh, regl; 87226026Sdelphij 88226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", sc, sc->is64bit); 89226026Sdelphij sc->obfl_q_overrun = false; 90226026Sdelphij if ( tws_init_connect(sc, tws_queue_depth) ) 91226026Sdelphij { 92226026Sdelphij TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit); 93226026Sdelphij return(FAILURE); 94226026Sdelphij 95226026Sdelphij } 96226026Sdelphij 97226026Sdelphij 98226026Sdelphij while( 1 ) { 99226026Sdelphij regh = tws_read_reg(sc, TWS_I2O0_IOPOBQPH, 4); 100226026Sdelphij regl = tws_read_reg(sc, TWS_I2O0_IOPOBQPL, 4); 101226026Sdelphij reg = (((u_int64_t)regh) << 32) | regl; 102247551Skevlo TWS_TRACE_DEBUG(sc, "host outbound cleanup",reg, regl); 103226026Sdelphij if ( regh == TWS_FIFO_EMPTY32 ) 104226026Sdelphij break; 105226026Sdelphij } 106226026Sdelphij 107226026Sdelphij tws_init_obfl_q(sc); 108226026Sdelphij tws_display_ctlr_info(sc); 109226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4); 110226026Sdelphij tws_turn_on_interrupts(sc); 111226026Sdelphij return(SUCCESS); 112226026Sdelphij} 113226026Sdelphij 114226026Sdelphijvoid 115226026Sdelphijtws_init_obfl_q(struct tws_softc *sc) 116226026Sdelphij{ 117226026Sdelphij int i=0; 118226026Sdelphij u_int64_t paddr; 119226026Sdelphij u_int32_t paddrh, paddrl, status; 120226026Sdelphij 121226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, sc->obfl_q_overrun); 122226026Sdelphij 123226026Sdelphij while ( i < tws_queue_depth ) { 124226026Sdelphij paddr = sc->sense_bufs[i].hdr_pkt_phy; 125226026Sdelphij paddrh = (u_int32_t)( paddr>>32); 126226026Sdelphij paddrl = (u_int32_t) paddr; 127226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBQPH, paddrh, 4); 128226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBQPL, paddrl, 4); 129226026Sdelphij 130226026Sdelphij status = tws_read_reg(sc, TWS_I2O0_STATUS, 4); 131226026Sdelphij if ( status & TWS_BIT13 ) { 132226026Sdelphij device_printf(sc->tws_dev, "OBFL Overrun\n"); 133226026Sdelphij sc->obfl_q_overrun = true; 134226026Sdelphij break; 135226026Sdelphij } 136226026Sdelphij i++; 137226026Sdelphij } 138226026Sdelphij 139226026Sdelphij if ( i == tws_queue_depth ) 140226026Sdelphij sc->obfl_q_overrun = false; 141226026Sdelphij} 142226026Sdelphij 143226026Sdelphijint 144226026Sdelphijtws_init_connect(struct tws_softc *sc, u_int16_t mcreadits ) 145226026Sdelphij{ 146226026Sdelphij struct tws_request *req; 147226026Sdelphij struct tws_cmd_init_connect *initc; 148226026Sdelphij u_int16_t reqid; 149226026Sdelphij u_int64_t mfa; 150226026Sdelphij 151226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, mcreadits); 152226026Sdelphij#if 0 153226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD); 154226026Sdelphij#else // 0 155226026Sdelphij req = &sc->reqs[TWS_REQ_TYPE_INTERNAL_CMD]; 156226026Sdelphij bzero(&req->cmd_pkt->cmd, sizeof(struct tws_command_apache)); 157226026Sdelphij req->data = NULL; 158226026Sdelphij req->length = 0; 159226026Sdelphij req->type = TWS_REQ_TYPE_INTERNAL_CMD; 160226026Sdelphij req->flags = TWS_DIR_UNKNOWN; 161226026Sdelphij req->error_code = TWS_REQ_RET_INVALID; 162226026Sdelphij req->cb = NULL; 163226026Sdelphij req->ccb_ptr = NULL; 164272000Sjhb callout_stop(&req->timeout); 165226026Sdelphij req->next = req->prev = NULL; 166226026Sdelphij req->state = TWS_REQ_STATE_BUSY; 167226026Sdelphij#endif // 0 168226026Sdelphij 169226026Sdelphij if ( req == NULL ) { 170226026Sdelphij TWS_TRACE_DEBUG(sc, "no requests", 0, 0); 171226026Sdelphij// device_printf(sc->tws_dev, "No requests for initConnect\n"); 172226026Sdelphij return(FAILURE); 173226026Sdelphij } 174226026Sdelphij 175226026Sdelphij tws_swap16(0xbeef); /* just for test */ 176226026Sdelphij tws_swap32(0xdeadbeef); /* just for test */ 177226026Sdelphij tws_swap64(0xdeadbeef); /* just for test */ 178226026Sdelphij initc = &(req->cmd_pkt->cmd.pkt_g.init_connect); 179226026Sdelphij /* req->cmd_pkt->hdr.header_desc.size_header = 128; */ 180226026Sdelphij 181226026Sdelphij initc->res1__opcode = 182226026Sdelphij BUILD_RES__OPCODE(0, TWS_FW_CMD_INIT_CONNECTION); 183226026Sdelphij initc->size = 6; 184226026Sdelphij initc->request_id = req->request_id; 185226026Sdelphij initc->message_credits = mcreadits; 186226026Sdelphij initc->features |= TWS_BIT_EXTEND; 187226026Sdelphij if ( sc->is64bit && !tws_use_32bit_sgls ) 188226026Sdelphij initc->features |= TWS_64BIT_SG_ADDRESSES; 189226026Sdelphij /* assuming set features is always on */ 190226026Sdelphij 191226026Sdelphij initc->size = 6; 192226026Sdelphij initc->fw_srl = sc->cinfo.working_srl = TWS_CURRENT_FW_SRL; 193226026Sdelphij initc->fw_arch_id = 0; 194226026Sdelphij initc->fw_branch = sc->cinfo.working_branch = 0; 195226026Sdelphij initc->fw_build = sc->cinfo.working_build = 0; 196226026Sdelphij 197226026Sdelphij req->error_code = tws_submit_command(sc, req); 198226026Sdelphij reqid = tws_poll4_response(sc, &mfa); 199226026Sdelphij if ( reqid != TWS_INVALID_REQID && reqid == req->request_id ) { 200226026Sdelphij sc->cinfo.fw_on_ctlr_srl = initc->fw_srl; 201226026Sdelphij sc->cinfo.fw_on_ctlr_branch = initc->fw_branch; 202226026Sdelphij sc->cinfo.fw_on_ctlr_build = initc->fw_build; 203226026Sdelphij sc->stats.reqs_out++; 204226026Sdelphij req->state = TWS_REQ_STATE_FREE; 205226026Sdelphij } 206226026Sdelphij else { 207226026Sdelphij /* 208226026Sdelphij * REVISIT::If init connect fails we need to reset the ctlr 209226026Sdelphij * and try again? 210226026Sdelphij */ 211226026Sdelphij TWS_TRACE(sc, "unexpected req_id ", reqid, 0); 212226026Sdelphij TWS_TRACE(sc, "INITCONNECT FAILED", reqid, 0); 213226026Sdelphij return(FAILURE); 214226026Sdelphij } 215226026Sdelphij return(SUCCESS); 216226026Sdelphij} 217226026Sdelphij 218226026Sdelphijvoid 219226026Sdelphijtws_display_ctlr_info(struct tws_softc *sc) 220226026Sdelphij{ 221226026Sdelphij 222226026Sdelphij uint8_t fw_ver[16], bios_ver[16], ctlr_model[16], num_phys=0; 223226026Sdelphij uint32_t error[4]; 224226026Sdelphij 225226026Sdelphij error[0] = tws_get_param(sc, TWS_PARAM_PHYS_TABLE, 226226026Sdelphij TWS_PARAM_CONTROLLER_PHYS_COUNT, 1, &num_phys); 227226026Sdelphij error[1] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE, 228226026Sdelphij TWS_PARAM_VERSION_FW, 16, fw_ver); 229226026Sdelphij error[2] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE, 230226026Sdelphij TWS_PARAM_VERSION_BIOS, 16, bios_ver); 231226026Sdelphij error[3] = tws_get_param(sc, TWS_PARAM_VERSION_TABLE, 232226026Sdelphij TWS_PARAM_CTLR_MODEL, 16, ctlr_model); 233226026Sdelphij 234226026Sdelphij if ( !error[0] && !error[1] && !error[2] && !error[3] ) { 235226026Sdelphij device_printf( sc->tws_dev, 236226026Sdelphij "Controller details: Model %.16s, %d Phys, Firmware %.16s, BIOS %.16s\n", 237226026Sdelphij ctlr_model, num_phys, fw_ver, bios_ver); 238226026Sdelphij } 239226026Sdelphij 240226026Sdelphij} 241226026Sdelphij 242226026Sdelphijint 243226026Sdelphijtws_send_generic_cmd(struct tws_softc *sc, u_int8_t opcode) 244226026Sdelphij{ 245226026Sdelphij struct tws_request *req; 246226026Sdelphij struct tws_cmd_generic *cmd; 247226026Sdelphij 248226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", sc, opcode); 249226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD); 250226026Sdelphij 251226026Sdelphij if ( req == NULL ) { 252226026Sdelphij TWS_TRACE_DEBUG(sc, "no requests", 0, 0); 253226026Sdelphij return(FAILURE); 254226026Sdelphij } 255226026Sdelphij 256226026Sdelphij cmd = &(req->cmd_pkt->cmd.pkt_g.generic); 257226026Sdelphij bzero(cmd, sizeof(struct tws_cmd_generic)); 258226026Sdelphij /* req->cmd_pkt->hdr.header_desc.size_header = 128; */ 259226026Sdelphij req->cb = tws_cmd_complete; 260226026Sdelphij 261226026Sdelphij cmd->sgl_off__opcode = BUILD_RES__OPCODE(0, opcode); 262226026Sdelphij cmd->size = 2; 263226026Sdelphij cmd->request_id = req->request_id; 264226026Sdelphij cmd->host_id__unit = 0; 265226026Sdelphij cmd->status = 0; 266226026Sdelphij cmd->flags = 0; 267226026Sdelphij cmd->count = 0; 268226026Sdelphij 269226026Sdelphij req->error_code = tws_submit_command(sc, req); 270226026Sdelphij 271226026Sdelphij return(SUCCESS); 272226026Sdelphij 273226026Sdelphij} 274226026Sdelphij 275226026Sdelphij 276226026Sdelphijint 277226026Sdelphijtws_submit_command(struct tws_softc *sc, struct tws_request *req) 278226026Sdelphij{ 279226026Sdelphij u_int32_t regl, regh; 280226026Sdelphij u_int64_t mfa=0; 281226026Sdelphij 282226026Sdelphij /* 283226026Sdelphij * mfa register read and write must be in order. 284226026Sdelphij * Get the io_lock to protect against simultinous 285226026Sdelphij * passthru calls 286226026Sdelphij */ 287226026Sdelphij mtx_lock(&sc->io_lock); 288226026Sdelphij 289226026Sdelphij if ( sc->obfl_q_overrun ) { 290226026Sdelphij tws_init_obfl_q(sc); 291226026Sdelphij } 292226026Sdelphij 293226026Sdelphij#ifdef TWS_PULL_MODE_ENABLE 294226026Sdelphij regh = (u_int32_t)(req->cmd_pkt_phy >> 32); 295226026Sdelphij /* regh = regh | TWS_MSG_ACC_MASK; */ 296226026Sdelphij mfa = regh; 297226026Sdelphij mfa = mfa << 32; 298226026Sdelphij regl = (u_int32_t)req->cmd_pkt_phy; 299226026Sdelphij regl = regl | TWS_BIT0; 300226026Sdelphij mfa = mfa | regl; 301226026Sdelphij#else 302226026Sdelphij regh = tws_read_reg(sc, TWS_I2O0_HIBQPH, 4); 303226026Sdelphij mfa = regh; 304226026Sdelphij mfa = mfa << 32; 305226026Sdelphij regl = tws_read_reg(sc, TWS_I2O0_HIBQPL, 4); 306226026Sdelphij mfa = mfa | regl; 307226026Sdelphij#endif 308226026Sdelphij 309226026Sdelphij mtx_unlock(&sc->io_lock); 310226026Sdelphij 311226026Sdelphij if ( mfa == TWS_FIFO_EMPTY ) { 312226026Sdelphij TWS_TRACE_DEBUG(sc, "inbound fifo empty", mfa, 0); 313226026Sdelphij 314226026Sdelphij /* 315226026Sdelphij * Generaly we should not get here. 316226026Sdelphij * If the fifo was empty we can't do any thing much 317226026Sdelphij * retry later 318226026Sdelphij */ 319226026Sdelphij return(TWS_REQ_RET_PEND_NOMFA); 320226026Sdelphij 321226026Sdelphij } 322226026Sdelphij 323226026Sdelphij#ifndef TWS_PULL_MODE_ENABLE 324226026Sdelphij for (int i=mfa; i<(sizeof(struct tws_command_packet)+ mfa - 325226026Sdelphij sizeof( struct tws_command_header)); i++) { 326226026Sdelphij 327226026Sdelphij bus_space_write_1(sc->bus_mfa_tag, sc->bus_mfa_handle,i, 328226026Sdelphij ((u_int8_t *)&req->cmd_pkt->cmd)[i-mfa]); 329226026Sdelphij 330226026Sdelphij } 331226026Sdelphij#endif 332226026Sdelphij 333226026Sdelphij if ( req->type == TWS_REQ_TYPE_SCSI_IO ) { 334226026Sdelphij mtx_lock(&sc->q_lock); 335226026Sdelphij tws_q_insert_tail(sc, req, TWS_BUSY_Q); 336226026Sdelphij mtx_unlock(&sc->q_lock); 337226026Sdelphij } 338226026Sdelphij 339226026Sdelphij /* 340226026Sdelphij * mfa register read and write must be in order. 341226026Sdelphij * Get the io_lock to protect against simultinous 342226026Sdelphij * passthru calls 343226026Sdelphij */ 344226026Sdelphij mtx_lock(&sc->io_lock); 345226026Sdelphij 346226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIBQPH, regh, 4); 347226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIBQPL, regl, 4); 348226026Sdelphij 349226026Sdelphij sc->stats.reqs_in++; 350226026Sdelphij mtx_unlock(&sc->io_lock); 351226026Sdelphij 352226026Sdelphij return(TWS_REQ_RET_SUBMIT_SUCCESS); 353226026Sdelphij 354226026Sdelphij} 355226026Sdelphij 356226026Sdelphij/* 357226026Sdelphij * returns true if the respose was available othewise, false. 358226026Sdelphij * In the case of error the arg mfa will contain the address and 359226026Sdelphij * req_id will be TWS_INVALID_REQID 360226026Sdelphij */ 361226026Sdelphijboolean 362226026Sdelphijtws_get_response(struct tws_softc *sc, u_int16_t *req_id, u_int64_t *mfa) 363226026Sdelphij{ 364226026Sdelphij u_int64_t out_mfa=0, val=0; 365226026Sdelphij struct tws_outbound_response out_res; 366226026Sdelphij 367226026Sdelphij *req_id = TWS_INVALID_REQID; 368226026Sdelphij out_mfa = (u_int64_t)tws_read_reg(sc, TWS_I2O0_HOBQPH, 4); 369226026Sdelphij 370226026Sdelphij if ( out_mfa == TWS_FIFO_EMPTY32 ) { 371226026Sdelphij return(false); 372226026Sdelphij 373226026Sdelphij } 374226026Sdelphij out_mfa = out_mfa << 32; 375226026Sdelphij val = tws_read_reg(sc, TWS_I2O0_HOBQPL, 4); 376226026Sdelphij out_mfa = out_mfa | val; 377226026Sdelphij 378226026Sdelphij out_res = *(struct tws_outbound_response *)&out_mfa; 379226026Sdelphij 380226026Sdelphij if ( !out_res.not_mfa ) { 381226026Sdelphij *mfa = out_mfa; 382226026Sdelphij return(true); 383226026Sdelphij } else { 384226026Sdelphij *req_id = out_res.request_id; 385226026Sdelphij } 386226026Sdelphij 387226026Sdelphij return(true); 388226026Sdelphij} 389226026Sdelphij 390226026Sdelphij 391226026Sdelphij 392226026Sdelphij 393226026Sdelphiju_int16_t 394226026Sdelphijtws_poll4_response(struct tws_softc *sc, u_int64_t *mfa) 395226026Sdelphij{ 396226026Sdelphij u_int16_t req_id; 397226026Sdelphij time_t endt; 398226026Sdelphij 399226026Sdelphij endt = TWS_LOCAL_TIME + TWS_POLL_TIMEOUT; 400226026Sdelphij do { 401226026Sdelphij if(tws_get_response(sc, &req_id, mfa)) { 402226026Sdelphij 403226026Sdelphij if ( req_id == TWS_INVALID_REQID ) { 404226026Sdelphij TWS_TRACE_DEBUG(sc, "invalid req_id", 0, req_id); 405226026Sdelphij return(TWS_INVALID_REQID); 406226026Sdelphij } 407226026Sdelphij return(req_id); 408226026Sdelphij } 409226026Sdelphij } while (TWS_LOCAL_TIME <= endt); 410226026Sdelphij TWS_TRACE_DEBUG(sc, "poll timeout", 0, 0); 411226026Sdelphij return(TWS_INVALID_REQID); 412226026Sdelphij} 413226026Sdelphij 414226026Sdelphijboolean 415226026Sdelphijtws_ctlr_ready(struct tws_softc *sc) 416226026Sdelphij{ 417226026Sdelphij u_int32_t reg; 418226026Sdelphij 419226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4); 420226026Sdelphij if ( reg & TWS_BIT13 ) 421226026Sdelphij return(true); 422226026Sdelphij else 423226026Sdelphij return(false); 424226026Sdelphij} 425226026Sdelphij 426226026Sdelphijvoid 427226026Sdelphijtws_turn_on_interrupts(struct tws_softc *sc) 428226026Sdelphij{ 429226026Sdelphij 430226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 431226026Sdelphij /* turn on responce and db interrupt only */ 432226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIMASK, TWS_BIT0, 4); 433226026Sdelphij 434226026Sdelphij} 435226026Sdelphij 436226026Sdelphijvoid 437226026Sdelphijtws_turn_off_interrupts(struct tws_softc *sc) 438226026Sdelphij{ 439226026Sdelphij 440226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 441226026Sdelphij 442226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIMASK, ~0, 4); 443226026Sdelphij 444226026Sdelphij} 445226026Sdelphij 446226026Sdelphijvoid 447226026Sdelphijtws_disable_db_intr(struct tws_softc *sc) 448226026Sdelphij{ 449226026Sdelphij u_int32_t reg; 450226026Sdelphij 451226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 452226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4); 453226026Sdelphij reg = reg | TWS_BIT2; 454226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIMASK, reg, 4); 455226026Sdelphij} 456226026Sdelphij 457226026Sdelphijvoid 458226026Sdelphijtws_enable_db_intr(struct tws_softc *sc) 459226026Sdelphij{ 460226026Sdelphij u_int32_t reg; 461226026Sdelphij 462226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 463226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4); 464226026Sdelphij reg = reg & ~TWS_BIT2; 465226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIMASK, reg, 4); 466226026Sdelphij} 467226026Sdelphij 468226026Sdelphijboolean 469226026Sdelphijtws_ctlr_reset(struct tws_softc *sc) 470226026Sdelphij{ 471226026Sdelphij 472226026Sdelphij u_int32_t reg; 473226026Sdelphij time_t endt; 474226026Sdelphij /* int i=0; */ 475226026Sdelphij 476226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 477226026Sdelphij 478226026Sdelphij tws_assert_soft_reset(sc); 479226026Sdelphij 480226026Sdelphij do { 481226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4); 482226026Sdelphij } while ( reg & TWS_BIT13 ); 483226026Sdelphij 484226026Sdelphij endt = TWS_LOCAL_TIME + TWS_RESET_TIMEOUT; 485226026Sdelphij do { 486226026Sdelphij if(tws_ctlr_ready(sc)) 487226026Sdelphij return(true); 488226026Sdelphij } while (TWS_LOCAL_TIME <= endt); 489226026Sdelphij return(false); 490226026Sdelphij 491226026Sdelphij} 492226026Sdelphij 493226026Sdelphijvoid 494226026Sdelphijtws_assert_soft_reset(struct tws_softc *sc) 495226026Sdelphij{ 496226026Sdelphij u_int32_t reg; 497226026Sdelphij 498226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_HIBDB, 4); 499226026Sdelphij TWS_TRACE_DEBUG(sc, "in bound door bell read ", reg, TWS_I2O0_HIBDB); 500226026Sdelphij tws_write_reg(sc, TWS_I2O0_HIBDB, reg | TWS_BIT8, 4); 501226026Sdelphij 502226026Sdelphij} 503226026Sdelphij 504226026Sdelphijvoid 505226026Sdelphijtws_fetch_aen(void *arg) 506226026Sdelphij{ 507226026Sdelphij struct tws_softc *sc = (struct tws_softc *)arg; 508226026Sdelphij int error = 0; 509226026Sdelphij 510226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 511226026Sdelphij 512226026Sdelphij if ((error = tws_send_scsi_cmd(sc, 0x03 /* REQUEST_SENSE */))) { 513226026Sdelphij TWS_TRACE_DEBUG(sc, "aen fetch send in progress", 0, 0); 514226026Sdelphij } 515226026Sdelphij} 516226026Sdelphij 517226026Sdelphijvoid 518226026Sdelphijtws_aen_synctime_with_host(struct tws_softc *sc) 519226026Sdelphij{ 520226026Sdelphij 521226026Sdelphij int error; 522226026Sdelphij long int sync_time; 523226026Sdelphij 524226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", sc, 0); 525226026Sdelphij 526226026Sdelphij sync_time = (TWS_LOCAL_TIME - (3 * 86400)) % 604800; 527226026Sdelphij TWS_TRACE_DEBUG(sc, "sync_time,ts", sync_time, time_second); 528226026Sdelphij TWS_TRACE_DEBUG(sc, "utc_offset", utc_offset(), 0); 529226026Sdelphij error = tws_set_param(sc, TWS_PARAM_TIME_TABLE, TWS_PARAM_TIME_SCHED_TIME, 530226026Sdelphij 4, &sync_time); 531226026Sdelphij if ( error ) 532226026Sdelphij TWS_TRACE_DEBUG(sc, "set param failed", sync_time, error); 533226026Sdelphij} 534226026Sdelphij 535226026SdelphijTUNABLE_INT("hw.tws.use_32bit_sgls", &tws_use_32bit_sgls); 536