1101704Smjacob/* $FreeBSD: releng/10.3/sys/dev/mpt/mpt.h 292794 2015-12-27 20:52:32Z marius $ */ 2139749Simp/*- 3101704Smjacob * Generic defines for LSI '909 FC adapters. 4101704Smjacob * FreeBSD Version. 5101704Smjacob * 6101704Smjacob * Copyright (c) 2000, 2001 by Greg Ansley 7101704Smjacob * 8101704Smjacob * Redistribution and use in source and binary forms, with or without 9101704Smjacob * modification, are permitted provided that the following conditions 10101704Smjacob * are met: 11101704Smjacob * 1. Redistributions of source code must retain the above copyright 12101704Smjacob * notice immediately at the beginning of the file, without modification, 13101704Smjacob * this list of conditions, and the following disclaimer. 14101704Smjacob * 2. The name of the author may not be used to endorse or promote products 15101704Smjacob * derived from this software without specific prior written permission. 16101704Smjacob * 17101704Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18101704Smjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19101704Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20101704Smjacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21101704Smjacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22101704Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23101704Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24101704Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25101704Smjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26101704Smjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27101704Smjacob * SUCH DAMAGE. 28156000Smjacob */ 29156000Smjacob/*- 30156000Smjacob * Copyright (c) 2002, 2006 by Matthew Jacob 31156000Smjacob * All rights reserved. 32156000Smjacob * 33156000Smjacob * Redistribution and use in source and binary forms, with or without 34156000Smjacob * modification, are permitted provided that the following conditions are 35156000Smjacob * met: 36156000Smjacob * 1. Redistributions of source code must retain the above copyright 37156000Smjacob * notice, this list of conditions and the following disclaimer. 38156000Smjacob * 2. Redistributions in binary form must reproduce at minimum a disclaimer 39156000Smjacob * substantially similar to the "NO WARRANTY" disclaimer below 40156000Smjacob * ("Disclaimer") and any redistribution must be conditioned upon including 41156000Smjacob * a substantially similar Disclaimer requirement for further binary 42156000Smjacob * redistribution. 43156000Smjacob * 3. Neither the names of the above listed copyright holders nor the names 44156000Smjacob * of any contributors may be used to endorse or promote products derived 45156000Smjacob * from this software without specific prior written permission. 46156000Smjacob * 47156000Smjacob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48156000Smjacob * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49156000Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50156000Smjacob * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51156000Smjacob * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52156000Smjacob * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53156000Smjacob * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54156000Smjacob * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55156000Smjacob * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56156000Smjacob * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 57156000Smjacob * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58147883Sscottl * 59156000Smjacob * Support from Chris Ellsworth in order to make SAS adapters work 60156000Smjacob * is gratefully acknowledged. 61159052Smjacob * 62159052Smjacob * 63159052Smjacob * Support from LSI-Logic has also gone a great deal toward making this a 64159052Smjacob * workable subsystem and is gratefully acknowledged. 65101704Smjacob */ 66101704Smjacob/* 67147883Sscottl * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 68147883Sscottl * Copyright (c) 2004, 2005 Justin T. Gibbs 69147883Sscottl * Copyright (c) 2005, WHEEL Sp. z o.o. 70147883Sscottl * All rights reserved. 71147883Sscottl * 72147883Sscottl * Redistribution and use in source and binary forms, with or without 73147883Sscottl * modification, are permitted provided that the following conditions are 74147883Sscottl * met: 75147883Sscottl * 1. Redistributions of source code must retain the above copyright 76147883Sscottl * notice, this list of conditions and the following disclaimer. 77147883Sscottl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 78147883Sscottl * substantially similar to the "NO WARRANTY" disclaimer below 79147883Sscottl * ("Disclaimer") and any redistribution must be conditioned upon including 80147883Sscottl * a substantially similar Disclaimer requirement for further binary 81147883Sscottl * redistribution. 82148679Sgibbs * 3. Neither the names of the above listed copyright holders nor the names 83148679Sgibbs * of any contributors may be used to endorse or promote products derived 84148679Sgibbs * from this software without specific prior written permission. 85147883Sscottl * 86147883Sscottl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 87147883Sscottl * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 88147883Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 89147883Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 90147883Sscottl * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 91147883Sscottl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 92147883Sscottl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 93147883Sscottl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 94147883Sscottl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 95147883Sscottl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 96147883Sscottl * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 97101704Smjacob */ 98101704Smjacob 99101704Smjacob#ifndef _MPT_H_ 100101704Smjacob#define _MPT_H_ 101147883Sscottl 102147883Sscottl/********************************* OS Includes ********************************/ 103147883Sscottl#include <sys/param.h> 104147883Sscottl#include <sys/systm.h> 105241874Smarius#include <sys/bus.h> 106241874Smarius#include <sys/condvar.h> 107147883Sscottl#include <sys/endian.h> 108147883Sscottl#include <sys/eventhandler.h> 109147883Sscottl#include <sys/kernel.h> 110147883Sscottl#include <sys/lock.h> 111147883Sscottl#include <sys/malloc.h> 112241874Smarius#include <sys/module.h> 113147883Sscottl#include <sys/mutex.h> 114147883Sscottl#include <sys/proc.h> 115241874Smarius#include <sys/queue.h> 116241874Smarius#include <sys/rman.h> 117241874Smarius#include <sys/types.h> 118147883Sscottl 119241874Smarius#include <machine/bus.h> 120147883Sscottl#include <machine/cpu.h> 121147883Sscottl#include <machine/resource.h> 122147883Sscottl 123207287Smarius#ifdef __sparc64__ 124207287Smarius#include <dev/ofw/openfirm.h> 125207287Smarius#include <machine/ofw_machdep.h> 126207287Smarius#endif 127207287Smarius 128155521Smjacob#include <dev/pci/pcireg.h> 129155521Smjacob#include <dev/pci/pcivar.h> 130155521Smjacob 131147883Sscottl#include "opt_ddb.h" 132147883Sscottl 133147883Sscottl/**************************** Register Definitions ****************************/ 134147883Sscottl#include <dev/mpt/mpt_reg.h> 135147883Sscottl 136147883Sscottl/******************************* MPI Definitions ******************************/ 137147883Sscottl#include <dev/mpt/mpilib/mpi_type.h> 138147883Sscottl#include <dev/mpt/mpilib/mpi.h> 139147883Sscottl#include <dev/mpt/mpilib/mpi_cnfg.h> 140147883Sscottl#include <dev/mpt/mpilib/mpi_ioc.h> 141147883Sscottl#include <dev/mpt/mpilib/mpi_raid.h> 142147883Sscottl 143147883Sscottl/* XXX For mpt_debug.c */ 144147883Sscottl#include <dev/mpt/mpilib/mpi_init.h> 145147883Sscottl 146164990Smjacob#define MPT_S64_2_SCALAR(y) ((((int64_t)y.High) << 32) | (y.Low)) 147164990Smjacob#define MPT_U64_2_SCALAR(y) ((((uint64_t)y.High) << 32) | (y.Low)) 148164990Smjacob 149147883Sscottl/****************************** Misc Definitions ******************************/ 150165814Smjacob/* #define MPT_TEST_MULTIPATH 1 */ 151101704Smjacob#define MPT_OK (0) 152101704Smjacob#define MPT_FAIL (0x10000) 153101704Smjacob 154147883Sscottl#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) 155101704Smjacob 156157117Smjacob#define MPT_ROLE_NONE 0 157157117Smjacob#define MPT_ROLE_INITIATOR 1 158157117Smjacob#define MPT_ROLE_TARGET 2 159157117Smjacob#define MPT_ROLE_BOTH 3 160157117Smjacob#define MPT_ROLE_DEFAULT MPT_ROLE_INITIATOR 161157117Smjacob 162207287Smarius#define MPT_INI_ID_NONE -1 163207287Smarius 164147883Sscottl/**************************** Forward Declarations ****************************/ 165147883Sscottlstruct mpt_softc; 166147883Sscottlstruct mpt_personality; 167147883Sscottltypedef struct req_entry request_t; 168101704Smjacob 169147883Sscottl/************************* Personality Module Support *************************/ 170147883Sscottltypedef int mpt_load_handler_t(struct mpt_personality *); 171147883Sscottltypedef int mpt_probe_handler_t(struct mpt_softc *); 172147883Sscottltypedef int mpt_attach_handler_t(struct mpt_softc *); 173157117Smjacobtypedef int mpt_enable_handler_t(struct mpt_softc *); 174162133Smjacobtypedef void mpt_ready_handler_t(struct mpt_softc *); 175147883Sscottltypedef int mpt_event_handler_t(struct mpt_softc *, request_t *, 176147883Sscottl MSG_EVENT_NOTIFY_REPLY *); 177147883Sscottltypedef void mpt_reset_handler_t(struct mpt_softc *, int /*type*/); 178147883Sscottl/* XXX Add return value and use for veto? */ 179147883Sscottltypedef void mpt_shutdown_handler_t(struct mpt_softc *); 180147883Sscottltypedef void mpt_detach_handler_t(struct mpt_softc *); 181147883Sscottltypedef int mpt_unload_handler_t(struct mpt_personality *); 182147883Sscottl 183147883Sscottlstruct mpt_personality 184147883Sscottl{ 185147883Sscottl const char *name; 186147883Sscottl uint32_t id; /* Assigned identifier. */ 187147883Sscottl u_int use_count; /* Instances using personality*/ 188147883Sscottl mpt_load_handler_t *load; /* configure personailty */ 189147883Sscottl#define MPT_PERS_FIRST_HANDLER(pers) (&(pers)->load) 190147883Sscottl mpt_probe_handler_t *probe; /* configure personailty */ 191147883Sscottl mpt_attach_handler_t *attach; /* initialize device instance */ 192157117Smjacob mpt_enable_handler_t *enable; /* enable device */ 193162133Smjacob mpt_ready_handler_t *ready; /* final open for business */ 194147883Sscottl mpt_event_handler_t *event; /* Handle MPI event. */ 195147883Sscottl mpt_reset_handler_t *reset; /* Re-init after reset. */ 196147883Sscottl mpt_shutdown_handler_t *shutdown; /* Shutdown instance. */ 197147883Sscottl mpt_detach_handler_t *detach; /* release device instance */ 198147883Sscottl mpt_unload_handler_t *unload; /* Shutdown personality */ 199147883Sscottl#define MPT_PERS_LAST_HANDLER(pers) (&(pers)->unload) 200101704Smjacob}; 201101704Smjacob 202147883Sscottlint mpt_modevent(module_t, int, void *); 203101704Smjacob 204147883Sscottl/* Maximum supported number of personalities. */ 205147883Sscottl#define MPT_MAX_PERSONALITIES (15) 206101704Smjacob 207147883Sscottl#define MPT_PERSONALITY_DEPEND(name, dep, vmin, vpref, vmax) \ 208147883Sscottl MODULE_DEPEND(name, dep, vmin, vpref, vmax) 209101704Smjacob 210147883Sscottl#define DECLARE_MPT_PERSONALITY(name, order) \ 211147883Sscottl static moduledata_t name##_mod = { \ 212147883Sscottl #name, mpt_modevent, &name##_personality \ 213147883Sscottl }; \ 214147883Sscottl DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, order); \ 215147883Sscottl MODULE_VERSION(name, 1); \ 216147883Sscottl MPT_PERSONALITY_DEPEND(name, mpt_core, 1, 1, 1) 217147883Sscottl 218147883Sscottl/******************************* Bus DMA Support ******************************/ 219147883Sscottl/* XXX Need to update bus_dmamap_sync to take a range argument. */ 220147883Sscottl#define bus_dmamap_sync_range(dma_tag, dmamap, offset, len, op) \ 221147883Sscottl bus_dmamap_sync(dma_tag, dmamap, op) 222147883Sscottl 223147883Sscottl#define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary, \ 224147883Sscottl lowaddr, highaddr, filter, filterarg, \ 225147883Sscottl maxsize, nsegments, maxsegsz, flags, \ 226147883Sscottl dma_tagp) \ 227147883Sscottl bus_dma_tag_create(parent_tag, alignment, boundary, \ 228147883Sscottl lowaddr, highaddr, filter, filterarg, \ 229147883Sscottl maxsize, nsegments, maxsegsz, flags, \ 230169293Smjacob busdma_lock_mutex, &(mpt)->mpt_lock, \ 231147883Sscottl dma_tagp) 232147883Sscottlstruct mpt_map_info { 233147883Sscottl struct mpt_softc *mpt; 234147883Sscottl int error; 235147883Sscottl uint32_t phys; 236147883Sscottl}; 237147883Sscottl 238147883Sscottlvoid mpt_map_rquest(void *, bus_dma_segment_t *, int, int); 239147883Sscottl 240147883Sscottl/********************************** Endianess *********************************/ 241164990Smjacob#define MPT_2_HOST64(ptr, tag) ptr->tag = le64toh(ptr->tag) 242164990Smjacob#define MPT_2_HOST32(ptr, tag) ptr->tag = le32toh(ptr->tag) 243164990Smjacob#define MPT_2_HOST16(ptr, tag) ptr->tag = le16toh(ptr->tag) 244147883Sscottl 245164990Smjacob#define HOST_2_MPT64(ptr, tag) ptr->tag = htole64(ptr->tag) 246164990Smjacob#define HOST_2_MPT32(ptr, tag) ptr->tag = htole32(ptr->tag) 247164990Smjacob#define HOST_2_MPT16(ptr, tag) ptr->tag = htole16(ptr->tag) 248147883Sscottl 249164998Smjacob#if _BYTE_ORDER == _BIG_ENDIAN 250164998Smjacobvoid mpt2host_sge_simple_union(SGE_SIMPLE_UNION *); 251164998Smjacobvoid mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *); 252164998Smjacobvoid mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *); 253164998Smjacobvoid mpt2host_config_page_ioc2(CONFIG_PAGE_IOC_2 *); 254186878Smariusvoid mpt2host_config_page_ioc3(CONFIG_PAGE_IOC_3 *); 255186878Smariusvoid mpt2host_config_page_scsi_port_0(CONFIG_PAGE_SCSI_PORT_0 *); 256186878Smariusvoid mpt2host_config_page_scsi_port_1(CONFIG_PAGE_SCSI_PORT_1 *); 257186878Smariusvoid host2mpt_config_page_scsi_port_1(CONFIG_PAGE_SCSI_PORT_1 *); 258186878Smariusvoid mpt2host_config_page_scsi_port_2(CONFIG_PAGE_SCSI_PORT_2 *); 259186878Smariusvoid mpt2host_config_page_scsi_device_0(CONFIG_PAGE_SCSI_DEVICE_0 *); 260186878Smariusvoid mpt2host_config_page_scsi_device_1(CONFIG_PAGE_SCSI_DEVICE_1 *); 261186878Smariusvoid host2mpt_config_page_scsi_device_1(CONFIG_PAGE_SCSI_DEVICE_1 *); 262186878Smariusvoid mpt2host_config_page_fc_port_0(CONFIG_PAGE_FC_PORT_0 *); 263186878Smariusvoid mpt2host_config_page_fc_port_1(CONFIG_PAGE_FC_PORT_1 *); 264186878Smariusvoid host2mpt_config_page_fc_port_1(CONFIG_PAGE_FC_PORT_1 *); 265164998Smjacobvoid mpt2host_config_page_raid_vol_0(CONFIG_PAGE_RAID_VOL_0 *); 266186878Smariusvoid mpt2host_config_page_raid_phys_disk_0(CONFIG_PAGE_RAID_PHYS_DISK_0 *); 267164998Smjacobvoid mpt2host_mpi_raid_vol_indicator(MPI_RAID_VOL_INDICATOR *); 268164998Smjacob#else 269164990Smjacob#define mpt2host_sge_simple_union(x) do { ; } while (0) 270164990Smjacob#define mpt2host_iocfacts_reply(x) do { ; } while (0) 271164990Smjacob#define mpt2host_portfacts_reply(x) do { ; } while (0) 272164990Smjacob#define mpt2host_config_page_ioc2(x) do { ; } while (0) 273186878Smarius#define mpt2host_config_page_ioc3(x) do { ; } while (0) 274186878Smarius#define mpt2host_config_page_scsi_port_0(x) do { ; } while (0) 275186878Smarius#define mpt2host_config_page_scsi_port_1(x) do { ; } while (0) 276186878Smarius#define host2mpt_config_page_scsi_port_1(x) do { ; } while (0) 277186878Smarius#define mpt2host_config_page_scsi_port_2(x) do { ; } while (0) 278186878Smarius#define mpt2host_config_page_scsi_device_0(x) do { ; } while (0) 279186878Smarius#define mpt2host_config_page_scsi_device_1(x) do { ; } while (0) 280186878Smarius#define host2mpt_config_page_scsi_device_1(x) do { ; } while (0) 281186878Smarius#define mpt2host_config_page_fc_port_0(x) do { ; } while (0) 282186878Smarius#define mpt2host_config_page_fc_port_1(x) do { ; } while (0) 283186878Smarius#define host2mpt_config_page_fc_port_1(x) do { ; } while (0) 284164990Smjacob#define mpt2host_config_page_raid_vol_0(x) do { ; } while (0) 285186878Smarius#define mpt2host_config_page_raid_phys_disk_0(x) \ 286186878Smarius do { ; } while (0) 287164990Smjacob#define mpt2host_mpi_raid_vol_indicator(x) do { ; } while (0) 288164990Smjacob#endif 289164990Smjacob 290147883Sscottl/**************************** MPI Transaction State ***************************/ 291147883Sscottltypedef enum { 292157354Smjacob REQ_STATE_NIL = 0x00, 293157354Smjacob REQ_STATE_FREE = 0x01, 294157354Smjacob REQ_STATE_ALLOCATED = 0x02, 295157354Smjacob REQ_STATE_QUEUED = 0x04, 296157354Smjacob REQ_STATE_DONE = 0x08, 297157354Smjacob REQ_STATE_TIMEDOUT = 0x10, 298157354Smjacob REQ_STATE_NEED_WAKEUP = 0x20, 299157354Smjacob REQ_STATE_LOCKED = 0x80, /* can't be freed */ 300147883Sscottl REQ_STATE_MASK = 0xFF 301147883Sscottl} mpt_req_state_t; 302147883Sscottl 303147883Sscottlstruct req_entry { 304147883Sscottl TAILQ_ENTRY(req_entry) links; /* Pointer to next in list */ 305147883Sscottl mpt_req_state_t state; /* Request State Information */ 306147883Sscottl uint16_t index; /* Index of this entry */ 307147883Sscottl uint16_t IOCStatus; /* Completion status */ 308220945Smarius uint16_t ResponseCode; /* TMF Response Code */ 309157662Smjacob uint16_t serno; /* serial number */ 310147883Sscottl union ccb *ccb; /* CAM request */ 311147883Sscottl void *req_vbuf; /* Virtual Address of Entry */ 312147883Sscottl void *sense_vbuf; /* Virtual Address of sense data */ 313147883Sscottl bus_addr_t req_pbuf; /* Physical Address of Entry */ 314147883Sscottl bus_addr_t sense_pbuf; /* Physical Address of sense data */ 315159312Smjacob bus_dmamap_t dmap; /* DMA map for data buffers */ 316155521Smjacob struct req_entry *chain; /* for SGE overallocations */ 317169293Smjacob struct callout callout; /* Timeout for the request */ 318147883Sscottl}; 319147883Sscottl 320170252Sscottltypedef struct mpt_config_params { 321170252Sscottl u_int Action; 322170252Sscottl u_int PageVersion; 323170252Sscottl u_int PageLength; 324170252Sscottl u_int PageNumber; 325170252Sscottl u_int PageType; 326170252Sscottl u_int PageAddress; 327170252Sscottl u_int ExtPageLength; 328170252Sscottl u_int ExtPageType; 329170252Sscottl} cfgparms_t; 330170252Sscottl 331157117Smjacob/**************************** MPI Target State Info ***************************/ 332157117Smjacobtypedef struct { 333157117Smjacob uint32_t reply_desc; /* current reply descriptor */ 334157117Smjacob uint32_t resid; /* current data residual */ 335157117Smjacob uint32_t bytes_xfered; /* current relative offset */ 336157117Smjacob union ccb *ccb; /* pointer to currently active ccb */ 337157117Smjacob request_t *req; /* pointer to currently active assist request */ 338160391Smjacob uint32_t 339160391Smjacob is_local : 1, 340160391Smjacob nxfers : 31; 341157354Smjacob uint32_t tag_id; 342157117Smjacob enum { 343157117Smjacob TGT_STATE_NIL, 344157354Smjacob TGT_STATE_LOADING, 345157117Smjacob TGT_STATE_LOADED, 346157117Smjacob TGT_STATE_IN_CAM, 347157117Smjacob TGT_STATE_SETTING_UP_FOR_DATA, 348157117Smjacob TGT_STATE_MOVING_DATA, 349157117Smjacob TGT_STATE_MOVING_DATA_AND_STATUS, 350157117Smjacob TGT_STATE_SENDING_STATUS 351157117Smjacob } state; 352157117Smjacob} mpt_tgt_state_t; 353157117Smjacob 354157117Smjacob/* 355157117Smjacob * When we get an incoming command it has its own tag which is called the 356157117Smjacob * IoIndex. This is the value we gave that particular command buffer when 357157117Smjacob * we originally assigned it. It's just a number, really. The FC card uses 358157117Smjacob * it as an RX_ID. We can use it to index into mpt->tgt_cmd_ptrs, which 359157117Smjacob * contains pointers the request_t structures related to that IoIndex. 360157117Smjacob * 361157117Smjacob * What *we* do is construct a tag out of the index for the target command 362157117Smjacob * which owns the incoming ATIO plus a rolling sequence number. 363157117Smjacob */ 364157117Smjacob#define MPT_MAKE_TAGID(mpt, req, ioindex) \ 365157354Smjacob ((ioindex << 18) | (((mpt->sequence++) & 0x3f) << 12) | (req->index & 0xfff)) 366157117Smjacob 367157117Smjacob#ifdef INVARIANTS 368157117Smjacob#define MPT_TAG_2_REQ(a, b) mpt_tag_2_req(a, (uint32_t) b) 369157117Smjacob#else 370157354Smjacob#define MPT_TAG_2_REQ(mpt, tag) mpt->tgt_cmd_ptrs[tag >> 18] 371157117Smjacob#endif 372157117Smjacob 373157117Smjacob#define MPT_TGT_STATE(mpt, req) ((mpt_tgt_state_t *) \ 374157117Smjacob (&((uint8_t *)req->req_vbuf)[MPT_RQSL(mpt) - sizeof (mpt_tgt_state_t)])) 375157117Smjacob 376157117SmjacobSTAILQ_HEAD(mpt_hdr_stailq, ccb_hdr); 377157117Smjacob#define MPT_MAX_LUNS 256 378157117Smjacobtypedef struct { 379157117Smjacob struct mpt_hdr_stailq atios; 380157117Smjacob struct mpt_hdr_stailq inots; 381157117Smjacob int enabled; 382157117Smjacob} tgt_resource_t; 383157662Smjacob#define MPT_MAX_ELS 64 384157117Smjacob 385147883Sscottl/**************************** Handler Registration ****************************/ 386101704Smjacob/* 387147883Sscottl * Global table of registered reply handlers. The 388147883Sscottl * handler is indicated by byte 3 of the request 389147883Sscottl * index submitted to the IOC. This allows the 390147883Sscottl * driver core to perform generic processing without 391147883Sscottl * any knowledge of per-personality behavior. 392147883Sscottl * 393147883Sscottl * MPT_NUM_REPLY_HANDLERS must be a power of 2 394147883Sscottl * to allow the easy generation of a mask. 395147883Sscottl * 396147883Sscottl * The handler offsets used by the core are hard coded 397147883Sscottl * allowing faster code generation when assigning a handler 398147883Sscottl * to a request. All "personalities" must use the 399147883Sscottl * the handler registration mechanism. 400147883Sscottl * 401147883Sscottl * The IOC handlers that are rarely executed are placed 402147883Sscottl * at the tail of the table to make it more likely that 403147883Sscottl * all commonly executed handlers fit in a single cache 404147883Sscottl * line. 405101704Smjacob */ 406157117Smjacob#define MPT_NUM_REPLY_HANDLERS (32) 407147883Sscottl#define MPT_REPLY_HANDLER_EVENTS MPT_CBI_TO_HID(0) 408147883Sscottl#define MPT_REPLY_HANDLER_CONFIG MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-1) 409147883Sscottl#define MPT_REPLY_HANDLER_HANDSHAKE MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-2) 410147883Sscottltypedef int mpt_reply_handler_t(struct mpt_softc *mpt, request_t *request, 411157117Smjacob uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame); 412147883Sscottltypedef union { 413147883Sscottl mpt_reply_handler_t *reply_handler; 414147883Sscottl} mpt_handler_t; 415101704Smjacob 416147883Sscottltypedef enum { 417147883Sscottl MPT_HANDLER_REPLY, 418147883Sscottl MPT_HANDLER_EVENT, 419147883Sscottl MPT_HANDLER_RESET, 420147883Sscottl MPT_HANDLER_SHUTDOWN 421147883Sscottl} mpt_handler_type; 422101704Smjacob 423147883Sscottlstruct mpt_handler_record 424147883Sscottl{ 425147883Sscottl LIST_ENTRY(mpt_handler_record) links; 426147883Sscottl mpt_handler_t handler; 427101704Smjacob}; 428101704Smjacob 429147883SscottlLIST_HEAD(mpt_handler_list, mpt_handler_record); 430147883Sscottl 431147883Sscottl/* 432147883Sscottl * The handler_id is currently unused but would contain the 433147883Sscottl * handler ID used in the MsgContext field to allow direction 434147883Sscottl * of replies to the handler. Registrations that don't require 435147883Sscottl * a handler id can pass in NULL for the handler_id. 436147883Sscottl * 437147883Sscottl * Deregistrations for handlers without a handler id should 438147883Sscottl * pass in MPT_HANDLER_ID_NONE. 439147883Sscottl */ 440147883Sscottl#define MPT_HANDLER_ID_NONE (0xFFFFFFFF) 441147883Sscottlint mpt_register_handler(struct mpt_softc *, mpt_handler_type, 442147883Sscottl mpt_handler_t, uint32_t *); 443147883Sscottlint mpt_deregister_handler(struct mpt_softc *, mpt_handler_type, 444147883Sscottl mpt_handler_t, uint32_t); 445147883Sscottl 446147883Sscottl/******************* Per-Controller Instance Data Structures ******************/ 447147883SscottlTAILQ_HEAD(req_queue, req_entry); 448147883Sscottl 449147883Sscottl/* Structure for saving proper values for modifyable PCI config registers */ 450147883Sscottlstruct mpt_pci_cfg { 451147883Sscottl uint16_t Command; 452147883Sscottl uint16_t LatencyTimer_LineSize; 453147883Sscottl uint32_t IO_BAR; 454147883Sscottl uint32_t Mem0_BAR[2]; 455147883Sscottl uint32_t Mem1_BAR[2]; 456147883Sscottl uint32_t ROM_BAR; 457147883Sscottl uint8_t IntLine; 458147883Sscottl uint32_t PMCSR; 459101704Smjacob}; 460101704Smjacob 461147883Sscottltypedef enum { 462147883Sscottl MPT_RVF_NONE = 0x0, 463147883Sscottl MPT_RVF_ACTIVE = 0x1, 464147883Sscottl MPT_RVF_ANNOUNCED = 0x2, 465147883Sscottl MPT_RVF_UP2DATE = 0x4, 466147883Sscottl MPT_RVF_REFERENCED = 0x8, 467147883Sscottl MPT_RVF_WCE_CHANGED = 0x10 468147883Sscottl} mpt_raid_volume_flags; 469101704Smjacob 470147883Sscottlstruct mpt_raid_volume { 471147883Sscottl CONFIG_PAGE_RAID_VOL_0 *config_page; 472147883Sscottl MPI_RAID_VOL_INDICATOR sync_progress; 473147883Sscottl mpt_raid_volume_flags flags; 474158933Smjacob u_int quiesced_disks; 475101704Smjacob}; 476101704Smjacob 477147883Sscottltypedef enum { 478147883Sscottl MPT_RDF_NONE = 0x00, 479147883Sscottl MPT_RDF_ACTIVE = 0x01, 480147883Sscottl MPT_RDF_ANNOUNCED = 0x02, 481147883Sscottl MPT_RDF_UP2DATE = 0x04, 482147883Sscottl MPT_RDF_REFERENCED = 0x08, 483147883Sscottl MPT_RDF_QUIESCING = 0x10, 484147883Sscottl MPT_RDF_QUIESCED = 0x20 485147883Sscottl} mpt_raid_disk_flags; 486147883Sscottl 487147883Sscottlstruct mpt_raid_disk { 488147883Sscottl CONFIG_PAGE_RAID_PHYS_DISK_0 config_page; 489147883Sscottl struct mpt_raid_volume *volume; 490147883Sscottl u_int member_number; 491147883Sscottl u_int pass_thru_active; 492147883Sscottl mpt_raid_disk_flags flags; 493101704Smjacob}; 494101704Smjacob 495147883Sscottlstruct mpt_evtf_record { 496147883Sscottl MSG_EVENT_NOTIFY_REPLY reply; 497147883Sscottl uint32_t context; 498147883Sscottl LIST_ENTRY(mpt_evtf_record) links; 499147883Sscottl}; 500101704Smjacob 501147883SscottlLIST_HEAD(mpt_evtf_list, mpt_evtf_record); 502101704Smjacob 503170252Sscottlstruct mptsas_devinfo { 504170252Sscottl uint16_t dev_handle; 505170252Sscottl uint16_t parent_dev_handle; 506170252Sscottl uint16_t enclosure_handle; 507170252Sscottl uint16_t slot; 508170252Sscottl uint8_t phy_num; 509170252Sscottl uint8_t physical_port; 510170252Sscottl uint8_t target_id; 511170252Sscottl uint8_t bus; 512170252Sscottl uint64_t sas_address; 513170252Sscottl uint32_t device_info; 514170252Sscottl}; 515170252Sscottl 516170252Sscottlstruct mptsas_phyinfo { 517170252Sscottl uint16_t handle; 518170252Sscottl uint8_t phy_num; 519170252Sscottl uint8_t port_id; 520170252Sscottl uint8_t negotiated_link_rate; 521170252Sscottl uint8_t hw_link_rate; 522170252Sscottl uint8_t programmed_link_rate; 523170252Sscottl uint8_t sas_port_add_phy; 524170252Sscottl struct mptsas_devinfo identify; 525170252Sscottl struct mptsas_devinfo attached; 526170252Sscottl}; 527170252Sscottl 528170252Sscottlstruct mptsas_portinfo { 529170252Sscottl uint16_t num_phys; 530170252Sscottl struct mptsas_phyinfo *phy_info; 531170252Sscottl}; 532170252Sscottl 533147883Sscottlstruct mpt_softc { 534147883Sscottl device_t dev; 535147883Sscottl struct mtx mpt_lock; 536157662Smjacob int mpt_locksetup; 537147883Sscottl uint32_t mpt_pers_mask; 538160290Smjacob uint32_t 539231518Smarius : 7, 540157117Smjacob unit : 8, 541165814Smjacob ready : 1, 542164990Smjacob fw_uploaded : 1, 543164416Smjacob msi_enable : 1, 544157117Smjacob twildcard : 1, 545157117Smjacob tenabled : 1, 546160290Smjacob do_cfg_role : 1, 547158982Smjacob raid_enabled : 1, 548147883Sscottl raid_mwce_set : 1, 549147883Sscottl getreqwaiter : 1, 550147883Sscottl shutdwn_raid : 1, 551147883Sscottl shutdwn_recovery: 1, 552147883Sscottl outofbeer : 1, 553147883Sscottl disabled : 1, 554159178Smjacob is_spi : 1, 555157117Smjacob is_sas : 1, 556231518Smarius is_fc : 1, 557231518Smarius is_1078 : 1; 558101704Smjacob 559160290Smjacob u_int cfg_role; 560160290Smjacob u_int role; /* role: none, ini, target, both */ 561160290Smjacob 562147883Sscottl u_int verbose; 563165814Smjacob#ifdef MPT_TEST_MULTIPATH 564165814Smjacob int failure_id; 565165814Smjacob#endif 566101704Smjacob 567147883Sscottl /* 568147883Sscottl * IOC Facts 569147883Sscottl */ 570164990Smjacob MSG_IOC_FACTS_REPLY ioc_facts; 571101704Smjacob 572147883Sscottl /* 573147883Sscottl * Port Facts 574147883Sscottl */ 575164990Smjacob MSG_PORT_FACTS_REPLY * port_facts; 576164990Smjacob#define mpt_max_tgtcmds port_facts[0].MaxPostedCmdBuffers 577102822Smjacob 578147883Sscottl /* 579147883Sscottl * Device Configuration Information 580147883Sscottl */ 581147883Sscottl union { 582147883Sscottl struct mpt_spi_cfg { 583147883Sscottl CONFIG_PAGE_SCSI_PORT_0 _port_page0; 584147883Sscottl CONFIG_PAGE_SCSI_PORT_1 _port_page1; 585147883Sscottl CONFIG_PAGE_SCSI_PORT_2 _port_page2; 586147883Sscottl CONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16]; 587147883Sscottl CONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; 588207287Smarius int _ini_id; 589147883Sscottl uint16_t _tag_enable; 590147883Sscottl uint16_t _disc_enable; 591147883Sscottl } spi; 592147883Sscottl#define mpt_port_page0 cfg.spi._port_page0 593147883Sscottl#define mpt_port_page1 cfg.spi._port_page1 594147883Sscottl#define mpt_port_page2 cfg.spi._port_page2 595147883Sscottl#define mpt_dev_page0 cfg.spi._dev_page0 596147883Sscottl#define mpt_dev_page1 cfg.spi._dev_page1 597207287Smarius#define mpt_ini_id cfg.spi._ini_id 598147883Sscottl#define mpt_tag_enable cfg.spi._tag_enable 599147883Sscottl#define mpt_disc_enable cfg.spi._disc_enable 600147883Sscottl struct mpi_fc_cfg { 601157117Smjacob CONFIG_PAGE_FC_PORT_0 _port_page0; 602159919Smjacob uint32_t _port_speed; 603157117Smjacob#define mpt_fcport_page0 cfg.fc._port_page0 604159919Smjacob#define mpt_fcport_speed cfg.fc._port_speed 605147883Sscottl } fc; 606147883Sscottl } cfg; 607160397Smjacob /* 608160397Smjacob * Device config information stored up for sysctl to access 609160397Smjacob */ 610160397Smjacob union { 611160397Smjacob struct { 612160397Smjacob unsigned int initiator_id; 613160397Smjacob } spi; 614160397Smjacob struct { 615160397Smjacob char wwnn[19]; 616160397Smjacob char wwpn[19]; 617160397Smjacob } fc; 618160397Smjacob } scinfo; 619147883Sscottl 620158982Smjacob /* Controller Info for RAID information */ 621147883Sscottl CONFIG_PAGE_IOC_2 * ioc_page2; 622147883Sscottl CONFIG_PAGE_IOC_3 * ioc_page3; 623147883Sscottl 624147883Sscottl /* Raid Data */ 625147883Sscottl struct mpt_raid_volume* raid_volumes; 626147883Sscottl struct mpt_raid_disk* raid_disks; 627147883Sscottl u_int raid_max_volumes; 628147883Sscottl u_int raid_max_disks; 629147883Sscottl u_int raid_page0_len; 630147883Sscottl u_int raid_wakeup; 631147883Sscottl u_int raid_rescan; 632147883Sscottl u_int raid_resync_rate; 633147883Sscottl u_int raid_mwce_setting; 634147883Sscottl u_int raid_queue_depth; 635152444Skan u_int raid_nonopt_volumes; 636147883Sscottl struct proc *raid_thread; 637147883Sscottl struct callout raid_timer; 638147883Sscottl 639147883Sscottl /* 640147883Sscottl * PCI Hardware info 641147883Sscottl */ 642147883Sscottl struct resource * pci_irq; /* Interrupt map for chip */ 643220945Smarius void * ih; /* Interrupt handle */ 644233403Smarius#if 0 645147883Sscottl struct mpt_pci_cfg pci_cfg; /* saved PCI conf registers */ 646233403Smarius#endif 647147883Sscottl 648147883Sscottl /* 649147883Sscottl * DMA Mapping Stuff 650147883Sscottl */ 651147883Sscottl struct resource * pci_reg; /* Register map for chip */ 652147883Sscottl bus_space_tag_t pci_st; /* Bus tag for registers */ 653147883Sscottl bus_space_handle_t pci_sh; /* Bus handle for registers */ 654147883Sscottl /* PIO versions of above. */ 655147883Sscottl struct resource * pci_pio_reg; 656147883Sscottl bus_space_tag_t pci_pio_st; 657147883Sscottl bus_space_handle_t pci_pio_sh; 658147883Sscottl 659147883Sscottl bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */ 660147883Sscottl bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */ 661147883Sscottl bus_dmamap_t reply_dmap; /* DMA map for reply memory */ 662147883Sscottl uint8_t *reply; /* KVA of reply memory */ 663147883Sscottl bus_addr_t reply_phys; /* BusAddr of reply memory */ 664147883Sscottl 665147883Sscottl bus_dma_tag_t buffer_dmat; /* DMA tag for buffers */ 666147883Sscottl bus_dma_tag_t request_dmat; /* DMA tag for request memroy */ 667147883Sscottl bus_dmamap_t request_dmap; /* DMA map for request memroy */ 668147883Sscottl uint8_t *request; /* KVA of Request memory */ 669157117Smjacob bus_addr_t request_phys; /* BusAddr of request memory */ 670147883Sscottl 671155521Smjacob uint32_t max_seg_cnt; /* calculated after IOC facts */ 672209599Sken uint32_t max_cam_seg_cnt;/* calculated from MAXPHYS*/ 673155521Smjacob 674155521Smjacob /* 675155521Smjacob * Hardware management 676155521Smjacob */ 677147883Sscottl u_int reset_cnt; 678147883Sscottl 679147883Sscottl /* 680147883Sscottl * CAM && Software Management 681147883Sscottl */ 682147883Sscottl request_t *request_pool; 683147883Sscottl struct req_queue request_free_list; 684147883Sscottl struct req_queue request_pending_list; 685147883Sscottl struct req_queue request_timeout_list; 686147883Sscottl 687147883Sscottl 688147883Sscottl struct cam_sim *sim; 689147883Sscottl struct cam_path *path; 690147883Sscottl 691147883Sscottl struct cam_sim *phydisk_sim; 692147883Sscottl struct cam_path *phydisk_path; 693147883Sscottl 694147883Sscottl struct proc *recovery_thread; 695147883Sscottl request_t *tmf_req; 696147883Sscottl 697157117Smjacob /* 698157354Smjacob * Deferred frame acks due to resource shortage. 699157354Smjacob */ 700157354Smjacob struct mpt_evtf_list ack_frames; 701159312Smjacob 702157354Smjacob /* 703157117Smjacob * Target Mode Support 704157117Smjacob */ 705157117Smjacob uint32_t scsi_tgt_handler_id; 706157117Smjacob request_t ** tgt_cmd_ptrs; 707157662Smjacob request_t ** els_cmd_ptrs; /* FC only */ 708147883Sscottl 709157117Smjacob /* 710157117Smjacob * *snork*- this is chosen to be here *just in case* somebody 711157117Smjacob * forgets to point to it exactly and we index off of trt with 712157117Smjacob * CAM_LUN_WILDCARD. 713157117Smjacob */ 714160391Smjacob tgt_resource_t trt_wildcard; /* wildcard luns */ 715157117Smjacob tgt_resource_t trt[MPT_MAX_LUNS]; 716157117Smjacob uint16_t tgt_cmds_allocated; 717157662Smjacob uint16_t els_cmds_allocated; /* FC only */ 718157117Smjacob 719157117Smjacob uint16_t timeouts; /* timeout count */ 720157117Smjacob uint16_t success; /* successes afer timeout */ 721157662Smjacob uint16_t sequence; /* Sequence Number */ 722157662Smjacob uint16_t pad3; 723157117Smjacob 724264949Smarius#if 0 725159312Smjacob /* Paired port in some dual adapters configurations */ 726147883Sscottl struct mpt_softc * mpt2; 727264949Smarius#endif 728147883Sscottl 729147883Sscottl /* FW Image management */ 730147883Sscottl uint32_t fw_image_size; 731147883Sscottl uint8_t *fw_image; 732147883Sscottl bus_dma_tag_t fw_dmat; /* DMA tag for firmware image */ 733147883Sscottl bus_dmamap_t fw_dmap; /* DMA map for firmware image */ 734159178Smjacob bus_addr_t fw_phys; /* BusAddr of firmware image */ 735147883Sscottl 736170252Sscottl /* SAS Topology */ 737170252Sscottl struct mptsas_portinfo *sas_portinfo; 738170252Sscottl 739147883Sscottl /* Shutdown Event Handler. */ 740147883Sscottl eventhandler_tag eh; 741147883Sscottl 742178814Sjhb /* Userland management interface. */ 743178814Sjhb struct cdev *cdev; 744178814Sjhb 745147883Sscottl TAILQ_ENTRY(mpt_softc) links; 746147883Sscottl}; 747147883Sscottl 748157662Smjacobstatic __inline void mpt_assign_serno(struct mpt_softc *, request_t *); 749157662Smjacob 750157662Smjacobstatic __inline void 751157662Smjacobmpt_assign_serno(struct mpt_softc *mpt, request_t *req) 752157662Smjacob{ 753157662Smjacob if ((req->serno = mpt->sequence++) == 0) { 754157662Smjacob req->serno = mpt->sequence++; 755157662Smjacob } 756157662Smjacob} 757157662Smjacob 758157117Smjacob/***************************** Locking Primitives *****************************/ 759147883Sscottl#define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE 760147883Sscottl#define MPT_LOCK_SETUP(mpt) \ 761147883Sscottl mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF); \ 762147883Sscottl mpt->mpt_locksetup = 1 763147883Sscottl#define MPT_LOCK_DESTROY(mpt) \ 764147883Sscottl if (mpt->mpt_locksetup) { \ 765147883Sscottl mtx_destroy(&mpt->mpt_lock); \ 766147883Sscottl mpt->mpt_locksetup = 0; \ 767147883Sscottl } 768147883Sscottl 769147883Sscottl#define MPT_LOCK(mpt) mtx_lock(&(mpt)->mpt_lock) 770147883Sscottl#define MPT_UNLOCK(mpt) mtx_unlock(&(mpt)->mpt_lock) 771157662Smjacob#define MPT_OWNED(mpt) mtx_owned(&(mpt)->mpt_lock) 772169293Smjacob#define MPT_LOCK_ASSERT(mpt) mtx_assert(&(mpt)->mpt_lock, MA_OWNED) 773275982Ssmh#define mpt_sleep(mpt, ident, priority, wmesg, sbt) \ 774275982Ssmh msleep_sbt(ident, &(mpt)->mpt_lock, priority, wmesg, sbt, 0, 0) 775275982Ssmh#define mpt_req_timeout(req, sbt, func, arg) \ 776275982Ssmh callout_reset_sbt(&(req)->callout, (sbt), 0, (func), (arg), 0) 777169293Smjacob#define mpt_req_untimeout(req, func, arg) \ 778169293Smjacob callout_stop(&(req)->callout) 779198262Skan#define mpt_callout_init(mpt, c) \ 780198262Skan callout_init_mtx(c, &(mpt)->mpt_lock, 0) 781198262Skan#define mpt_callout_drain(mpt, c) \ 782198262Skan callout_drain(c) 783157662Smjacob 784147883Sscottl/******************************* Register Access ******************************/ 785147883Sscottlstatic __inline void mpt_write(struct mpt_softc *, size_t, uint32_t); 786292794Smariusstatic __inline void mpt_write_stream(struct mpt_softc *, size_t, uint32_t); 787147883Sscottlstatic __inline uint32_t mpt_read(struct mpt_softc *, int); 788147883Sscottlstatic __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t); 789147883Sscottlstatic __inline uint32_t mpt_pio_read(struct mpt_softc *, int); 790147883Sscottl 791147883Sscottlstatic __inline void 792147883Sscottlmpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val) 793147883Sscottl{ 794147883Sscottl bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val); 795147883Sscottl} 796147883Sscottl 797292794Smariusstatic __inline void 798292794Smariusmpt_write_stream(struct mpt_softc *mpt, size_t offset, uint32_t val) 799292794Smarius{ 800292794Smarius bus_space_write_stream_4(mpt->pci_st, mpt->pci_sh, offset, val); 801292794Smarius} 802292794Smarius 803147883Sscottlstatic __inline uint32_t 804147883Sscottlmpt_read(struct mpt_softc *mpt, int offset) 805147883Sscottl{ 806147883Sscottl return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset)); 807147883Sscottl} 808147883Sscottl 809147883Sscottl/* 810147883Sscottl * Some operations (e.g. diagnostic register writes while the ARM proccessor 811147883Sscottl * is disabled), must be performed using "PCI pio" operations. On non-PCI 812147883Sscottl * busses, these operations likely map to normal register accesses. 813147883Sscottl */ 814147883Sscottlstatic __inline void 815147883Sscottlmpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val) 816147883Sscottl{ 817231518Smarius KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource")); 818147883Sscottl bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val); 819147883Sscottl} 820147883Sscottl 821147883Sscottlstatic __inline uint32_t 822147883Sscottlmpt_pio_read(struct mpt_softc *mpt, int offset) 823147883Sscottl{ 824231518Smarius KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource")); 825147883Sscottl return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset)); 826147883Sscottl} 827292794Smarius 828147883Sscottl/*********************** Reply Frame/Request Management ***********************/ 829147883Sscottl/* Max MPT Reply we are willing to accept (must be power of 2) */ 830155521Smjacob#define MPT_REPLY_SIZE 256 831147883Sscottl 832157117Smjacob/* 833157117Smjacob * Must be less than 16384 in order for target mode to work 834157117Smjacob */ 835155521Smjacob#define MPT_MAX_REQUESTS(mpt) 512 836155521Smjacob#define MPT_REQUEST_AREA 512 837155521Smjacob#define MPT_SENSE_SIZE 32 /* included in MPT_REQUEST_AREA */ 838147883Sscottl#define MPT_REQ_MEM_SIZE(mpt) (MPT_MAX_REQUESTS(mpt) * MPT_REQUEST_AREA) 839147883Sscottl 840157354Smjacob#define MPT_CONTEXT_CB_SHIFT (16) 841157117Smjacob#define MPT_CBI(handle) (handle >> MPT_CONTEXT_CB_SHIFT) 842147883Sscottl#define MPT_CBI_TO_HID(cbi) ((cbi) << MPT_CONTEXT_CB_SHIFT) 843147883Sscottl#define MPT_CONTEXT_TO_CBI(x) \ 844147883Sscottl (((x) >> MPT_CONTEXT_CB_SHIFT) & (MPT_NUM_REPLY_HANDLERS - 1)) 845157354Smjacob#define MPT_CONTEXT_REQI_MASK 0xFFFF 846157117Smjacob#define MPT_CONTEXT_TO_REQI(x) ((x) & MPT_CONTEXT_REQI_MASK) 847147883Sscottl 848147883Sscottl/* 849147883Sscottl * Convert a 32bit physical address returned from IOC to an 850147883Sscottl * offset into our reply frame memory or the kvm address needed 851147883Sscottl * to access the data. The returned address is only the low 852147883Sscottl * 32 bits, so mask our base physical address accordingly. 853147883Sscottl */ 854147883Sscottl#define MPT_REPLY_BADDR(x) \ 855147883Sscottl (x << 1) 856147883Sscottl#define MPT_REPLY_OTOV(m, i) \ 857147883Sscottl ((void *)(&m->reply[i])) 858147883Sscottl 859147883Sscottl#define MPT_DUMP_REPLY_FRAME(mpt, reply_frame) \ 860147883Sscottldo { \ 861158982Smjacob if (mpt->verbose > MPT_PRT_DEBUG) \ 862147883Sscottl mpt_dump_reply_frame(mpt, reply_frame); \ 863147883Sscottl} while(0) 864147883Sscottl 865147883Sscottlstatic __inline uint32_t mpt_pop_reply_queue(struct mpt_softc *mpt); 866147883Sscottlstatic __inline void mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr); 867147883Sscottl 868147883Sscottl/* 869147883Sscottl * Give the reply buffer back to the IOC after we have 870147883Sscottl * finished processing it. 871147883Sscottl */ 872147883Sscottlstatic __inline void 873147883Sscottlmpt_free_reply(struct mpt_softc *mpt, uint32_t ptr) 874147883Sscottl{ 875147883Sscottl mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr); 876147883Sscottl} 877147883Sscottl 878147883Sscottl/* Get a reply from the IOC */ 879147883Sscottlstatic __inline uint32_t 880147883Sscottlmpt_pop_reply_queue(struct mpt_softc *mpt) 881147883Sscottl{ 882147883Sscottl return mpt_read(mpt, MPT_OFFSET_REPLY_Q); 883147883Sscottl} 884147883Sscottl 885157354Smjacobvoid 886157354Smjacobmpt_complete_request_chain(struct mpt_softc *, struct req_queue *, u_int); 887157354Smjacob 888220945Smarius/************************** Scatter Gather Management **************************/ 889155521Smjacob/* MPT_RQSL- size of request frame, in bytes */ 890164990Smjacob#define MPT_RQSL(mpt) (mpt->ioc_facts.RequestFrameSize << 2) 891155521Smjacob 892155521Smjacob/* MPT_NSGL- how many SG entries can fit in a request frame size */ 893155521Smjacob#define MPT_NSGL(mpt) (MPT_RQSL(mpt) / sizeof (SGE_IO_UNION)) 894155521Smjacob 895155521Smjacob/* MPT_NRFM- how many request frames can fit in each request alloc we make */ 896155521Smjacob#define MPT_NRFM(mpt) (MPT_REQUEST_AREA / MPT_RQSL(mpt)) 897155521Smjacob 898147883Sscottl/* 899155521Smjacob * MPT_NSGL_FIRST- # of SG elements that can fit after 900155521Smjacob * an I/O request but still within the request frame. 901155521Smjacob * Do this safely based upon SGE_IO_UNION. 902155521Smjacob * 903155521Smjacob * Note that the first element is *within* the SCSI request. 904147883Sscottl */ 905155521Smjacob#define MPT_NSGL_FIRST(mpt) \ 906155521Smjacob ((MPT_RQSL(mpt) - sizeof (MSG_SCSI_IO_REQUEST) + sizeof (SGE_IO_UNION)) / \ 907155521Smjacob sizeof (SGE_IO_UNION)) 908147883Sscottl 909147883Sscottl/***************************** IOC Initialization *****************************/ 910147883Sscottlint mpt_reset(struct mpt_softc *, int /*reinit*/); 911147883Sscottl 912157117Smjacob/****************************** Debugging ************************************/ 913160290Smjacobvoid mpt_dump_data(struct mpt_softc *, const char *, void *, int); 914158933Smjacobvoid mpt_dump_request(struct mpt_softc *, request_t *); 915158933Smjacob 916147883Sscottlenum { 917147883Sscottl MPT_PRT_ALWAYS, 918147883Sscottl MPT_PRT_FATAL, 919147883Sscottl MPT_PRT_ERROR, 920147883Sscottl MPT_PRT_WARN, 921147883Sscottl MPT_PRT_INFO, 922159049Smjacob MPT_PRT_NEGOTIATION, 923147883Sscottl MPT_PRT_DEBUG, 924157117Smjacob MPT_PRT_DEBUG1, 925157117Smjacob MPT_PRT_DEBUG2, 926157117Smjacob MPT_PRT_DEBUG3, 927155521Smjacob MPT_PRT_TRACE, 928155521Smjacob MPT_PRT_NONE=100 929147883Sscottl}; 930147883Sscottl 931147883Sscottl#define mpt_lprt(mpt, level, ...) \ 932147883Sscottldo { \ 933147883Sscottl if (level <= (mpt)->verbose) \ 934147883Sscottl mpt_prt(mpt, __VA_ARGS__); \ 935147883Sscottl} while (0) 936147883Sscottl 937224493Smarius#if 0 938215325Smarius#define mpt_lprtc(mpt, level, ...) \ 939215325Smariusdo { \ 940215325Smarius if (level <= (mpt)->verbose) \ 941215325Smarius mpt_prtc(mpt, __VA_ARGS__); \ 942147883Sscottl} while (0) 943224493Smarius#endif 944241874Smarius 945157117Smjacobvoid mpt_prt(struct mpt_softc *, const char *, ...) 946157117Smjacob __printflike(2, 3); 947157117Smjacobvoid mpt_prtc(struct mpt_softc *, const char *, ...) 948157117Smjacob __printflike(2, 3); 949147883Sscottl 950157117Smjacob/**************************** Target Mode Related ***************************/ 951157117Smjacobstatic __inline int mpt_cdblen(uint8_t, int); 952157117Smjacobstatic __inline int 953157117Smjacobmpt_cdblen(uint8_t cdb0, int maxlen) 954157117Smjacob{ 955157117Smjacob int group = cdb0 >> 5; 956157117Smjacob switch (group) { 957157117Smjacob case 0: 958157117Smjacob return (6); 959157117Smjacob case 1: 960157117Smjacob return (10); 961157117Smjacob case 4: 962157117Smjacob case 5: 963157117Smjacob return (12); 964157117Smjacob default: 965157117Smjacob return (16); 966157117Smjacob } 967157117Smjacob} 968292794Smarius 969157117Smjacob#ifdef INVARIANTS 970157117Smjacobstatic __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t); 971157117Smjacobstatic __inline request_t * 972157117Smjacobmpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag) 973157117Smjacob{ 974157354Smjacob uint16_t rtg = (tag >> 18); 975231228Smarius KASSERT(rtg < mpt->tgt_cmds_allocated, ("bad tag %d", tag)); 976157117Smjacob KASSERT(mpt->tgt_cmd_ptrs, ("no cmd backpointer array")); 977157117Smjacob KASSERT(mpt->tgt_cmd_ptrs[rtg], ("no cmd backpointer")); 978157117Smjacob return (mpt->tgt_cmd_ptrs[rtg]); 979157117Smjacob} 980213147Smarius#endif 981157662Smjacob 982157662Smjacobstatic __inline int 983157662Smjacobmpt_req_on_free_list(struct mpt_softc *, request_t *); 984157662Smjacobstatic __inline int 985157662Smjacobmpt_req_on_pending_list(struct mpt_softc *, request_t *); 986157662Smjacob 987157662Smjacob/* 988157662Smjacob * Is request on freelist? 989157662Smjacob */ 990157662Smjacobstatic __inline int 991157662Smjacobmpt_req_on_free_list(struct mpt_softc *mpt, request_t *req) 992157662Smjacob{ 993157662Smjacob request_t *lrq; 994157662Smjacob 995157662Smjacob TAILQ_FOREACH(lrq, &mpt->request_free_list, links) { 996157662Smjacob if (lrq == req) { 997157662Smjacob return (1); 998157662Smjacob } 999157662Smjacob } 1000157662Smjacob return (0); 1001157662Smjacob} 1002157662Smjacob 1003157662Smjacob/* 1004157662Smjacob * Is request on pending list? 1005157662Smjacob */ 1006157662Smjacobstatic __inline int 1007157662Smjacobmpt_req_on_pending_list(struct mpt_softc *mpt, request_t *req) 1008157662Smjacob{ 1009157662Smjacob request_t *lrq; 1010157662Smjacob 1011157662Smjacob TAILQ_FOREACH(lrq, &mpt->request_pending_list, links) { 1012157662Smjacob if (lrq == req) { 1013157662Smjacob return (1); 1014157662Smjacob } 1015157662Smjacob } 1016157662Smjacob return (0); 1017157662Smjacob} 1018157662Smjacob 1019213147Smarius#ifdef INVARIANTS 1020213147Smariusstatic __inline void 1021213147Smariusmpt_req_spcl(struct mpt_softc *, request_t *, const char *, int); 1022213147Smariusstatic __inline void 1023213147Smariusmpt_req_not_spcl(struct mpt_softc *, request_t *, const char *, int); 1024213147Smarius 1025157662Smjacob/* 1026157662Smjacob * Make sure that req *is* part of one of the special lists 1027157662Smjacob */ 1028157662Smjacobstatic __inline void 1029157662Smjacobmpt_req_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) 1030157662Smjacob{ 1031157662Smjacob int i; 1032157662Smjacob for (i = 0; i < mpt->els_cmds_allocated; i++) { 1033157662Smjacob if (req == mpt->els_cmd_ptrs[i]) { 1034157662Smjacob return; 1035157662Smjacob } 1036157662Smjacob } 1037157662Smjacob for (i = 0; i < mpt->tgt_cmds_allocated; i++) { 1038157662Smjacob if (req == mpt->tgt_cmd_ptrs[i]) { 1039157662Smjacob return; 1040157662Smjacob } 1041157662Smjacob } 1042231228Smarius panic("%s(%d): req %p:%u function %x not in els or tgt ptrs", 1043157662Smjacob s, line, req, req->serno, 1044157662Smjacob ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function); 1045157662Smjacob} 1046157662Smjacob 1047157662Smjacob/* 1048157662Smjacob * Make sure that req is *not* part of one of the special lists. 1049157662Smjacob */ 1050157662Smjacobstatic __inline void 1051157662Smjacobmpt_req_not_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) 1052157662Smjacob{ 1053157662Smjacob int i; 1054157662Smjacob for (i = 0; i < mpt->els_cmds_allocated; i++) { 1055157662Smjacob KASSERT(req != mpt->els_cmd_ptrs[i], 1056231228Smarius ("%s(%d): req %p:%u func %x in els ptrs at ioindex %d", 1057157662Smjacob s, line, req, req->serno, 1058157662Smjacob ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); 1059157662Smjacob } 1060157662Smjacob for (i = 0; i < mpt->tgt_cmds_allocated; i++) { 1061157662Smjacob KASSERT(req != mpt->tgt_cmd_ptrs[i], 1062231228Smarius ("%s(%d): req %p:%u func %x in tgt ptrs at ioindex %d", 1063157662Smjacob s, line, req, req->serno, 1064157662Smjacob ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); 1065157662Smjacob } 1066157662Smjacob} 1067157117Smjacob#endif 1068147883Sscottl 1069160391Smjacob/* 1070160391Smjacob * Task Management Types, purely for internal consumption 1071160391Smjacob */ 1072157117Smjacobtypedef enum { 1073157117Smjacob MPT_ABORT_TASK_SET=1234, 1074157117Smjacob MPT_CLEAR_TASK_SET, 1075157117Smjacob MPT_TARGET_RESET, 1076157117Smjacob MPT_CLEAR_ACA, 1077157117Smjacob MPT_TERMINATE_TASK, 1078157117Smjacob MPT_NIL_TMT_VALUE=5678 1079157117Smjacob} mpt_task_mgmt_t; 1080157117Smjacob 1081147883Sscottl/**************************** Unclassified Routines ***************************/ 1082147883Sscottlvoid mpt_send_cmd(struct mpt_softc *mpt, request_t *req); 1083147883Sscottlint mpt_recv_handshake_reply(struct mpt_softc *mpt, 1084147883Sscottl size_t reply_len, void *reply); 1085147883Sscottlint mpt_wait_req(struct mpt_softc *mpt, request_t *req, 1086147883Sscottl mpt_req_state_t state, mpt_req_state_t mask, 1087147883Sscottl int sleep_ok, int time_ms); 1088147883Sscottlvoid mpt_enable_ints(struct mpt_softc *mpt); 1089147883Sscottlvoid mpt_disable_ints(struct mpt_softc *mpt); 1090147883Sscottlint mpt_attach(struct mpt_softc *mpt); 1091147883Sscottlint mpt_shutdown(struct mpt_softc *mpt); 1092147883Sscottlint mpt_detach(struct mpt_softc *mpt); 1093147883Sscottlint mpt_send_handshake_cmd(struct mpt_softc *mpt, 1094147883Sscottl size_t len, void *cmd); 1095147883Sscottlrequest_t * mpt_get_request(struct mpt_softc *mpt, int sleep_ok); 1096147883Sscottlvoid mpt_free_request(struct mpt_softc *mpt, request_t *req); 1097147883Sscottlvoid mpt_intr(void *arg); 1098147883Sscottlvoid mpt_check_doorbell(struct mpt_softc *mpt); 1099147883Sscottlvoid mpt_dump_reply_frame(struct mpt_softc *mpt, 1100147883Sscottl MSG_DEFAULT_REPLY *reply_frame); 1101147883Sscottl 1102147883Sscottlint mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/, 1103170252Sscottl cfgparms_t *params, 1104147883Sscottl bus_addr_t /*addr*/, bus_size_t/*len*/, 1105147883Sscottl int /*sleep_ok*/, int /*timeout_ms*/); 1106170252Sscottlint mpt_read_extcfg_header(struct mpt_softc *mpt, int PageVersion, 1107170252Sscottl int PageNumber, uint32_t PageAddress, 1108170252Sscottl int ExtPageType, 1109170252Sscottl CONFIG_EXTENDED_PAGE_HEADER *rslt, 1110170252Sscottl int sleep_ok, int timeout_ms); 1111170252Sscottlint mpt_read_extcfg_page(struct mpt_softc *mpt, int Action, 1112170252Sscottl uint32_t PageAddress, 1113170252Sscottl CONFIG_EXTENDED_PAGE_HEADER *hdr, 1114170252Sscottl void *buf, size_t len, int sleep_ok, 1115170252Sscottl int timeout_ms); 1116147883Sscottlint mpt_read_cfg_header(struct mpt_softc *, int /*PageType*/, 1117147883Sscottl int /*PageNumber*/, 1118147883Sscottl uint32_t /*PageAddress*/, 1119147883Sscottl CONFIG_PAGE_HEADER *, 1120147883Sscottl int /*sleep_ok*/, int /*timeout_ms*/); 1121147883Sscottlint mpt_read_cfg_page(struct mpt_softc *t, int /*Action*/, 1122147883Sscottl uint32_t /*PageAddress*/, 1123147883Sscottl CONFIG_PAGE_HEADER *, size_t /*len*/, 1124147883Sscottl int /*sleep_ok*/, int /*timeout_ms*/); 1125147883Sscottlint mpt_write_cfg_page(struct mpt_softc *, int /*Action*/, 1126147883Sscottl uint32_t /*PageAddress*/, 1127147883Sscottl CONFIG_PAGE_HEADER *, size_t /*len*/, 1128147883Sscottl int /*sleep_ok*/, int /*timeout_ms*/); 1129147883Sscottlstatic __inline int 1130147883Sscottlmpt_read_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress, 1131147883Sscottl CONFIG_PAGE_HEADER *hdr, size_t len, 1132147883Sscottl int sleep_ok, int timeout_ms) 1133147883Sscottl{ 1134147883Sscottl return (mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, 1135147883Sscottl PageAddress, hdr, len, sleep_ok, timeout_ms)); 1136147883Sscottl} 1137147883Sscottl 1138147883Sscottlstatic __inline int 1139147883Sscottlmpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress, 1140147883Sscottl CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok, 1141147883Sscottl int timeout_ms) 1142147883Sscottl{ 1143147883Sscottl return (mpt_write_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, 1144147883Sscottl PageAddress, hdr, len, sleep_ok, 1145147883Sscottl timeout_ms)); 1146147883Sscottl} 1147292794Smarius 1148101704Smjacob/* mpt_debug.c functions */ 1149101704Smjacobvoid mpt_print_reply(void *vmsg); 1150147883Sscottlvoid mpt_print_db(uint32_t mb); 1151101704Smjacobvoid mpt_print_config_reply(void *vmsg); 1152147883Sscottlchar *mpt_ioc_diag(uint32_t diag); 1153147883Sscottlvoid mpt_req_state(mpt_req_state_t state); 1154101704Smjacobvoid mpt_print_config_request(void *vmsg); 1155101704Smjacobvoid mpt_print_request(void *vmsg); 1156155521Smjacobvoid mpt_dump_sgl(SGE_IO_UNION *se, int offset); 1157292794Smarius 1158101704Smjacob#endif /* _MPT_H_ */ 1159