1f11c7f63SJim Harris /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4f11c7f63SJim Harris * BSD LICENSE 5f11c7f63SJim Harris * 6f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 7f11c7f63SJim Harris * All rights reserved. 8f11c7f63SJim Harris * 9f11c7f63SJim Harris * Redistribution and use in source and binary forms, with or without 10f11c7f63SJim Harris * modification, are permitted provided that the following conditions 11f11c7f63SJim Harris * are met: 12f11c7f63SJim Harris * 13f11c7f63SJim Harris * * Redistributions of source code must retain the above copyright 14f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer. 15f11c7f63SJim Harris * * Redistributions in binary form must reproduce the above copyright 16f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer in 17f11c7f63SJim Harris * the documentation and/or other materials provided with the 18f11c7f63SJim Harris * distribution. 19f11c7f63SJim Harris * 20f11c7f63SJim Harris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21f11c7f63SJim Harris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22f11c7f63SJim Harris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23f11c7f63SJim Harris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24f11c7f63SJim Harris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25f11c7f63SJim Harris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26f11c7f63SJim Harris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27f11c7f63SJim Harris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28f11c7f63SJim Harris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29f11c7f63SJim Harris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30f11c7f63SJim Harris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31f11c7f63SJim Harris */ 32f11c7f63SJim Harris 33dd925305SJim Harris #ifndef _ISCI_H 34dd925305SJim Harris #define _ISCI_H 35dd925305SJim Harris 36f11c7f63SJim Harris #include <sys/param.h> 37f11c7f63SJim Harris #include <sys/systm.h> 38f11c7f63SJim Harris #include <sys/kernel.h> 39f11c7f63SJim Harris #include <sys/bus.h> 40f11c7f63SJim Harris #include <sys/lock.h> 41f11c7f63SJim Harris #include <sys/mutex.h> 42f11c7f63SJim Harris #include <sys/types.h> 43f11c7f63SJim Harris #include <sys/malloc.h> 44f11c7f63SJim Harris #include <sys/rman.h> 45f11c7f63SJim Harris 46f11c7f63SJim Harris #include <machine/bus.h> 47f11c7f63SJim Harris #include <machine/resource.h> 48f11c7f63SJim Harris 49f11c7f63SJim Harris #include <cam/cam.h> 50f11c7f63SJim Harris #include <cam/cam_ccb.h> 51f11c7f63SJim Harris #include <cam/cam_sim.h> 52f11c7f63SJim Harris #include <cam/cam_xpt_sim.h> 53f11c7f63SJim Harris 54f11c7f63SJim Harris #include <dev/isci/environment.h> 55f11c7f63SJim Harris #include <dev/isci/scil/intel_pci.h> 56f11c7f63SJim Harris 57f11c7f63SJim Harris #include <dev/isci/scil/sci_types.h> 58f11c7f63SJim Harris #include <dev/isci/scil/sci_object.h> 59f11c7f63SJim Harris #include <dev/isci/scil/sci_status.h> 60f11c7f63SJim Harris #include <dev/isci/scil/sci_pool.h> 61f11c7f63SJim Harris #include <dev/isci/scil/sci_fast_list.h> 62f11c7f63SJim Harris 63f11c7f63SJim Harris #include <dev/isci/scil/sci_controller_constants.h> 64f11c7f63SJim Harris 65f11c7f63SJim Harris #include <dev/isci/scil/scic_controller.h> 66f11c7f63SJim Harris #include <dev/isci/scil/scic_config_parameters.h> 67f11c7f63SJim Harris 68f11c7f63SJim Harris #define DEVICE2SOFTC(dev) ((struct isci_softc *) device_get_softc(dev)) 69f11c7f63SJim Harris 70f11c7f63SJim Harris #define DEVICE_TIMEOUT 1000 71f11c7f63SJim Harris #define SCI_MAX_TIMERS 32 72f11c7f63SJim Harris 73f11c7f63SJim Harris #define ISCI_NUM_PCI_BARS 2 74f11c7f63SJim Harris #define ISCI_MAX_LUN 8 75f11c7f63SJim Harris 76*f6ccd325SWarner Losh /* This device cannot DMA across a 4GB boundary */ 77*f6ccd325SWarner Losh #define ISCI_DMA_BOUNDARY ((bus_addr_t)((uint64_t)1 << 32)) 78*f6ccd325SWarner Losh 79f11c7f63SJim Harris MALLOC_DECLARE(M_ISCI); 80f11c7f63SJim Harris 81f11c7f63SJim Harris struct ISCI_TIMER { 82f11c7f63SJim Harris struct callout callout; 83f11c7f63SJim Harris SCI_TIMER_CALLBACK_T callback; 84f11c7f63SJim Harris void *cookie; 85f11c7f63SJim Harris BOOL is_started; 86f11c7f63SJim Harris }; 87f11c7f63SJim Harris 88f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE { 89f11c7f63SJim Harris uint32_t index; 90f11c7f63SJim Harris struct ISCI_DOMAIN *domain; 91f11c7f63SJim Harris SCI_REMOTE_DEVICE_HANDLE_T sci_object; 92f11c7f63SJim Harris BOOL is_resetting; 93f11c7f63SJim Harris uint32_t frozen_lun_mask; 94f11c7f63SJim Harris SCI_FAST_LIST_ELEMENT_T pending_device_reset_element; 95dd925305SJim Harris 96dd925305SJim Harris /* 97dd925305SJim Harris * This queue maintains CCBs that have been returned with 98dd925305SJim Harris * SCI_IO_FAILURE_INVALID_STATE from the SCI layer. These CCBs 99dd925305SJim Harris * need to be retried, but we cannot return CAM_REQUEUE_REQ because 100dd925305SJim Harris * this status gets passed all the way back up to users of the pass(4) 101dd925305SJim Harris * interface and breaks things like smartctl. So instead, we queue 102dd925305SJim Harris * these CCBs internally. 103dd925305SJim Harris */ 104cb77f0daSJim Harris TAILQ_HEAD(,ccb_hdr) queued_ccbs; 105dd925305SJim Harris 106dd925305SJim Harris /* 107dd925305SJim Harris * Marker denoting this remote device needs its first queued ccb to 108dd925305SJim Harris * be retried. 109dd925305SJim Harris */ 110dd925305SJim Harris BOOL release_queued_ccb; 111dd925305SJim Harris 112dd925305SJim Harris /* 113dd925305SJim Harris * Points to a CCB in the queue that is currently being processed by 114dd925305SJim Harris * SCIL. This allows us to keep in flight CCBs in the queue so as to 115dd925305SJim Harris * maintain ordering (i.e. in case we retry an I/O and then find out 116dd925305SJim Harris * it needs to be retried again - it just keeps its same place in the 117dd925305SJim Harris * queue. 118dd925305SJim Harris */ 119dd925305SJim Harris union ccb * queued_ccb_in_progress; 120f11c7f63SJim Harris }; 121f11c7f63SJim Harris 122f11c7f63SJim Harris struct ISCI_DOMAIN { 123f11c7f63SJim Harris struct ISCI_CONTROLLER *controller; 124f11c7f63SJim Harris SCI_DOMAIN_HANDLE_T sci_object; 125f11c7f63SJim Harris uint8_t index; 12647c3b893SJim Harris struct ISCI_REMOTE_DEVICE *da_remote_device; 127f11c7f63SJim Harris }; 128f11c7f63SJim Harris 129f11c7f63SJim Harris struct ISCI_MEMORY 130f11c7f63SJim Harris { 131f11c7f63SJim Harris bus_addr_t physical_address; 132f11c7f63SJim Harris bus_dma_tag_t dma_tag; 133f11c7f63SJim Harris bus_dmamap_t dma_map; 134f11c7f63SJim Harris POINTER_UINT virtual_address; 135f11c7f63SJim Harris uint32_t size; 136f11c7f63SJim Harris int error; 137f11c7f63SJim Harris }; 138f11c7f63SJim Harris 139f11c7f63SJim Harris struct ISCI_INTERRUPT_INFO 140f11c7f63SJim Harris { 141f11c7f63SJim Harris SCIC_CONTROLLER_HANDLER_METHODS_T *handlers; 142f11c7f63SJim Harris void *interrupt_target_handle; 143f11c7f63SJim Harris struct resource *res; 144f11c7f63SJim Harris int rid; 145f11c7f63SJim Harris void *tag; 146f11c7f63SJim Harris 147f11c7f63SJim Harris }; 148f11c7f63SJim Harris 149500cbe13SJim Harris struct ISCI_PHY 15037274fc0SJim Harris { 151500cbe13SJim Harris struct cdev *cdev_fault; 152500cbe13SJim Harris struct cdev *cdev_locate; 15337274fc0SJim Harris SCI_CONTROLLER_HANDLE_T handle; 15437274fc0SJim Harris int index; 155500cbe13SJim Harris int led_fault; 156500cbe13SJim Harris int led_locate; 15737274fc0SJim Harris }; 15837274fc0SJim Harris 159f11c7f63SJim Harris struct ISCI_CONTROLLER 160f11c7f63SJim Harris { 161f11c7f63SJim Harris struct isci_softc *isci; 162f11c7f63SJim Harris uint8_t index; 163f11c7f63SJim Harris SCI_CONTROLLER_HANDLE_T scif_controller_handle; 164f11c7f63SJim Harris struct ISCI_DOMAIN domain[SCI_MAX_DOMAINS]; 165f11c7f63SJim Harris BOOL is_started; 1667ccd2036SJim Harris BOOL has_been_scanned; 167f11c7f63SJim Harris uint32_t initial_discovery_mask; 168f11c7f63SJim Harris BOOL is_frozen; 169dd925305SJim Harris BOOL release_queued_ccbs; 1703da2a91aSScott Long BOOL fail_on_task_timeout; 171f11c7f63SJim Harris uint8_t *remote_device_memory; 172f11c7f63SJim Harris struct ISCI_MEMORY cached_controller_memory; 173f11c7f63SJim Harris struct ISCI_MEMORY uncached_controller_memory; 174f11c7f63SJim Harris struct ISCI_MEMORY request_memory; 175f11c7f63SJim Harris bus_dma_tag_t buffer_dma_tag; 176f11c7f63SJim Harris struct mtx lock; 177f11c7f63SJim Harris struct cam_sim *sim; 178f11c7f63SJim Harris struct cam_path *path; 179f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE *remote_device[SCI_MAX_REMOTE_DEVICES]; 180f11c7f63SJim Harris void *timer_memory; 181f11c7f63SJim Harris SCIC_OEM_PARAMETERS_T oem_parameters; 182f11c7f63SJim Harris uint32_t oem_parameters_version; 183f11c7f63SJim Harris uint32_t queue_depth; 184f11c7f63SJim Harris uint32_t sim_queue_depth; 185f11c7f63SJim Harris SCI_FAST_LIST_T pending_device_reset_list; 186500cbe13SJim Harris struct ISCI_PHY phys[SCI_MAX_PHYS]; 187f11c7f63SJim Harris 188f11c7f63SJim Harris SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl; 189f11c7f63SJim Harris 190f11c7f63SJim Harris SCI_POOL_CREATE(remote_device_pool, struct ISCI_REMOTE_DEVICE *, SCI_MAX_REMOTE_DEVICES); 191f11c7f63SJim Harris SCI_POOL_CREATE(request_pool, struct ISCI_REQUEST *, SCI_MAX_IO_REQUESTS); 192f11c7f63SJim Harris SCI_POOL_CREATE(timer_pool, struct ISCI_TIMER *, SCI_MAX_TIMERS); 1933e0a9f1fSJim Harris SCI_POOL_CREATE(unmap_buffer_pool, void *, SCI_MAX_REMOTE_DEVICES); 194f11c7f63SJim Harris }; 195f11c7f63SJim Harris 196f11c7f63SJim Harris struct ISCI_REQUEST 197f11c7f63SJim Harris { 198f11c7f63SJim Harris SCI_CONTROLLER_HANDLE_T controller_handle; 199f11c7f63SJim Harris SCI_REMOTE_DEVICE_HANDLE_T remote_device_handle; 200f11c7f63SJim Harris bus_dma_tag_t dma_tag; 201f11c7f63SJim Harris bus_dmamap_t dma_map; 202f11c7f63SJim Harris SCI_PHYSICAL_ADDRESS physical_address; 203f11c7f63SJim Harris struct callout timer; 204f11c7f63SJim Harris }; 205f11c7f63SJim Harris 206f11c7f63SJim Harris struct ISCI_IO_REQUEST 207f11c7f63SJim Harris { 208f11c7f63SJim Harris struct ISCI_REQUEST parent; 209f11c7f63SJim Harris SCI_IO_REQUEST_HANDLE_T sci_object; 210f11c7f63SJim Harris union ccb *ccb; 211f11c7f63SJim Harris uint32_t num_segments; 212f11c7f63SJim Harris uint32_t current_sge_index; 213f11c7f63SJim Harris bus_dma_segment_t *sge; 214f11c7f63SJim Harris }; 215f11c7f63SJim Harris 216f11c7f63SJim Harris struct ISCI_TASK_REQUEST 217f11c7f63SJim Harris { 218f11c7f63SJim Harris struct ISCI_REQUEST parent; 219f11c7f63SJim Harris struct scsi_sense_data sense_data; 220f11c7f63SJim Harris SCI_TASK_REQUEST_HANDLE_T sci_object; 221f11c7f63SJim Harris union ccb *ccb; 222f11c7f63SJim Harris 223f11c7f63SJim Harris }; 224f11c7f63SJim Harris 225f11c7f63SJim Harris struct ISCI_PCI_BAR { 226f11c7f63SJim Harris 227f11c7f63SJim Harris bus_space_tag_t bus_tag; 228f11c7f63SJim Harris bus_space_handle_t bus_handle; 229f11c7f63SJim Harris int resource_id; 230f11c7f63SJim Harris struct resource *resource; 231f11c7f63SJim Harris 232f11c7f63SJim Harris }; 233f11c7f63SJim Harris 234f11c7f63SJim Harris /* 235f11c7f63SJim Harris * One of these per allocated PCI device. 236f11c7f63SJim Harris */ 237f11c7f63SJim Harris struct isci_softc { 238f11c7f63SJim Harris 239f11c7f63SJim Harris struct ISCI_PCI_BAR pci_bar[ISCI_NUM_PCI_BARS]; 240f11c7f63SJim Harris struct ISCI_CONTROLLER controllers[SCI_MAX_CONTROLLERS]; 241f11c7f63SJim Harris SCI_LIBRARY_HANDLE_T sci_library_handle; 242f11c7f63SJim Harris void * sci_library_memory; 243f11c7f63SJim Harris SCIC_CONTROLLER_HANDLER_METHODS_T handlers[4]; 244f11c7f63SJim Harris struct ISCI_INTERRUPT_INFO interrupt_info[4]; 245f11c7f63SJim Harris uint32_t controller_count; 246f11c7f63SJim Harris uint32_t num_interrupts; 247f11c7f63SJim Harris uint32_t coalesce_number; 248f11c7f63SJim Harris uint32_t coalesce_timeout; 249f11c7f63SJim Harris device_t device; 250f11c7f63SJim Harris SCI_PCI_COMMON_HEADER_T pci_common_header; 251f11c7f63SJim Harris BOOL oem_parameters_found; 252f11c7f63SJim Harris struct intr_config_hook config_hook; 253f11c7f63SJim Harris }; 254f11c7f63SJim Harris 255f11c7f63SJim Harris int isci_allocate_resources(device_t device); 256f11c7f63SJim Harris 257dad0dd21SKonstantin Belousov int isci_allocate_dma_buffer(device_t device, struct ISCI_CONTROLLER *lock, 258dad0dd21SKonstantin Belousov struct ISCI_MEMORY *memory); 259f11c7f63SJim Harris 260f11c7f63SJim Harris void isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device, 261f11c7f63SJim Harris union ccb *ccb); 262f11c7f63SJim Harris 263f11c7f63SJim Harris /** 264f11c7f63SJim Harris * Returns the negotiated link rate (in KB/s) for the associated 265f11c7f63SJim Harris * remote device. Used to fill out bitrate field for GET_TRANS_SETTINGS. 266f11c7f63SJim Harris * Will match the negotiated link rate for the lowest numbered local phy 267f11c7f63SJim Harris * in the port/domain containing this remote device. 268f11c7f63SJim Harris */ 269f11c7f63SJim Harris uint32_t isci_remote_device_get_bitrate( 270f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE *remote_device); 271f11c7f63SJim Harris 272f11c7f63SJim Harris void isci_remote_device_freeze_lun_queue( 273f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun); 274f11c7f63SJim Harris 275f11c7f63SJim Harris void isci_remote_device_release_lun_queue( 276f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun); 277f11c7f63SJim Harris 278f11c7f63SJim Harris void isci_remote_device_release_device_queue( 279f11c7f63SJim Harris struct ISCI_REMOTE_DEVICE * remote_device); 280f11c7f63SJim Harris 281f11c7f63SJim Harris void isci_request_construct(struct ISCI_REQUEST *request, 282f11c7f63SJim Harris SCI_CONTROLLER_HANDLE_T scif_controller_handle, 283f11c7f63SJim Harris bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address); 284f11c7f63SJim Harris 285f11c7f63SJim Harris #define isci_io_request_get_max_io_size() \ 286f11c7f63SJim Harris ((SCI_MAX_SCATTER_GATHER_ELEMENTS - 1) * PAGE_SIZE) 287f11c7f63SJim Harris 288f11c7f63SJim Harris #define isci_task_request_get_object_size() \ 289f11c7f63SJim Harris (sizeof(struct ISCI_TASK_REQUEST) + scif_task_request_get_object_size()) 290f11c7f63SJim Harris 291f11c7f63SJim Harris #define isci_io_request_get_object_size() \ 292f11c7f63SJim Harris (sizeof(struct ISCI_IO_REQUEST) + scif_io_request_get_object_size()) 293f11c7f63SJim Harris 294f11c7f63SJim Harris #define isci_request_get_object_size() \ 295f11c7f63SJim Harris max( \ 296f11c7f63SJim Harris isci_task_request_get_object_size(), \ 297f11c7f63SJim Harris isci_io_request_get_object_size() \ 298f11c7f63SJim Harris ) 299f11c7f63SJim Harris 300f11c7f63SJim Harris 301f11c7f63SJim Harris void isci_io_request_execute_scsi_io(union ccb *ccb, 302f11c7f63SJim Harris struct ISCI_CONTROLLER *controller); 303f11c7f63SJim Harris 304f11c7f63SJim Harris void isci_io_request_execute_smp_io( 305f11c7f63SJim Harris union ccb *ccb, struct ISCI_CONTROLLER *controller); 306f11c7f63SJim Harris 307f11c7f63SJim Harris void isci_io_request_timeout(void *); 308f11c7f63SJim Harris 309f11c7f63SJim Harris void isci_get_oem_parameters(struct isci_softc *isci); 310f11c7f63SJim Harris 311f11c7f63SJim Harris void isci_io_request_complete( 312f11c7f63SJim Harris SCI_CONTROLLER_HANDLE_T scif_controller, 313f11c7f63SJim Harris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 314f11c7f63SJim Harris struct ISCI_IO_REQUEST * isci_request, SCI_IO_STATUS completion_status); 315f11c7f63SJim Harris 316f11c7f63SJim Harris void isci_task_request_complete( 317f11c7f63SJim Harris SCI_CONTROLLER_HANDLE_T scif_controller, 318f11c7f63SJim Harris SCI_REMOTE_DEVICE_HANDLE_T remote_device, 319f11c7f63SJim Harris SCI_TASK_REQUEST_HANDLE_T io_request, SCI_TASK_STATUS completion_status); 320f11c7f63SJim Harris 321f11c7f63SJim Harris void isci_sysctl_initialize(struct isci_softc *isci); 322f11c7f63SJim Harris 323f11c7f63SJim Harris void isci_controller_construct(struct ISCI_CONTROLLER *controller, 324f11c7f63SJim Harris struct isci_softc *isci); 325f11c7f63SJim Harris 326f11c7f63SJim Harris SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller); 327f11c7f63SJim Harris 328f11c7f63SJim Harris int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller); 329f11c7f63SJim Harris 330f11c7f63SJim Harris void isci_controller_domain_discovery_complete( 331f11c7f63SJim Harris struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain); 332f11c7f63SJim Harris 333f11c7f63SJim Harris int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller); 334f11c7f63SJim Harris 335f11c7f63SJim Harris void isci_controller_start(void *controller); 336f11c7f63SJim Harris 337dd925305SJim Harris void isci_controller_release_queued_ccbs(struct ISCI_CONTROLLER *controller); 338dd925305SJim Harris 339f11c7f63SJim Harris void isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index, 340f11c7f63SJim Harris struct ISCI_CONTROLLER *controller); 341f11c7f63SJim Harris 342f11c7f63SJim Harris void isci_interrupt_setup(struct isci_softc *isci); 343f11c7f63SJim Harris void isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller); 344f11c7f63SJim Harris 345f11c7f63SJim Harris void isci_log_message(uint32_t verbosity, char *log_message_prefix, 346f11c7f63SJim Harris char *log_message, ...); 347f11c7f63SJim Harris 348f11c7f63SJim Harris extern uint32_t g_isci_debug_level; 349dd925305SJim Harris 350dd925305SJim Harris #endif /* #ifndef _ISCI_H */ 351