1144966Svkashyap/* 2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap 4144966Svkashyap * All rights reserved. 5144966Svkashyap * 6144966Svkashyap * Redistribution and use in source and binary forms, with or without 7144966Svkashyap * modification, are permitted provided that the following conditions 8144966Svkashyap * are met: 9144966Svkashyap * 1. Redistributions of source code must retain the above copyright 10144966Svkashyap * notice, this list of conditions and the following disclaimer. 11144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright 12144966Svkashyap * notice, this list of conditions and the following disclaimer in the 13144966Svkashyap * documentation and/or other materials provided with the distribution. 14144966Svkashyap * 15144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18144966Svkashyap * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25144966Svkashyap * SUCH DAMAGE. 26144966Svkashyap * 27144966Svkashyap * $FreeBSD: releng/10.3/sys/dev/twa/tw_cl_init.c 212008 2010-08-30 19:15:04Z delphij $ 28144966Svkashyap */ 29144966Svkashyap 30144966Svkashyap/* 31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers. 32144966Svkashyap * 33144966Svkashyap * Author: Vinod Kashyap 34169400Sscottl * Modifications by: Adam Radford 35172496Sscottl * Modifications by: Manjunath Ranganathaiah 36144966Svkashyap */ 37144966Svkashyap 38144966Svkashyap 39144966Svkashyap/* 40144966Svkashyap * Common Layer initialization functions. 41144966Svkashyap */ 42144966Svkashyap 43144966Svkashyap 44144966Svkashyap#include "tw_osl_share.h" 45144966Svkashyap#include "tw_cl_share.h" 46144966Svkashyap#include "tw_cl_fwif.h" 47144966Svkashyap#include "tw_cl_ioctl.h" 48144966Svkashyap#include "tw_cl.h" 49144966Svkashyap#include "tw_cl_externs.h" 50144966Svkashyap#include "tw_osl_ioctl.h" 51144966Svkashyap 52144966Svkashyap 53144966Svkashyap/* 54144966Svkashyap * Function name: tw_cl_ctlr_supported 55144966Svkashyap * Description: Determines if a controller is supported. 56144966Svkashyap * 57144966Svkashyap * Input: vendor_id -- vendor id of the controller 58144966Svkashyap * device_id -- device id of the controller 59144966Svkashyap * Output: None 60144966Svkashyap * Return value: TW_CL_TRUE-- controller supported 61144966Svkashyap * TW_CL_FALSE-- controller not supported 62144966Svkashyap */ 63144966SvkashyapTW_INT32 64144966Svkashyaptw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id) 65144966Svkashyap{ 66152213Svkashyap if ((vendor_id == TW_CL_VENDOR_ID) && 67152213Svkashyap ((device_id == TW_CL_DEVICE_ID_9K) || 68169400Sscottl (device_id == TW_CL_DEVICE_ID_9K_X) || 69172496Sscottl (device_id == TW_CL_DEVICE_ID_9K_E) || 70172496Sscottl (device_id == TW_CL_DEVICE_ID_9K_SA))) 71144966Svkashyap return(TW_CL_TRUE); 72144966Svkashyap return(TW_CL_FALSE); 73144966Svkashyap} 74144966Svkashyap 75144966Svkashyap 76144966Svkashyap 77144966Svkashyap/* 78152213Svkashyap * Function name: tw_cl_get_pci_bar_info 79152213Svkashyap * Description: Returns PCI BAR info. 80152213Svkashyap * 81152213Svkashyap * Input: device_id -- device id of the controller 82152213Svkashyap * bar_type -- type of PCI BAR in question 83152213Svkashyap * Output: bar_num -- PCI BAR number corresponding to bar_type 84152213Svkashyap * bar0_offset -- byte offset from BAR 0 (0x10 in 85152213Svkashyap * PCI config space) 86152213Svkashyap * bar_size -- size, in bytes, of the BAR in question 87152213Svkashyap * Return value: 0 -- success 88152213Svkashyap * non-zero -- failure 89152213Svkashyap */ 90152213SvkashyapTW_INT32 91152213Svkashyaptw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type, 92152213Svkashyap TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size) 93152213Svkashyap{ 94152213Svkashyap TW_INT32 error = TW_OSL_ESUCCESS; 95152213Svkashyap 96152213Svkashyap switch(device_id) { 97152213Svkashyap case TW_CL_DEVICE_ID_9K: 98152213Svkashyap switch(bar_type) { 99152213Svkashyap case TW_CL_BAR_TYPE_IO: 100152213Svkashyap *bar_num = 0; 101152213Svkashyap *bar0_offset = 0; 102152213Svkashyap *bar_size = 4; 103152213Svkashyap break; 104152213Svkashyap 105152213Svkashyap case TW_CL_BAR_TYPE_MEM: 106152213Svkashyap *bar_num = 1; 107152213Svkashyap *bar0_offset = 0x4; 108152213Svkashyap *bar_size = 8; 109152213Svkashyap break; 110152213Svkashyap 111152213Svkashyap case TW_CL_BAR_TYPE_SBUF: 112152213Svkashyap *bar_num = 2; 113152213Svkashyap *bar0_offset = 0xC; 114152213Svkashyap *bar_size = 8; 115152213Svkashyap break; 116152213Svkashyap } 117152213Svkashyap break; 118152213Svkashyap 119152213Svkashyap case TW_CL_DEVICE_ID_9K_X: 120169400Sscottl case TW_CL_DEVICE_ID_9K_E: 121172496Sscottl case TW_CL_DEVICE_ID_9K_SA: 122152213Svkashyap switch(bar_type) { 123152213Svkashyap case TW_CL_BAR_TYPE_IO: 124152213Svkashyap *bar_num = 2; 125152213Svkashyap *bar0_offset = 0x10; 126152213Svkashyap *bar_size = 4; 127152213Svkashyap break; 128152213Svkashyap 129152213Svkashyap case TW_CL_BAR_TYPE_MEM: 130152213Svkashyap *bar_num = 1; 131152213Svkashyap *bar0_offset = 0x8; 132152213Svkashyap *bar_size = 8; 133152213Svkashyap break; 134152213Svkashyap 135152213Svkashyap case TW_CL_BAR_TYPE_SBUF: 136152213Svkashyap *bar_num = 0; 137152213Svkashyap *bar0_offset = 0; 138152213Svkashyap *bar_size = 8; 139152213Svkashyap break; 140152213Svkashyap } 141152213Svkashyap break; 142152213Svkashyap 143152213Svkashyap default: 144152213Svkashyap error = TW_OSL_ENOTTY; 145152213Svkashyap break; 146152213Svkashyap } 147152213Svkashyap 148152213Svkashyap return(error); 149152213Svkashyap} 150152213Svkashyap 151152213Svkashyap 152152213Svkashyap 153152213Svkashyap/* 154144966Svkashyap * Function name: tw_cl_get_mem_requirements 155144966Svkashyap * Description: Provides info about Common Layer requirements for a 156144966Svkashyap * controller, given the controller type (in 'flags'). 157144966Svkashyap * Input: ctlr_handle -- controller handle 158144966Svkashyap * flags -- more info passed by the OS Layer 159152213Svkashyap * device_id -- device id of the controller 160144966Svkashyap * max_simult_reqs -- maximum # of simultaneous 161144966Svkashyap * requests that the OS Layer expects 162144966Svkashyap * the Common Layer to support 163144966Svkashyap * max_aens -- maximun # of AEN's needed to be supported 164144966Svkashyap * Output: alignment -- alignment needed for all DMA'able 165144966Svkashyap * buffers 166144966Svkashyap * sg_size_factor -- every SG element should have a size 167144966Svkashyap * that's a multiple of this number 168144966Svkashyap * non_dma_mem_size -- # of bytes of memory needed for 169144966Svkashyap * non-DMA purposes 170144966Svkashyap * dma_mem_size -- # of bytes of DMA'able memory needed 171144966Svkashyap * per_req_dma_mem_size -- # of bytes of DMA'able memory 172144966Svkashyap * needed per request, if applicable 173144966Svkashyap * per_req_non_dma_mem_size -- # of bytes of memory needed 174144966Svkashyap * per request for non-DMA purposes, 175144966Svkashyap * if applicable 176144966Svkashyap * Output: None 177144966Svkashyap * Return value: 0 -- success 178144966Svkashyap * non-zero-- failure 179144966Svkashyap */ 180144966SvkashyapTW_INT32 181144966Svkashyaptw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle, 182152213Svkashyap TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs, 183152213Svkashyap TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor, 184144966Svkashyap TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size 185144966Svkashyap ) 186144966Svkashyap{ 187152213Svkashyap if (device_id == 0) 188152213Svkashyap device_id = TW_CL_DEVICE_ID_9K; 189152213Svkashyap 190144966Svkashyap if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) { 191144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 192144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 193144966Svkashyap 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING, 194144966Svkashyap "Too many simultaneous requests to support!", 195144966Svkashyap "requested = %d, supported = %d, error = %d\n", 196144966Svkashyap max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS, 197144966Svkashyap TW_OSL_EBIG); 198144966Svkashyap return(TW_OSL_EBIG); 199144966Svkashyap } 200144966Svkashyap 201152213Svkashyap *alignment = TWA_ALIGNMENT(device_id); 202152213Svkashyap *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id); 203144966Svkashyap 204144966Svkashyap /* 205144966Svkashyap * Total non-DMA memory needed is the sum total of memory needed for 206144966Svkashyap * the controller context, request packets (including the 1 needed for 207144966Svkashyap * CL internal requests), and event packets. 208144966Svkashyap */ 209144966Svkashyap 210144966Svkashyap *non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) + 211208969Sdelphij (sizeof(struct tw_cli_req_context) * max_simult_reqs) + 212144966Svkashyap (sizeof(struct tw_cl_event_packet) * max_aens); 213144966Svkashyap 214144966Svkashyap 215144966Svkashyap /* 216144966Svkashyap * Total DMA'able memory needed is the sum total of memory needed for 217144966Svkashyap * all command packets (including the 1 needed for CL internal 218144966Svkashyap * requests), and memory needed to hold the payload for internal 219144966Svkashyap * requests. 220144966Svkashyap */ 221144966Svkashyap 222144966Svkashyap *dma_mem_size = (sizeof(struct tw_cl_command_packet) * 223208969Sdelphij (max_simult_reqs)) + (TW_CLI_SECTOR_SIZE); 224144966Svkashyap 225144966Svkashyap return(0); 226144966Svkashyap} 227144966Svkashyap 228144966Svkashyap 229144966Svkashyap 230144966Svkashyap/* 231144966Svkashyap * Function name: tw_cl_init_ctlr 232144966Svkashyap * Description: Initializes driver data structures for the controller. 233144966Svkashyap * 234144966Svkashyap * Input: ctlr_handle -- controller handle 235144966Svkashyap * flags -- more info passed by the OS Layer 236152213Svkashyap * device_id -- device id of the controller 237144966Svkashyap * max_simult_reqs -- maximum # of simultaneous requests 238144966Svkashyap * that the OS Layer expects the Common 239144966Svkashyap * Layer to support 240144966Svkashyap * max_aens -- maximun # of AEN's needed to be supported 241144966Svkashyap * non_dma_mem -- ptr to allocated non-DMA memory 242144966Svkashyap * dma_mem -- ptr to allocated DMA'able memory 243144966Svkashyap * dma_mem_phys -- physical address of dma_mem 244144966Svkashyap * Output: None 245144966Svkashyap * Return value: 0 -- success 246144966Svkashyap * non-zero-- failure 247144966Svkashyap */ 248144966SvkashyapTW_INT32 249144966Svkashyaptw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags, 250152213Svkashyap TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens, 251152213Svkashyap TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys 252144966Svkashyap ) 253144966Svkashyap{ 254144966Svkashyap struct tw_cli_ctlr_context *ctlr; 255144966Svkashyap struct tw_cli_req_context *req; 256144966Svkashyap TW_UINT8 *free_non_dma_mem; 257144966Svkashyap TW_INT32 error = TW_OSL_ESUCCESS; 258144966Svkashyap TW_INT32 i; 259144966Svkashyap 260144966Svkashyap tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered"); 261144966Svkashyap 262144966Svkashyap if (flags & TW_CL_START_CTLR_ONLY) { 263144966Svkashyap ctlr = (struct tw_cli_ctlr_context *) 264144966Svkashyap (ctlr_handle->cl_ctlr_ctxt); 265144966Svkashyap goto start_ctlr; 266144966Svkashyap } 267144966Svkashyap 268144966Svkashyap if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) { 269144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 270144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 271144966Svkashyap 0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING, 272144966Svkashyap "Too many simultaneous requests to support!", 273144966Svkashyap "requested = %d, supported = %d, error = %d\n", 274144966Svkashyap max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS, 275144966Svkashyap TW_OSL_EBIG); 276144966Svkashyap return(TW_OSL_EBIG); 277144966Svkashyap } 278144966Svkashyap 279144966Svkashyap if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL) 280144966Svkashyap ) { 281144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 282144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 283144966Svkashyap 0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING, 284144966Svkashyap "Insufficient memory for Common Layer's internal usage", 285144966Svkashyap "error = %d\n", TW_OSL_ENOMEM); 286144966Svkashyap return(TW_OSL_ENOMEM); 287144966Svkashyap } 288144966Svkashyap 289144966Svkashyap tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) + 290208969Sdelphij (sizeof(struct tw_cli_req_context) * max_simult_reqs) + 291144966Svkashyap (sizeof(struct tw_cl_event_packet) * max_aens)); 292144966Svkashyap 293144966Svkashyap tw_osl_memzero(dma_mem, 294144966Svkashyap (sizeof(struct tw_cl_command_packet) * 295208969Sdelphij max_simult_reqs) + 296144966Svkashyap TW_CLI_SECTOR_SIZE); 297144966Svkashyap 298144966Svkashyap free_non_dma_mem = (TW_UINT8 *)non_dma_mem; 299144966Svkashyap 300144966Svkashyap ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem; 301144966Svkashyap free_non_dma_mem += sizeof(struct tw_cli_ctlr_context); 302144966Svkashyap 303144966Svkashyap ctlr_handle->cl_ctlr_ctxt = ctlr; 304144966Svkashyap ctlr->ctlr_handle = ctlr_handle; 305144966Svkashyap 306152213Svkashyap ctlr->device_id = (TW_UINT32)device_id; 307152213Svkashyap ctlr->arch_id = TWA_ARCH_ID(device_id); 308152213Svkashyap ctlr->flags = flags; 309152213Svkashyap ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id); 310208969Sdelphij ctlr->max_simult_reqs = max_simult_reqs; 311144966Svkashyap ctlr->max_aens_supported = max_aens; 312144966Svkashyap 313144966Svkashyap /* Initialize queues of CL internal request context packets. */ 314144966Svkashyap tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q); 315144966Svkashyap tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q); 316144966Svkashyap tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q); 317144966Svkashyap tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q); 318212008Sdelphij tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q); 319144966Svkashyap 320144966Svkashyap /* Initialize all locks used by CL. */ 321144966Svkashyap ctlr->gen_lock = &(ctlr->gen_lock_handle); 322144966Svkashyap tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock); 323144966Svkashyap ctlr->io_lock = &(ctlr->io_lock_handle); 324144966Svkashyap tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock); 325144966Svkashyap 326144966Svkashyap /* Initialize CL internal request context packets. */ 327144966Svkashyap ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem; 328144966Svkashyap free_non_dma_mem += (sizeof(struct tw_cli_req_context) * 329208969Sdelphij max_simult_reqs); 330144966Svkashyap 331144966Svkashyap ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem; 332144966Svkashyap ctlr->cmd_pkt_phys = dma_mem_phys; 333144966Svkashyap 334144966Svkashyap ctlr->internal_req_data = (TW_UINT8 *) 335144966Svkashyap (ctlr->cmd_pkt_buf + 336208969Sdelphij max_simult_reqs); 337144966Svkashyap ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys + 338144966Svkashyap (sizeof(struct tw_cl_command_packet) * 339208969Sdelphij max_simult_reqs); 340144966Svkashyap 341208969Sdelphij for (i = 0; i < max_simult_reqs; i++) { 342144966Svkashyap req = &(ctlr->req_ctxt_buf[i]); 343144966Svkashyap 344144966Svkashyap req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]); 345144966Svkashyap req->cmd_pkt_phys = ctlr->cmd_pkt_phys + 346144966Svkashyap (i * sizeof(struct tw_cl_command_packet)); 347144966Svkashyap 348144966Svkashyap req->request_id = i; 349144966Svkashyap req->ctlr = ctlr; 350144966Svkashyap 351144966Svkashyap /* Insert request into the free queue. */ 352144966Svkashyap tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 353144966Svkashyap } 354144966Svkashyap 355144966Svkashyap /* Initialize the AEN queue. */ 356144966Svkashyap ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem; 357144966Svkashyap 358144966Svkashyap 359144966Svkashyapstart_ctlr: 360144966Svkashyap /* 361144966Svkashyap * Disable interrupts. Interrupts will be enabled in tw_cli_start_ctlr 362144966Svkashyap * (only) if initialization succeeded. 363144966Svkashyap */ 364144966Svkashyap tw_cli_disable_interrupts(ctlr); 365144966Svkashyap 366144966Svkashyap /* Initialize the controller. */ 367144966Svkashyap if ((error = tw_cli_start_ctlr(ctlr))) { 368144966Svkashyap /* Soft reset the controller, and try one more time. */ 369144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 370144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 371144966Svkashyap 0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING, 372144966Svkashyap "Controller initialization failed. Retrying...", 373144966Svkashyap "error = %d\n", error); 374144966Svkashyap if ((error = tw_cli_soft_reset(ctlr))) { 375144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 376144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 377144966Svkashyap 0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING, 378144966Svkashyap "Controller soft reset failed", 379144966Svkashyap "error = %d\n", error); 380144966Svkashyap return(error); 381144966Svkashyap } else if ((error = tw_cli_start_ctlr(ctlr))) { 382144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 383144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 384144966Svkashyap 0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING, 385144966Svkashyap "Controller initialization retry failed", 386144966Svkashyap "error = %d\n", error); 387144966Svkashyap return(error); 388144966Svkashyap } 389144966Svkashyap } 390144966Svkashyap /* Notify some info about the controller to the OSL. */ 391144966Svkashyap tw_cli_notify_ctlr_info(ctlr); 392144966Svkashyap 393208969Sdelphij /* Mark the controller active. */ 394208969Sdelphij ctlr->active = TW_CL_TRUE; 395144966Svkashyap return(error); 396144966Svkashyap} 397144966Svkashyap 398144966Svkashyap/* 399144966Svkashyap * Function name: tw_cli_start_ctlr 400144966Svkashyap * Description: Establishes a logical connection with the controller. 401169400Sscottl * Determines whether or not the driver is compatible 402169400Sscottl * with the firmware on the controller, before proceeding 403169400Sscottl * to work with it. 404144966Svkashyap * 405144966Svkashyap * Input: ctlr -- ptr to per ctlr structure 406144966Svkashyap * Output: None 407144966Svkashyap * Return value: 0 -- success 408144966Svkashyap * non-zero-- failure 409144966Svkashyap */ 410144966SvkashyapTW_INT32 411144966Svkashyaptw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr) 412144966Svkashyap{ 413144966Svkashyap TW_UINT16 fw_on_ctlr_srl = 0; 414144966Svkashyap TW_UINT16 fw_on_ctlr_arch_id = 0; 415144966Svkashyap TW_UINT16 fw_on_ctlr_branch = 0; 416144966Svkashyap TW_UINT16 fw_on_ctlr_build = 0; 417144966Svkashyap TW_UINT32 init_connect_result = 0; 418144966Svkashyap TW_INT32 error = TW_OSL_ESUCCESS; 419144966Svkashyap 420144966Svkashyap tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 421144966Svkashyap 422144966Svkashyap /* Wait for the controller to become ready. */ 423144966Svkashyap if ((error = tw_cli_poll_status(ctlr, 424144966Svkashyap TWA_STATUS_MICROCONTROLLER_READY, 425144966Svkashyap TW_CLI_REQUEST_TIMEOUT_PERIOD))) { 426144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 427144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 428144966Svkashyap 0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING, 429144966Svkashyap "Microcontroller not ready", 430144966Svkashyap "error = %d", error); 431144966Svkashyap return(error); 432144966Svkashyap } 433144966Svkashyap /* Drain the response queue. */ 434144966Svkashyap if ((error = tw_cli_drain_response_queue(ctlr))) { 435144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 436144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 437144966Svkashyap 0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING, 438144966Svkashyap "Can't drain response queue", 439144966Svkashyap "error = %d", error); 440144966Svkashyap return(error); 441144966Svkashyap } 442144966Svkashyap /* Establish a logical connection with the controller. */ 443144966Svkashyap if ((error = tw_cli_init_connection(ctlr, 444144966Svkashyap (TW_UINT16)(ctlr->max_simult_reqs), 445144966Svkashyap TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL, 446152213Svkashyap (TW_UINT16)(ctlr->arch_id), 447152213Svkashyap TWA_CURRENT_FW_BRANCH(ctlr->arch_id), 448152213Svkashyap TWA_CURRENT_FW_BUILD(ctlr->arch_id), 449152213Svkashyap &fw_on_ctlr_srl, &fw_on_ctlr_arch_id, 450152213Svkashyap &fw_on_ctlr_branch, &fw_on_ctlr_build, 451152213Svkashyap &init_connect_result))) { 452144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 453144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 454144966Svkashyap 0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING, 455144966Svkashyap "Can't initialize connection in current mode", 456144966Svkashyap "error = %d", error); 457144966Svkashyap return(error); 458144966Svkashyap } 459144966Svkashyap { 460169400Sscottl /* See if we can at least work with the firmware on the 461169400Sscottl * controller in the current mode. 462144966Svkashyap */ 463144966Svkashyap if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) { 464144966Svkashyap /* Yes, we can. Make note of the operating mode. */ 465144966Svkashyap if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) { 466144966Svkashyap ctlr->working_srl = TWA_CURRENT_FW_SRL; 467152213Svkashyap ctlr->working_branch = 468152213Svkashyap TWA_CURRENT_FW_BRANCH(ctlr->arch_id); 469152213Svkashyap ctlr->working_build = 470152213Svkashyap TWA_CURRENT_FW_BUILD(ctlr->arch_id); 471144966Svkashyap } else { 472144966Svkashyap ctlr->working_srl = fw_on_ctlr_srl; 473144966Svkashyap ctlr->working_branch = fw_on_ctlr_branch; 474144966Svkashyap ctlr->working_build = fw_on_ctlr_build; 475144966Svkashyap } 476144966Svkashyap } else { 477144966Svkashyap /* 478144966Svkashyap * No, we can't. See if we can at least work with 479169400Sscottl * it in the base mode. 480144966Svkashyap */ 481144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 482144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 483144966Svkashyap 0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING, 484144966Svkashyap "Driver/Firmware mismatch. " 485144966Svkashyap "Negotiating for base level...", 486144966Svkashyap " "); 487144966Svkashyap if ((error = tw_cli_init_connection(ctlr, 488144966Svkashyap (TW_UINT16)(ctlr->max_simult_reqs), 489144966Svkashyap TWA_EXTENDED_INIT_CONNECT, 490152213Svkashyap TWA_BASE_FW_SRL, 491152213Svkashyap (TW_UINT16)(ctlr->arch_id), 492144966Svkashyap TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD, 493144966Svkashyap &fw_on_ctlr_srl, &fw_on_ctlr_arch_id, 494144966Svkashyap &fw_on_ctlr_branch, &fw_on_ctlr_build, 495144966Svkashyap &init_connect_result))) { 496144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, 497144966Svkashyap TW_CL_FALSE, 498144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 499144966Svkashyap 0x1011, 0x1, 500144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 501144966Svkashyap "Can't initialize connection in " 502144966Svkashyap "base mode", 503144966Svkashyap " "); 504144966Svkashyap return(error); 505144966Svkashyap } 506144966Svkashyap if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) { 507144966Svkashyap /* 508144966Svkashyap * The firmware on the controller is not even 509144966Svkashyap * compatible with our base mode. We cannot 510144966Svkashyap * work with it. Bail... 511144966Svkashyap */ 512144966Svkashyap return(1); 513144966Svkashyap } 514144966Svkashyap /* 515144966Svkashyap * We can work with this firmware, but only in 516144966Svkashyap * base mode. 517144966Svkashyap */ 518144966Svkashyap ctlr->working_srl = TWA_BASE_FW_SRL; 519144966Svkashyap ctlr->working_branch = TWA_BASE_FW_BRANCH; 520144966Svkashyap ctlr->working_build = TWA_BASE_FW_BUILD; 521144966Svkashyap ctlr->operating_mode = TWA_BASE_MODE; 522144966Svkashyap } 523152213Svkashyap ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl; 524152213Svkashyap ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch; 525152213Svkashyap ctlr->fw_on_ctlr_build = fw_on_ctlr_build; 526144966Svkashyap } 527144966Svkashyap 528144966Svkashyap /* Drain the AEN queue */ 529144966Svkashyap if ((error = tw_cli_drain_aen_queue(ctlr))) 530144966Svkashyap /* 531144966Svkashyap * We will just print that we couldn't drain the AEN queue. 532144966Svkashyap * There's no need to bail out. 533144966Svkashyap */ 534144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 535144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 536144966Svkashyap 0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING, 537144966Svkashyap "Can't drain AEN queue", 538144966Svkashyap "error = %d", error); 539144966Svkashyap 540144966Svkashyap /* Enable interrupts. */ 541144966Svkashyap tw_cli_enable_interrupts(ctlr); 542144966Svkashyap 543144966Svkashyap return(TW_OSL_ESUCCESS); 544144966Svkashyap} 545144966Svkashyap 546144966Svkashyap 547144966Svkashyap/* 548144966Svkashyap * Function name: tw_cl_shutdown_ctlr 549144966Svkashyap * Description: Closes logical connection with the controller. 550144966Svkashyap * 551144966Svkashyap * Input: ctlr -- ptr to per ctlr structure 552144966Svkashyap * flags -- more info passed by the OS Layer 553144966Svkashyap * Output: None 554144966Svkashyap * Return value: 0 -- success 555144966Svkashyap * non-zero-- failure 556144966Svkashyap */ 557144966SvkashyapTW_INT32 558144966Svkashyaptw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags) 559144966Svkashyap{ 560144966Svkashyap struct tw_cli_ctlr_context *ctlr = 561144966Svkashyap (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt); 562144966Svkashyap TW_INT32 error; 563144966Svkashyap 564144966Svkashyap tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered"); 565144966Svkashyap /* 566144966Svkashyap * Mark the controller as inactive, disable any further interrupts, 567144966Svkashyap * and notify the controller that we are going down. 568144966Svkashyap */ 569208969Sdelphij ctlr->active = TW_CL_FALSE; 570144966Svkashyap 571144966Svkashyap tw_cli_disable_interrupts(ctlr); 572144966Svkashyap 573144966Svkashyap /* Let the controller know that we are going down. */ 574144966Svkashyap if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS, 575144966Svkashyap 0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL, 576144966Svkashyap TW_CL_NULL, TW_CL_NULL))) 577144966Svkashyap tw_cl_create_event(ctlr_handle, TW_CL_FALSE, 578144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 579144966Svkashyap 0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING, 580144966Svkashyap "Can't close connection with controller", 581144966Svkashyap "error = %d", error); 582144966Svkashyap 583144966Svkashyap if (flags & TW_CL_STOP_CTLR_ONLY) 584144966Svkashyap goto ret; 585144966Svkashyap 586144966Svkashyap /* Destroy all locks used by CL. */ 587144966Svkashyap tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock); 588144966Svkashyap tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock); 589144966Svkashyap 590144966Svkashyapret: 591144966Svkashyap return(error); 592144966Svkashyap} 593144966Svkashyap 594144966Svkashyap 595144966Svkashyap 596144966Svkashyap/* 597144966Svkashyap * Function name: tw_cli_init_connection 598144966Svkashyap * Description: Sends init_connection cmd to firmware 599144966Svkashyap * 600144966Svkashyap * Input: ctlr -- ptr to per ctlr structure 601144966Svkashyap * message_credits -- max # of requests that we might send 602144966Svkashyap * down simultaneously. This will be 603144966Svkashyap * typically set to 256 at init-time or 604144966Svkashyap * after a reset, and to 1 at shutdown-time 605144966Svkashyap * set_features -- indicates if we intend to use 64-bit 606144966Svkashyap * sg, also indicates if we want to do a 607144966Svkashyap * basic or an extended init_connection; 608144966Svkashyap * 609144966Svkashyap * Note: The following input/output parameters are valid, only in case of an 610144966Svkashyap * extended init_connection: 611144966Svkashyap * 612144966Svkashyap * current_fw_srl -- srl of fw we are bundled 613144966Svkashyap * with, if any; 0 otherwise 614144966Svkashyap * current_fw_arch_id -- arch_id of fw we are bundled 615144966Svkashyap * with, if any; 0 otherwise 616144966Svkashyap * current_fw_branch -- branch # of fw we are bundled 617144966Svkashyap * with, if any; 0 otherwise 618144966Svkashyap * current_fw_build -- build # of fw we are bundled 619144966Svkashyap * with, if any; 0 otherwise 620144966Svkashyap * Output: fw_on_ctlr_srl -- srl of fw on ctlr 621144966Svkashyap * fw_on_ctlr_arch_id -- arch_id of fw on ctlr 622144966Svkashyap * fw_on_ctlr_branch -- branch # of fw on ctlr 623144966Svkashyap * fw_on_ctlr_build -- build # of fw on ctlr 624144966Svkashyap * init_connect_result -- result bitmap of fw response 625144966Svkashyap * Return value: 0 -- success 626144966Svkashyap * non-zero-- failure 627144966Svkashyap */ 628144966SvkashyapTW_INT32 629144966Svkashyaptw_cli_init_connection(struct tw_cli_ctlr_context *ctlr, 630144966Svkashyap TW_UINT16 message_credits, TW_UINT32 set_features, 631144966Svkashyap TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id, 632144966Svkashyap TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build, 633144966Svkashyap TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id, 634144966Svkashyap TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build, 635144966Svkashyap TW_UINT32 *init_connect_result) 636144966Svkashyap{ 637144966Svkashyap struct tw_cli_req_context *req; 638144966Svkashyap struct tw_cl_command_init_connect *init_connect; 639144966Svkashyap TW_INT32 error = TW_OSL_EBUSY; 640144966Svkashyap 641144966Svkashyap tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); 642144966Svkashyap 643144966Svkashyap /* Get a request packet. */ 644144966Svkashyap if ((req = tw_cli_get_request(ctlr 645144966Svkashyap )) == TW_CL_NULL) 646144966Svkashyap goto out; 647144966Svkashyap 648144966Svkashyap req->flags |= TW_CLI_REQ_FLAGS_INTERNAL; 649144966Svkashyap 650144966Svkashyap /* Build the cmd pkt. */ 651144966Svkashyap init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect); 652144966Svkashyap 653144966Svkashyap req->cmd_pkt->cmd_hdr.header_desc.size_header = 128; 654144966Svkashyap 655144966Svkashyap init_connect->res1__opcode = 656144966Svkashyap BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION); 657144966Svkashyap init_connect->request_id = 658144966Svkashyap (TW_UINT8)(TW_CL_SWAP16(req->request_id)); 659144966Svkashyap init_connect->message_credits = TW_CL_SWAP16(message_credits); 660144966Svkashyap init_connect->features = TW_CL_SWAP32(set_features); 661144966Svkashyap if (ctlr->flags & TW_CL_64BIT_ADDRESSES) 662190329Sjhb init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES); 663144966Svkashyap if (set_features & TWA_EXTENDED_INIT_CONNECT) { 664144966Svkashyap /* 665144966Svkashyap * Fill in the extra fields needed for an extended 666144966Svkashyap * init_connect. 667144966Svkashyap */ 668144966Svkashyap init_connect->size = 6; 669144966Svkashyap init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl); 670144966Svkashyap init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id); 671144966Svkashyap init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch); 672144966Svkashyap init_connect->fw_build = TW_CL_SWAP16(current_fw_build); 673144966Svkashyap } else 674144966Svkashyap init_connect->size = 3; 675144966Svkashyap 676144966Svkashyap /* Submit the command, and wait for it to complete. */ 677144966Svkashyap error = tw_cli_submit_and_poll_request(req, 678144966Svkashyap TW_CLI_REQUEST_TIMEOUT_PERIOD); 679144966Svkashyap if (error) 680144966Svkashyap goto out; 681144966Svkashyap if ((error = init_connect->status)) { 682212008Sdelphij#if 0 683144966Svkashyap tw_cli_create_ctlr_event(ctlr, 684144966Svkashyap TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR, 685144966Svkashyap &(req->cmd_pkt->cmd_hdr)); 686212008Sdelphij#endif // 0 687144966Svkashyap goto out; 688144966Svkashyap } 689144966Svkashyap if (set_features & TWA_EXTENDED_INIT_CONNECT) { 690144966Svkashyap *fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl); 691144966Svkashyap *fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id); 692144966Svkashyap *fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch); 693144966Svkashyap *fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build); 694144966Svkashyap *init_connect_result = TW_CL_SWAP32(init_connect->result); 695144966Svkashyap } 696144966Svkashyap tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 697144966Svkashyap return(error); 698144966Svkashyap 699144966Svkashyapout: 700144966Svkashyap tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, 701144966Svkashyap TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 702144966Svkashyap 0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING, 703144966Svkashyap "init_connection failed", 704144966Svkashyap "error = %d", error); 705144966Svkashyap if (req) 706144966Svkashyap tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); 707144966Svkashyap return(error); 708144966Svkashyap} 709144966Svkashyap 710144966Svkashyap 711