1230557Sjimharris/*- 2230557Sjimharris * BSD LICENSE 3230557Sjimharris * 4230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 5230557Sjimharris * All rights reserved. 6230557Sjimharris * 7230557Sjimharris * Redistribution and use in source and binary forms, with or without 8230557Sjimharris * modification, are permitted provided that the following conditions 9230557Sjimharris * are met: 10230557Sjimharris * 11230557Sjimharris * * Redistributions of source code must retain the above copyright 12230557Sjimharris * notice, this list of conditions and the following disclaimer. 13230557Sjimharris * * Redistributions in binary form must reproduce the above copyright 14230557Sjimharris * notice, this list of conditions and the following disclaimer in 15230557Sjimharris * the documentation and/or other materials provided with the 16230557Sjimharris * distribution. 17230557Sjimharris * 18230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29230557Sjimharris */ 30230557Sjimharris 31230557Sjimharris#include <sys/cdefs.h> 32230557Sjimharris__FBSDID("$FreeBSD$"); 33230557Sjimharris 34230557Sjimharris#include <dev/isci/isci.h> 35230557Sjimharris 36230557Sjimharris#include <sys/sysctl.h> 37230557Sjimharris#include <sys/malloc.h> 38230557Sjimharris 39230557Sjimharris#include <cam/cam_periph.h> 40230557Sjimharris 41240965Sjimharris#include <dev/led/led.h> 42240965Sjimharris 43230557Sjimharris#include <dev/pci/pcireg.h> 44230557Sjimharris#include <dev/pci/pcivar.h> 45230557Sjimharris 46230557Sjimharris#include <dev/isci/scil/scic_logger.h> 47230557Sjimharris#include <dev/isci/scil/scic_library.h> 48240965Sjimharris#include <dev/isci/scil/scic_sgpio.h> 49230557Sjimharris#include <dev/isci/scil/scic_user_callback.h> 50230557Sjimharris 51230557Sjimharris#include <dev/isci/scil/scif_controller.h> 52230557Sjimharris#include <dev/isci/scil/scif_library.h> 53230557Sjimharris#include <dev/isci/scil/scif_logger.h> 54230557Sjimharris#include <dev/isci/scil/scif_user_callback.h> 55230557Sjimharris 56230557SjimharrisMALLOC_DEFINE(M_ISCI, "isci", "isci driver memory allocations"); 57230557Sjimharris 58230557Sjimharrisstruct isci_softc *g_isci; 59230557Sjimharrisuint32_t g_isci_debug_level = 0; 60230557Sjimharris 61230557Sjimharrisstatic int isci_probe(device_t); 62230557Sjimharrisstatic int isci_attach(device_t); 63230557Sjimharrisstatic int isci_detach(device_t); 64230557Sjimharris 65230557Sjimharrisint isci_initialize(struct isci_softc *isci); 66230557Sjimharris 67230557Sjimharrisvoid isci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg, 68230557Sjimharris int nseg, int error); 69230557Sjimharris 70230557Sjimharrisstatic devclass_t isci_devclass; 71230557Sjimharris 72230557Sjimharrisstatic device_method_t isci_pci_methods[] = { 73230557Sjimharris /* Device interface */ 74230557Sjimharris DEVMETHOD(device_probe, isci_probe), 75230557Sjimharris DEVMETHOD(device_attach, isci_attach), 76230557Sjimharris DEVMETHOD(device_detach, isci_detach), 77230557Sjimharris { 0, 0 } 78230557Sjimharris}; 79230557Sjimharris 80230557Sjimharrisstatic driver_t isci_pci_driver = { 81230557Sjimharris "isci", 82230557Sjimharris isci_pci_methods, 83230557Sjimharris sizeof(struct isci_softc), 84230557Sjimharris}; 85230557Sjimharris 86230557SjimharrisDRIVER_MODULE(isci, pci, isci_pci_driver, isci_devclass, 0, 0); 87256125SkibMODULE_DEPEND(isci, cam, 1, 1, 1); 88230557Sjimharris 89230557Sjimharrisstatic struct _pcsid 90230557Sjimharris{ 91230557Sjimharris u_int32_t type; 92230557Sjimharris const char *desc; 93230557Sjimharris} pci_ids[] = { 94230557Sjimharris { 0x1d608086, "Intel(R) C600 Series Chipset SAS Controller" }, 95230557Sjimharris { 0x1d618086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" }, 96230557Sjimharris { 0x1d628086, "Intel(R) C600 Series Chipset SAS Controller" }, 97230557Sjimharris { 0x1d638086, "Intel(R) C600 Series Chipset SAS Controller" }, 98230557Sjimharris { 0x1d648086, "Intel(R) C600 Series Chipset SAS Controller" }, 99230557Sjimharris { 0x1d658086, "Intel(R) C600 Series Chipset SAS Controller" }, 100230557Sjimharris { 0x1d668086, "Intel(R) C600 Series Chipset SAS Controller" }, 101230557Sjimharris { 0x1d678086, "Intel(R) C600 Series Chipset SAS Controller" }, 102230557Sjimharris { 0x1d688086, "Intel(R) C600 Series Chipset SAS Controller" }, 103230557Sjimharris { 0x1d698086, "Intel(R) C600 Series Chipset SAS Controller" }, 104230557Sjimharris { 0x1d6a8086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" }, 105232225Ssbruno { 0x1d6b8086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" }, 106232225Ssbruno { 0x1d6c8086, "Intel(R) C600 Series Chipset SAS Controller" }, 107232225Ssbruno { 0x1d6d8086, "Intel(R) C600 Series Chipset SAS Controller" }, 108232225Ssbruno { 0x1d6e8086, "Intel(R) C600 Series Chipset SAS Controller" }, 109232225Ssbruno { 0x1d6f8086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" }, 110230557Sjimharris { 0x00000000, NULL } 111230557Sjimharris}; 112230557Sjimharris 113230557Sjimharrisstatic int 114230557Sjimharrisisci_probe (device_t device) 115230557Sjimharris{ 116230557Sjimharris u_int32_t type = pci_get_devid(device); 117230557Sjimharris struct _pcsid *ep = pci_ids; 118230557Sjimharris 119230557Sjimharris while (ep->type && ep->type != type) 120230557Sjimharris ++ep; 121230557Sjimharris 122230557Sjimharris if (ep->desc) 123230557Sjimharris { 124230557Sjimharris device_set_desc(device, ep->desc); 125232225Ssbruno return (BUS_PROBE_DEFAULT); 126230557Sjimharris } 127230557Sjimharris else 128230557Sjimharris return (ENXIO); 129230557Sjimharris} 130230557Sjimharris 131230557Sjimharrisstatic int 132230557Sjimharrisisci_allocate_pci_memory(struct isci_softc *isci) 133230557Sjimharris{ 134230557Sjimharris int i; 135230557Sjimharris 136230557Sjimharris for (i = 0; i < ISCI_NUM_PCI_BARS; i++) 137230557Sjimharris { 138230557Sjimharris struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i]; 139230557Sjimharris 140230557Sjimharris pci_bar->resource_id = PCIR_BAR(i*2); 141230557Sjimharris pci_bar->resource = bus_alloc_resource(isci->device, 142230557Sjimharris SYS_RES_MEMORY, &pci_bar->resource_id, 0, ~0, 1, 143230557Sjimharris RF_ACTIVE); 144230557Sjimharris 145230557Sjimharris if(pci_bar->resource == NULL) 146230557Sjimharris isci_log_message(0, "ISCI", 147230557Sjimharris "unable to allocate pci resource\n"); 148230557Sjimharris else { 149230557Sjimharris pci_bar->bus_tag = rman_get_bustag(pci_bar->resource); 150230557Sjimharris pci_bar->bus_handle = 151230557Sjimharris rman_get_bushandle(pci_bar->resource); 152230557Sjimharris } 153230557Sjimharris } 154230557Sjimharris 155230557Sjimharris return (0); 156230557Sjimharris} 157230557Sjimharris 158230557Sjimharrisstatic int 159230557Sjimharrisisci_attach(device_t device) 160230557Sjimharris{ 161230557Sjimharris int error; 162230557Sjimharris struct isci_softc *isci = DEVICE2SOFTC(device); 163230557Sjimharris 164230557Sjimharris g_isci = isci; 165230557Sjimharris isci->device = device; 166230557Sjimharris 167230557Sjimharris isci_allocate_pci_memory(isci); 168230557Sjimharris 169230557Sjimharris error = isci_initialize(isci); 170230557Sjimharris 171230557Sjimharris if (error) 172230557Sjimharris { 173230557Sjimharris isci_detach(device); 174230557Sjimharris return (error); 175230557Sjimharris } 176230557Sjimharris 177230557Sjimharris isci_interrupt_setup(isci); 178230557Sjimharris isci_sysctl_initialize(isci); 179230557Sjimharris 180230557Sjimharris return (0); 181230557Sjimharris} 182230557Sjimharris 183230557Sjimharrisstatic int 184230557Sjimharrisisci_detach(device_t device) 185230557Sjimharris{ 186230557Sjimharris struct isci_softc *isci = DEVICE2SOFTC(device); 187240965Sjimharris int i, phy; 188230557Sjimharris 189230557Sjimharris for (i = 0; i < isci->controller_count; i++) { 190230557Sjimharris struct ISCI_CONTROLLER *controller = &isci->controllers[i]; 191230557Sjimharris SCI_STATUS status; 192239545Sjimharris void *unmap_buffer; 193230557Sjimharris 194230557Sjimharris if (controller->scif_controller_handle != NULL) { 195230557Sjimharris scic_controller_disable_interrupts( 196230557Sjimharris scif_controller_get_scic_handle(controller->scif_controller_handle)); 197230557Sjimharris 198230557Sjimharris mtx_lock(&controller->lock); 199230557Sjimharris status = scif_controller_stop(controller->scif_controller_handle, 0); 200230557Sjimharris mtx_unlock(&controller->lock); 201230557Sjimharris 202230557Sjimharris while (controller->is_started == TRUE) { 203230557Sjimharris /* Now poll for interrupts until the controller stop complete 204230557Sjimharris * callback is received. 205230557Sjimharris */ 206230557Sjimharris mtx_lock(&controller->lock); 207230557Sjimharris isci_interrupt_poll_handler(controller); 208230557Sjimharris mtx_unlock(&controller->lock); 209230557Sjimharris pause("isci", 1); 210230557Sjimharris } 211230557Sjimharris 212230557Sjimharris if(controller->sim != NULL) { 213230557Sjimharris mtx_lock(&controller->lock); 214230557Sjimharris xpt_free_path(controller->path); 215230557Sjimharris xpt_bus_deregister(cam_sim_path(controller->sim)); 216230557Sjimharris cam_sim_free(controller->sim, TRUE); 217230557Sjimharris mtx_unlock(&controller->lock); 218230557Sjimharris } 219230557Sjimharris } 220230557Sjimharris 221230557Sjimharris if (controller->timer_memory != NULL) 222230557Sjimharris free(controller->timer_memory, M_ISCI); 223230557Sjimharris 224230557Sjimharris if (controller->remote_device_memory != NULL) 225230557Sjimharris free(controller->remote_device_memory, M_ISCI); 226239545Sjimharris 227241403Sjimharris for (phy = 0; phy < SCI_MAX_PHYS; phy++) { 228241403Sjimharris if (controller->phys[phy].cdev_fault) 229241403Sjimharris led_destroy(controller->phys[phy].cdev_fault); 230240965Sjimharris 231241403Sjimharris if (controller->phys[phy].cdev_locate) 232241403Sjimharris led_destroy(controller->phys[phy].cdev_locate); 233241403Sjimharris } 234241403Sjimharris 235239545Sjimharris while (1) { 236239545Sjimharris sci_pool_get(controller->unmap_buffer_pool, unmap_buffer); 237239545Sjimharris if (unmap_buffer == NULL) 238239545Sjimharris break; 239239545Sjimharris contigfree(unmap_buffer, PAGE_SIZE, M_ISCI); 240239545Sjimharris } 241230557Sjimharris } 242230557Sjimharris 243230557Sjimharris /* The SCIF controllers have been stopped, so we can now 244230557Sjimharris * free the SCI library memory. 245230557Sjimharris */ 246230557Sjimharris if (isci->sci_library_memory != NULL) 247230557Sjimharris free(isci->sci_library_memory, M_ISCI); 248230557Sjimharris 249230557Sjimharris for (i = 0; i < ISCI_NUM_PCI_BARS; i++) 250230557Sjimharris { 251230557Sjimharris struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i]; 252230557Sjimharris 253230557Sjimharris if (pci_bar->resource != NULL) 254230557Sjimharris bus_release_resource(device, SYS_RES_MEMORY, 255230557Sjimharris pci_bar->resource_id, pci_bar->resource); 256230557Sjimharris } 257230557Sjimharris 258230557Sjimharris for (i = 0; i < isci->num_interrupts; i++) 259230557Sjimharris { 260230557Sjimharris struct ISCI_INTERRUPT_INFO *interrupt_info; 261230557Sjimharris 262230557Sjimharris interrupt_info = &isci->interrupt_info[i]; 263230557Sjimharris 264230557Sjimharris if(interrupt_info->tag != NULL) 265230557Sjimharris bus_teardown_intr(device, interrupt_info->res, 266230557Sjimharris interrupt_info->tag); 267230557Sjimharris 268230557Sjimharris if(interrupt_info->res != NULL) 269230557Sjimharris bus_release_resource(device, SYS_RES_IRQ, 270230557Sjimharris rman_get_rid(interrupt_info->res), 271230557Sjimharris interrupt_info->res); 272230557Sjimharris 273230557Sjimharris pci_release_msi(device); 274230557Sjimharris } 275230557Sjimharris 276230557Sjimharris return (0); 277230557Sjimharris} 278230557Sjimharris 279230557Sjimharrisint 280230557Sjimharrisisci_initialize(struct isci_softc *isci) 281230557Sjimharris{ 282230557Sjimharris int error; 283230557Sjimharris uint32_t status = 0; 284230557Sjimharris uint32_t library_object_size; 285230557Sjimharris uint32_t verbosity_mask; 286230557Sjimharris uint32_t scic_log_object_mask; 287230557Sjimharris uint32_t scif_log_object_mask; 288230557Sjimharris uint8_t *header_buffer; 289230557Sjimharris 290230557Sjimharris library_object_size = scif_library_get_object_size(SCI_MAX_CONTROLLERS); 291230557Sjimharris 292230557Sjimharris isci->sci_library_memory = 293230557Sjimharris malloc(library_object_size, M_ISCI, M_NOWAIT | M_ZERO ); 294230557Sjimharris 295230557Sjimharris isci->sci_library_handle = scif_library_construct( 296230557Sjimharris isci->sci_library_memory, SCI_MAX_CONTROLLERS); 297230557Sjimharris 298230557Sjimharris sci_object_set_association( isci->sci_library_handle, (void *)isci); 299230557Sjimharris 300230557Sjimharris verbosity_mask = (1<<SCI_LOG_VERBOSITY_ERROR) | 301230557Sjimharris (1<<SCI_LOG_VERBOSITY_WARNING) | (1<<SCI_LOG_VERBOSITY_INFO) | 302230557Sjimharris (1<<SCI_LOG_VERBOSITY_TRACE); 303230557Sjimharris 304230557Sjimharris scic_log_object_mask = 0xFFFFFFFF; 305230557Sjimharris scic_log_object_mask &= ~SCIC_LOG_OBJECT_COMPLETION_QUEUE; 306230557Sjimharris scic_log_object_mask &= ~SCIC_LOG_OBJECT_SSP_IO_REQUEST; 307230557Sjimharris scic_log_object_mask &= ~SCIC_LOG_OBJECT_STP_IO_REQUEST; 308230557Sjimharris scic_log_object_mask &= ~SCIC_LOG_OBJECT_SMP_IO_REQUEST; 309230557Sjimharris scic_log_object_mask &= ~SCIC_LOG_OBJECT_CONTROLLER; 310230557Sjimharris 311230557Sjimharris scif_log_object_mask = 0xFFFFFFFF; 312230557Sjimharris scif_log_object_mask &= ~SCIF_LOG_OBJECT_CONTROLLER; 313230557Sjimharris scif_log_object_mask &= ~SCIF_LOG_OBJECT_IO_REQUEST; 314230557Sjimharris 315230557Sjimharris TUNABLE_INT_FETCH("hw.isci.debug_level", &g_isci_debug_level); 316230557Sjimharris 317230557Sjimharris sci_logger_enable(sci_object_get_logger(isci->sci_library_handle), 318230557Sjimharris scif_log_object_mask, verbosity_mask); 319230557Sjimharris 320230557Sjimharris sci_logger_enable(sci_object_get_logger( 321230557Sjimharris scif_library_get_scic_handle(isci->sci_library_handle)), 322230557Sjimharris scic_log_object_mask, verbosity_mask); 323230557Sjimharris 324230557Sjimharris header_buffer = (uint8_t *)&isci->pci_common_header; 325230557Sjimharris for (uint8_t i = 0; i < sizeof(isci->pci_common_header); i++) 326230557Sjimharris header_buffer[i] = pci_read_config(isci->device, i, 1); 327230557Sjimharris 328230557Sjimharris scic_library_set_pci_info( 329230557Sjimharris scif_library_get_scic_handle(isci->sci_library_handle), 330230557Sjimharris &isci->pci_common_header); 331230557Sjimharris 332230557Sjimharris isci->oem_parameters_found = FALSE; 333230557Sjimharris 334230557Sjimharris isci_get_oem_parameters(isci); 335230557Sjimharris 336230557Sjimharris /* trigger interrupt if 32 completions occur before timeout expires */ 337230557Sjimharris isci->coalesce_number = 32; 338230557Sjimharris 339230557Sjimharris /* trigger interrupt if 2 microseconds elapse after a completion occurs, 340230557Sjimharris * regardless if "coalesce_number" completions have occurred 341230557Sjimharris */ 342230557Sjimharris isci->coalesce_timeout = 2; 343230557Sjimharris 344230557Sjimharris isci->controller_count = scic_library_get_pci_device_controller_count( 345230557Sjimharris scif_library_get_scic_handle(isci->sci_library_handle)); 346230557Sjimharris 347230557Sjimharris for (int index = 0; index < isci->controller_count; index++) { 348230557Sjimharris struct ISCI_CONTROLLER *controller = &isci->controllers[index]; 349230557Sjimharris SCI_CONTROLLER_HANDLE_T scif_controller_handle; 350230557Sjimharris 351230557Sjimharris controller->index = index; 352230557Sjimharris isci_controller_construct(controller, isci); 353230557Sjimharris 354230557Sjimharris scif_controller_handle = controller->scif_controller_handle; 355230557Sjimharris 356230557Sjimharris status = isci_controller_initialize(controller); 357230557Sjimharris 358230557Sjimharris if(status != SCI_SUCCESS) { 359230557Sjimharris isci_log_message(0, "ISCI", 360230557Sjimharris "isci_controller_initialize FAILED: %x\n", 361230557Sjimharris status); 362230557Sjimharris return (status); 363230557Sjimharris } 364230557Sjimharris 365230557Sjimharris error = isci_controller_allocate_memory(controller); 366230557Sjimharris 367230557Sjimharris if (error != 0) 368230557Sjimharris return (error); 369230557Sjimharris 370230557Sjimharris scif_controller_set_interrupt_coalescence( 371230557Sjimharris scif_controller_handle, isci->coalesce_number, 372230557Sjimharris isci->coalesce_timeout); 373230557Sjimharris } 374230557Sjimharris 375230557Sjimharris /* FreeBSD provides us a hook to ensure we get a chance to start 376230557Sjimharris * our controllers and complete initial domain discovery before 377230557Sjimharris * it searches for the boot device. Once we're done, we'll 378230557Sjimharris * disestablish the hook, signaling the kernel that is can proceed 379230557Sjimharris * with the boot process. 380230557Sjimharris */ 381230557Sjimharris isci->config_hook.ich_func = &isci_controller_start; 382230557Sjimharris isci->config_hook.ich_arg = &isci->controllers[0]; 383230557Sjimharris 384230557Sjimharris if (config_intrhook_establish(&isci->config_hook) != 0) 385230557Sjimharris isci_log_message(0, "ISCI", 386230557Sjimharris "config_intrhook_establish failed!\n"); 387230557Sjimharris 388230557Sjimharris return (status); 389230557Sjimharris} 390230557Sjimharris 391230557Sjimharrisvoid 392230557Sjimharrisisci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg, 393230557Sjimharris int nseg, int error) 394230557Sjimharris{ 395230557Sjimharris struct ISCI_MEMORY *memory = (struct ISCI_MEMORY *)arg; 396230557Sjimharris 397230557Sjimharris memory->error = error; 398230557Sjimharris 399230557Sjimharris if (nseg != 1 || error != 0) 400230557Sjimharris isci_log_message(0, "ISCI", 401230557Sjimharris "Failed to allocate physically contiguous memory!\n"); 402230557Sjimharris else 403230557Sjimharris memory->physical_address = seg->ds_addr; 404230557Sjimharris} 405230557Sjimharris 406230557Sjimharrisint 407230557Sjimharrisisci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory) 408230557Sjimharris{ 409230557Sjimharris uint32_t status; 410230557Sjimharris 411230557Sjimharris status = bus_dma_tag_create(bus_get_dma_tag(device), 412230557Sjimharris 0x40 /* cacheline alignment */, 0x0, BUS_SPACE_MAXADDR, 413230557Sjimharris BUS_SPACE_MAXADDR, NULL, NULL, memory->size, 414230557Sjimharris 0x1 /* we want physically contiguous */, 415230557Sjimharris memory->size, 0, NULL, NULL, &memory->dma_tag); 416230557Sjimharris 417230557Sjimharris if(status == ENOMEM) { 418230557Sjimharris isci_log_message(0, "ISCI", "bus_dma_tag_create failed\n"); 419230557Sjimharris return (status); 420230557Sjimharris } 421230557Sjimharris 422230557Sjimharris status = bus_dmamem_alloc(memory->dma_tag, 423230557Sjimharris (void **)&memory->virtual_address, BUS_DMA_ZERO, &memory->dma_map); 424230557Sjimharris 425230557Sjimharris if(status == ENOMEM) 426230557Sjimharris { 427230557Sjimharris isci_log_message(0, "ISCI", "bus_dmamem_alloc failed\n"); 428230557Sjimharris return (status); 429230557Sjimharris } 430230557Sjimharris 431230557Sjimharris status = bus_dmamap_load(memory->dma_tag, memory->dma_map, 432230557Sjimharris (void *)memory->virtual_address, memory->size, 433230557Sjimharris isci_allocate_dma_buffer_callback, memory, 0); 434230557Sjimharris 435230557Sjimharris if(status == EINVAL) 436230557Sjimharris { 437230557Sjimharris isci_log_message(0, "ISCI", "bus_dmamap_load failed\n"); 438230557Sjimharris return (status); 439230557Sjimharris } 440230557Sjimharris 441230557Sjimharris return (0); 442230557Sjimharris} 443230557Sjimharris 444230557Sjimharris/** 445230557Sjimharris * @brief This callback method asks the user to associate the supplied 446230557Sjimharris * lock with an operating environment specific locking construct. 447230557Sjimharris * 448230557Sjimharris * @param[in] controller This parameter specifies the controller with 449230557Sjimharris * which this lock is to be associated. 450230557Sjimharris * @param[in] lock This parameter specifies the lock for which the 451230557Sjimharris * user should associate an operating environment specific 452230557Sjimharris * locking object. 453230557Sjimharris * 454230557Sjimharris * @see The SCI_LOCK_LEVEL enumeration for more information. 455230557Sjimharris * 456230557Sjimharris * @return none. 457230557Sjimharris */ 458230557Sjimharrisvoid 459230557Sjimharrisscif_cb_lock_associate(SCI_CONTROLLER_HANDLE_T controller, 460230557Sjimharris SCI_LOCK_HANDLE_T lock) 461230557Sjimharris{ 462230557Sjimharris 463230557Sjimharris} 464230557Sjimharris 465230557Sjimharris/** 466230557Sjimharris * @brief This callback method asks the user to de-associate the supplied 467230557Sjimharris * lock with an operating environment specific locking construct. 468230557Sjimharris * 469230557Sjimharris * @param[in] controller This parameter specifies the controller with 470230557Sjimharris * which this lock is to be de-associated. 471230557Sjimharris * @param[in] lock This parameter specifies the lock for which the 472230557Sjimharris * user should de-associate an operating environment specific 473230557Sjimharris * locking object. 474230557Sjimharris * 475230557Sjimharris * @see The SCI_LOCK_LEVEL enumeration for more information. 476230557Sjimharris * 477230557Sjimharris * @return none. 478230557Sjimharris */ 479230557Sjimharrisvoid 480230557Sjimharrisscif_cb_lock_disassociate(SCI_CONTROLLER_HANDLE_T controller, 481230557Sjimharris SCI_LOCK_HANDLE_T lock) 482230557Sjimharris{ 483230557Sjimharris 484230557Sjimharris} 485230557Sjimharris 486230557Sjimharris 487230557Sjimharris/** 488230557Sjimharris * @brief This callback method asks the user to acquire/get the lock. 489230557Sjimharris * This method should pend until the lock has been acquired. 490230557Sjimharris * 491230557Sjimharris * @param[in] controller This parameter specifies the controller with 492230557Sjimharris * which this lock is associated. 493230557Sjimharris * @param[in] lock This parameter specifies the lock to be acquired. 494230557Sjimharris * 495230557Sjimharris * @return none 496230557Sjimharris */ 497230557Sjimharrisvoid 498230557Sjimharrisscif_cb_lock_acquire(SCI_CONTROLLER_HANDLE_T controller, 499230557Sjimharris SCI_LOCK_HANDLE_T lock) 500230557Sjimharris{ 501230557Sjimharris 502230557Sjimharris} 503230557Sjimharris 504230557Sjimharris/** 505230557Sjimharris * @brief This callback method asks the user to release a lock. 506230557Sjimharris * 507230557Sjimharris * @param[in] controller This parameter specifies the controller with 508230557Sjimharris * which this lock is associated. 509230557Sjimharris * @param[in] lock This parameter specifies the lock to be released. 510230557Sjimharris * 511230557Sjimharris * @return none 512230557Sjimharris */ 513230557Sjimharrisvoid 514230557Sjimharrisscif_cb_lock_release(SCI_CONTROLLER_HANDLE_T controller, 515230557Sjimharris SCI_LOCK_HANDLE_T lock) 516230557Sjimharris{ 517230557Sjimharris} 518230557Sjimharris 519230557Sjimharris/** 520230557Sjimharris * @brief This callback method creates an OS specific deferred task 521230557Sjimharris * for internal usage. The handler to deferred task is stored by OS 522230557Sjimharris * driver. 523230557Sjimharris * 524230557Sjimharris * @param[in] controller This parameter specifies the controller object 525230557Sjimharris * with which this callback is associated. 526230557Sjimharris * 527230557Sjimharris * @return none 528230557Sjimharris */ 529230557Sjimharrisvoid 530230557Sjimharrisscif_cb_start_internal_io_task_create(SCI_CONTROLLER_HANDLE_T controller) 531230557Sjimharris{ 532230557Sjimharris 533230557Sjimharris} 534230557Sjimharris 535230557Sjimharris/** 536230557Sjimharris * @brief This callback method schedules a OS specific deferred task. 537230557Sjimharris * 538230557Sjimharris * @param[in] controller This parameter specifies the controller 539230557Sjimharris * object with which this callback is associated. 540230557Sjimharris * @param[in] start_internal_io_task_routine This parameter specifies the 541230557Sjimharris * sci start_internal_io routine. 542230557Sjimharris * @param[in] context This parameter specifies a handle to a parameter 543230557Sjimharris * that will be passed into the "start_internal_io_task_routine" 544230557Sjimharris * when it is invoked. 545230557Sjimharris * 546230557Sjimharris * @return none 547230557Sjimharris */ 548230557Sjimharrisvoid 549230557Sjimharrisscif_cb_start_internal_io_task_schedule(SCI_CONTROLLER_HANDLE_T scif_controller, 550230557Sjimharris FUNCPTR start_internal_io_task_routine, void *context) 551230557Sjimharris{ 552230557Sjimharris /** @todo Use FreeBSD tasklet to defer this routine to a later time, 553230557Sjimharris * rather than calling the routine inline. 554230557Sjimharris */ 555230557Sjimharris SCI_START_INTERNAL_IO_ROUTINE sci_start_internal_io_routine = 556230557Sjimharris (SCI_START_INTERNAL_IO_ROUTINE)start_internal_io_task_routine; 557230557Sjimharris 558230557Sjimharris sci_start_internal_io_routine(context); 559230557Sjimharris} 560230557Sjimharris 561230557Sjimharris/** 562230557Sjimharris * @brief In this method the user must write to PCI memory via access. 563230557Sjimharris * This method is used for access to memory space and IO space. 564230557Sjimharris * 565230557Sjimharris * @param[in] controller The controller for which to read a DWORD. 566230557Sjimharris * @param[in] address This parameter depicts the address into 567230557Sjimharris * which to write. 568230557Sjimharris * @param[out] write_value This parameter depicts the value being written 569230557Sjimharris * into the PCI memory location. 570230557Sjimharris * 571230557Sjimharris * @todo These PCI memory access calls likely needs to be optimized into macros? 572230557Sjimharris */ 573230557Sjimharrisvoid 574230557Sjimharrisscic_cb_pci_write_dword(SCI_CONTROLLER_HANDLE_T scic_controller, 575230557Sjimharris void *address, uint32_t write_value) 576230557Sjimharris{ 577230557Sjimharris SCI_CONTROLLER_HANDLE_T scif_controller = 578230557Sjimharris (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(scic_controller); 579230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 580230557Sjimharris (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller); 581230557Sjimharris struct isci_softc *isci = isci_controller->isci; 582230557Sjimharris uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28); 583230557Sjimharris bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF); 584230557Sjimharris 585230557Sjimharris bus_space_write_4(isci->pci_bar[bar].bus_tag, 586230557Sjimharris isci->pci_bar[bar].bus_handle, offset, write_value); 587230557Sjimharris} 588230557Sjimharris 589230557Sjimharris/** 590230557Sjimharris * @brief In this method the user must read from PCI memory via access. 591230557Sjimharris * This method is used for access to memory space and IO space. 592230557Sjimharris * 593230557Sjimharris * @param[in] controller The controller for which to read a DWORD. 594230557Sjimharris * @param[in] address This parameter depicts the address from 595230557Sjimharris * which to read. 596230557Sjimharris * 597230557Sjimharris * @return The value being returned from the PCI memory location. 598230557Sjimharris * 599230557Sjimharris * @todo This PCI memory access calls likely need to be optimized into macro? 600230557Sjimharris */ 601230557Sjimharrisuint32_t 602230557Sjimharrisscic_cb_pci_read_dword(SCI_CONTROLLER_HANDLE_T scic_controller, void *address) 603230557Sjimharris{ 604230557Sjimharris SCI_CONTROLLER_HANDLE_T scif_controller = 605230557Sjimharris (SCI_CONTROLLER_HANDLE_T)sci_object_get_association(scic_controller); 606230557Sjimharris struct ISCI_CONTROLLER *isci_controller = 607230557Sjimharris (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller); 608230557Sjimharris struct isci_softc *isci = isci_controller->isci; 609230557Sjimharris uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28); 610230557Sjimharris bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF); 611230557Sjimharris 612230557Sjimharris return (bus_space_read_4(isci->pci_bar[bar].bus_tag, 613230557Sjimharris isci->pci_bar[bar].bus_handle, offset)); 614230557Sjimharris} 615230557Sjimharris 616230557Sjimharris/** 617230557Sjimharris * @brief This method is called when the core requires the OS driver 618230557Sjimharris * to stall execution. This method is utilized during initialization 619230557Sjimharris * or non-performance paths only. 620230557Sjimharris * 621230557Sjimharris * @param[in] microseconds This parameter specifies the number of 622230557Sjimharris * microseconds for which to stall. The operating system driver 623230557Sjimharris * is allowed to round this value up where necessary. 624230557Sjimharris * 625230557Sjimharris * @return none. 626230557Sjimharris */ 627230557Sjimharrisvoid 628230557Sjimharrisscic_cb_stall_execution(uint32_t microseconds) 629230557Sjimharris{ 630230557Sjimharris 631230557Sjimharris DELAY(microseconds); 632230557Sjimharris} 633230557Sjimharris 634230557Sjimharris/** 635230557Sjimharris * @brief In this method the user must return the base address register (BAR) 636230557Sjimharris * value for the supplied base address register number. 637230557Sjimharris * 638230557Sjimharris * @param[in] controller The controller for which to retrieve the bar number. 639230557Sjimharris * @param[in] bar_number This parameter depicts the BAR index/number to be read. 640230557Sjimharris * 641230557Sjimharris * @return Return a pointer value indicating the contents of the BAR. 642230557Sjimharris * @retval NULL indicates an invalid BAR index/number was specified. 643230557Sjimharris * @retval All other values indicate a valid VIRTUAL address from the BAR. 644230557Sjimharris */ 645230557Sjimharrisvoid * 646230557Sjimharrisscic_cb_pci_get_bar(SCI_CONTROLLER_HANDLE_T controller, 647230557Sjimharris uint16_t bar_number) 648230557Sjimharris{ 649230557Sjimharris 650230557Sjimharris return ((void *)(POINTER_UINT)((uint32_t)bar_number << 28)); 651230557Sjimharris} 652230557Sjimharris 653230557Sjimharris/** 654230557Sjimharris * @brief This method informs the SCI Core user that a phy/link became 655230557Sjimharris * ready, but the phy is not allowed in the port. In some 656230557Sjimharris * situations the underlying hardware only allows for certain phy 657230557Sjimharris * to port mappings. If these mappings are violated, then this 658230557Sjimharris * API is invoked. 659230557Sjimharris * 660230557Sjimharris * @param[in] controller This parameter represents the controller which 661230557Sjimharris * contains the port. 662230557Sjimharris * @param[in] port This parameter specifies the SCI port object for which 663230557Sjimharris * the callback is being invoked. 664230557Sjimharris * @param[in] phy This parameter specifies the phy that came ready, but the 665230557Sjimharris * phy can't be a valid member of the port. 666230557Sjimharris * 667230557Sjimharris * @return none 668230557Sjimharris */ 669230557Sjimharrisvoid 670230557Sjimharrisscic_cb_port_invalid_link_up(SCI_CONTROLLER_HANDLE_T controller, 671230557Sjimharris SCI_PORT_HANDLE_T port, SCI_PHY_HANDLE_T phy) 672230557Sjimharris{ 673230557Sjimharris 674230557Sjimharris} 675