1144966Svkashyap/* 2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap. 4144966Svkashyap * Copyright (c) 2000 Michael Smith 5144966Svkashyap * Copyright (c) 2000 BSDi 6144966Svkashyap * All rights reserved. 7144966Svkashyap * 8144966Svkashyap * Redistribution and use in source and binary forms, with or without 9144966Svkashyap * modification, are permitted provided that the following conditions 10144966Svkashyap * are met: 11144966Svkashyap * 1. Redistributions of source code must retain the above copyright 12144966Svkashyap * notice, this list of conditions and the following disclaimer. 13144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright 14144966Svkashyap * notice, this list of conditions and the following disclaimer in the 15144966Svkashyap * documentation and/or other materials provided with the distribution. 16144966Svkashyap * 17144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20144966Svkashyap * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27144966Svkashyap * SUCH DAMAGE. 28144966Svkashyap */ 29144966Svkashyap 30229093Shselasky#include <sys/cdefs.h> 31229093Shselasky__FBSDID("$FreeBSD$"); 32229093Shselasky 33144966Svkashyap/* 34144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers. 35144966Svkashyap * 36144966Svkashyap * Author: Vinod Kashyap 37169400Sscottl * Modifications by: Adam Radford 38172496Sscottl * Modifications by: Manjunath Ranganathaiah 39144966Svkashyap */ 40144966Svkashyap 41144966Svkashyap 42144966Svkashyap/* 43144966Svkashyap * FreeBSD specific functions not related to CAM, and other 44144966Svkashyap * miscellaneous functions. 45144966Svkashyap */ 46144966Svkashyap 47144966Svkashyap 48149968Sobrien#include <dev/twa/tw_osl_includes.h> 49149968Sobrien#include <dev/twa/tw_cl_fwif.h> 50149968Sobrien#include <dev/twa/tw_cl_ioctl.h> 51149968Sobrien#include <dev/twa/tw_osl_ioctl.h> 52144966Svkashyap 53144966Svkashyap#ifdef TW_OSL_DEBUG 54144966SvkashyapTW_INT32 TW_DEBUG_LEVEL_FOR_OSL = TW_OSL_DEBUG; 55144966SvkashyapTW_INT32 TW_OSL_DEBUG_LEVEL_FOR_CL = TW_OSL_DEBUG; 56144966Svkashyap#endif /* TW_OSL_DEBUG */ 57144966Svkashyap 58249132Smavstatic MALLOC_DEFINE(TW_OSLI_MALLOC_CLASS, "twa_commands", "twa commands"); 59144966Svkashyap 60144966Svkashyap 61144966Svkashyapstatic d_open_t twa_open; 62144966Svkashyapstatic d_close_t twa_close; 63144966Svkashyapstatic d_ioctl_t twa_ioctl; 64144966Svkashyap 65144966Svkashyapstatic struct cdevsw twa_cdevsw = { 66144966Svkashyap .d_version = D_VERSION, 67144966Svkashyap .d_open = twa_open, 68144966Svkashyap .d_close = twa_close, 69144966Svkashyap .d_ioctl = twa_ioctl, 70144966Svkashyap .d_name = "twa", 71144966Svkashyap}; 72144966Svkashyap 73144966Svkashyapstatic devclass_t twa_devclass; 74144966Svkashyap 75144966Svkashyap 76144966Svkashyap/* 77144966Svkashyap * Function name: twa_open 78144966Svkashyap * Description: Called when the controller is opened. 79144966Svkashyap * Simply marks the controller as open. 80144966Svkashyap * 81144966Svkashyap * Input: dev -- control device corresponding to the ctlr 82144966Svkashyap * flags -- mode of open 83144966Svkashyap * fmt -- device type (character/block etc.) 84144966Svkashyap * proc -- current process 85144966Svkashyap * Output: None 86144966Svkashyap * Return value: 0 -- success 87144966Svkashyap * non-zero-- failure 88144966Svkashyap */ 89144966Svkashyapstatic TW_INT32 90192450Simptwa_open(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc) 91144966Svkashyap{ 92191060Sed struct twa_softc *sc = (struct twa_softc *)(dev->si_drv1); 93144966Svkashyap 94144966Svkashyap tw_osli_dbg_dprintf(5, sc, "entered"); 95208969Sdelphij sc->open = TW_CL_TRUE; 96144966Svkashyap return(0); 97144966Svkashyap} 98144966Svkashyap 99144966Svkashyap 100144966Svkashyap 101144966Svkashyap/* 102144966Svkashyap * Function name: twa_close 103144966Svkashyap * Description: Called when the controller is closed. 104144966Svkashyap * Simply marks the controller as not open. 105144966Svkashyap * 106144966Svkashyap * Input: dev -- control device corresponding to the ctlr 107144966Svkashyap * flags -- mode of corresponding open 108144966Svkashyap * fmt -- device type (character/block etc.) 109144966Svkashyap * proc -- current process 110144966Svkashyap * Output: None 111144966Svkashyap * Return value: 0 -- success 112144966Svkashyap * non-zero-- failure 113144966Svkashyap */ 114144966Svkashyapstatic TW_INT32 115192450Simptwa_close(struct cdev *dev, TW_INT32 flags, TW_INT32 fmt, struct thread *proc) 116144966Svkashyap{ 117191060Sed struct twa_softc *sc = (struct twa_softc *)(dev->si_drv1); 118144966Svkashyap 119144966Svkashyap tw_osli_dbg_dprintf(5, sc, "entered"); 120208969Sdelphij sc->open = TW_CL_FALSE; 121144966Svkashyap return(0); 122144966Svkashyap} 123144966Svkashyap 124144966Svkashyap 125144966Svkashyap 126144966Svkashyap/* 127144966Svkashyap * Function name: twa_ioctl 128144966Svkashyap * Description: Called when an ioctl is posted to the controller. 129144966Svkashyap * Handles any OS Layer specific cmds, passes the rest 130144966Svkashyap * on to the Common Layer. 131144966Svkashyap * 132144966Svkashyap * Input: dev -- control device corresponding to the ctlr 133144966Svkashyap * cmd -- ioctl cmd 134144966Svkashyap * buf -- ptr to buffer in kernel memory, which is 135144966Svkashyap * a copy of the input buffer in user-space 136144966Svkashyap * flags -- mode of corresponding open 137144966Svkashyap * proc -- current process 138144966Svkashyap * Output: buf -- ptr to buffer in kernel memory, which will 139144966Svkashyap * be copied to the output buffer in user-space 140144966Svkashyap * Return value: 0 -- success 141144966Svkashyap * non-zero-- failure 142144966Svkashyap */ 143144966Svkashyapstatic TW_INT32 144192450Simptwa_ioctl(struct cdev *dev, u_long cmd, caddr_t buf, TW_INT32 flags, struct thread *proc) 145144966Svkashyap{ 146144966Svkashyap struct twa_softc *sc = (struct twa_softc *)(dev->si_drv1); 147144966Svkashyap TW_INT32 error; 148144966Svkashyap 149144966Svkashyap tw_osli_dbg_dprintf(5, sc, "entered"); 150144966Svkashyap 151144966Svkashyap switch (cmd) { 152144966Svkashyap case TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH: 153144966Svkashyap tw_osli_dbg_dprintf(6, sc, "ioctl: fw_passthru"); 154144966Svkashyap error = tw_osli_fw_passthru(sc, (TW_INT8 *)buf); 155144966Svkashyap break; 156144966Svkashyap 157144966Svkashyap case TW_OSL_IOCTL_SCAN_BUS: 158144966Svkashyap /* Request CAM for a bus scan. */ 159144966Svkashyap tw_osli_dbg_dprintf(6, sc, "ioctl: scan bus"); 160144966Svkashyap error = tw_osli_request_bus_scan(sc); 161144966Svkashyap break; 162144966Svkashyap 163144966Svkashyap default: 164144966Svkashyap tw_osli_dbg_dprintf(6, sc, "ioctl: 0x%lx", cmd); 165144966Svkashyap error = tw_cl_ioctl(&sc->ctlr_handle, cmd, buf); 166144966Svkashyap break; 167144966Svkashyap } 168144966Svkashyap return(error); 169144966Svkashyap} 170144966Svkashyap 171144966Svkashyap 172144966Svkashyap 173144966Svkashyapstatic TW_INT32 twa_probe(device_t dev); 174144966Svkashyapstatic TW_INT32 twa_attach(device_t dev); 175144966Svkashyapstatic TW_INT32 twa_detach(device_t dev); 176144966Svkashyapstatic TW_INT32 twa_shutdown(device_t dev); 177144966Svkashyapstatic TW_VOID twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op); 178166901Spisostatic TW_VOID twa_pci_intr(TW_VOID *arg); 179212008Sdelphijstatic TW_VOID twa_watchdog(TW_VOID *arg); 180212008Sdelphijint twa_setup_intr(struct twa_softc *sc); 181212008Sdelphijint twa_teardown_intr(struct twa_softc *sc); 182144966Svkashyap 183144966Svkashyapstatic TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc); 184144966Svkashyapstatic TW_VOID tw_osli_free_resources(struct twa_softc *sc); 185144966Svkashyap 186144966Svkashyapstatic TW_VOID twa_map_load_data_callback(TW_VOID *arg, 187144966Svkashyap bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error); 188144966Svkashyapstatic TW_VOID twa_map_load_callback(TW_VOID *arg, 189144966Svkashyap bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error); 190144966Svkashyap 191144966Svkashyap 192144966Svkashyapstatic device_method_t twa_methods[] = { 193144966Svkashyap /* Device interface */ 194144966Svkashyap DEVMETHOD(device_probe, twa_probe), 195144966Svkashyap DEVMETHOD(device_attach, twa_attach), 196144966Svkashyap DEVMETHOD(device_detach, twa_detach), 197144966Svkashyap DEVMETHOD(device_shutdown, twa_shutdown), 198144966Svkashyap 199229093Shselasky DEVMETHOD_END 200144966Svkashyap}; 201144966Svkashyap 202144966Svkashyapstatic driver_t twa_pci_driver = { 203144966Svkashyap "twa", 204144966Svkashyap twa_methods, 205144966Svkashyap sizeof(struct twa_softc) 206144966Svkashyap}; 207144966Svkashyap 208144966SvkashyapDRIVER_MODULE(twa, pci, twa_pci_driver, twa_devclass, 0, 0); 209169400SscottlMODULE_DEPEND(twa, cam, 1, 1, 1); 210165106SmjacobMODULE_DEPEND(twa, pci, 1, 1, 1); 211144966Svkashyap 212144966Svkashyap 213144966Svkashyap/* 214144966Svkashyap * Function name: twa_probe 215144966Svkashyap * Description: Called at driver load time. Claims 9000 ctlrs. 216144966Svkashyap * 217144966Svkashyap * Input: dev -- bus device corresponding to the ctlr 218144966Svkashyap * Output: None 219144966Svkashyap * Return value: <= 0 -- success 220144966Svkashyap * > 0 -- failure 221144966Svkashyap */ 222144966Svkashyapstatic TW_INT32 223144966Svkashyaptwa_probe(device_t dev) 224144966Svkashyap{ 225144966Svkashyap static TW_UINT8 first_ctlr = 1; 226144966Svkashyap 227144966Svkashyap tw_osli_dbg_printf(3, "entered"); 228144966Svkashyap 229144966Svkashyap if (tw_cl_ctlr_supported(pci_get_vendor(dev), pci_get_device(dev))) { 230144966Svkashyap device_set_desc(dev, TW_OSLI_DEVICE_NAME); 231144966Svkashyap /* Print the driver version only once. */ 232144966Svkashyap if (first_ctlr) { 233144966Svkashyap printf("3ware device driver for 9000 series storage " 234144966Svkashyap "controllers, version: %s\n", 235144966Svkashyap TW_OSL_DRIVER_VERSION_STRING); 236144966Svkashyap first_ctlr = 0; 237144966Svkashyap } 238144966Svkashyap return(0); 239144966Svkashyap } 240144966Svkashyap return(ENXIO); 241144966Svkashyap} 242144966Svkashyap 243212008Sdelphijint twa_setup_intr(struct twa_softc *sc) 244212008Sdelphij{ 245212008Sdelphij int error = 0; 246144966Svkashyap 247212008Sdelphij if (!(sc->intr_handle) && (sc->irq_res)) { 248212008Sdelphij error = bus_setup_intr(sc->bus_dev, sc->irq_res, 249212008Sdelphij INTR_TYPE_CAM | INTR_MPSAFE, 250212008Sdelphij NULL, twa_pci_intr, 251212008Sdelphij sc, &sc->intr_handle); 252212008Sdelphij } 253212008Sdelphij return( error ); 254212008Sdelphij} 255144966Svkashyap 256212008Sdelphij 257212008Sdelphijint twa_teardown_intr(struct twa_softc *sc) 258212008Sdelphij{ 259212008Sdelphij int error = 0; 260212008Sdelphij 261212008Sdelphij if ((sc->intr_handle) && (sc->irq_res)) { 262212008Sdelphij error = bus_teardown_intr(sc->bus_dev, 263212008Sdelphij sc->irq_res, sc->intr_handle); 264212008Sdelphij sc->intr_handle = NULL; 265212008Sdelphij } 266212008Sdelphij return( error ); 267212008Sdelphij} 268212008Sdelphij 269212008Sdelphij 270212008Sdelphij 271144966Svkashyap/* 272144966Svkashyap * Function name: twa_attach 273144966Svkashyap * Description: Allocates pci resources; updates sc; adds a node to the 274144966Svkashyap * sysctl tree to expose the driver version; makes calls 275144966Svkashyap * (to the Common Layer) to initialize ctlr, and to 276144966Svkashyap * attach to CAM. 277144966Svkashyap * 278144966Svkashyap * Input: dev -- bus device corresponding to the ctlr 279144966Svkashyap * Output: None 280144966Svkashyap * Return value: 0 -- success 281144966Svkashyap * non-zero-- failure 282144966Svkashyap */ 283144966Svkashyapstatic TW_INT32 284144966Svkashyaptwa_attach(device_t dev) 285144966Svkashyap{ 286144966Svkashyap struct twa_softc *sc = device_get_softc(dev); 287152213Svkashyap TW_INT32 bar_num; 288152213Svkashyap TW_INT32 bar0_offset; 289152213Svkashyap TW_INT32 bar_size; 290144966Svkashyap TW_INT32 error; 291144966Svkashyap 292144966Svkashyap tw_osli_dbg_dprintf(3, sc, "entered"); 293144966Svkashyap 294144966Svkashyap sc->ctlr_handle.osl_ctlr_ctxt = sc; 295144966Svkashyap 296144966Svkashyap /* Initialize the softc structure. */ 297144966Svkashyap sc->bus_dev = dev; 298152213Svkashyap sc->device_id = pci_get_device(dev); 299144966Svkashyap 300144966Svkashyap /* Initialize the mutexes right here. */ 301144966Svkashyap sc->io_lock = &(sc->io_lock_handle); 302144966Svkashyap mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN); 303144966Svkashyap sc->q_lock = &(sc->q_lock_handle); 304144966Svkashyap mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN); 305172496Sscottl sc->sim_lock = &(sc->sim_lock_handle); 306172496Sscottl mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE); 307144966Svkashyap 308144966Svkashyap sysctl_ctx_init(&sc->sysctl_ctxt); 309144966Svkashyap sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt, 310144966Svkashyap SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 311144966Svkashyap device_get_nameunit(dev), CTLFLAG_RD, 0, ""); 312144966Svkashyap if (sc->sysctl_tree == NULL) { 313144966Svkashyap tw_osli_printf(sc, "error = %d", 314144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 315144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 316144966Svkashyap 0x2000, 317144966Svkashyap "Cannot add sysctl tree node", 318144966Svkashyap ENXIO); 319144966Svkashyap return(ENXIO); 320144966Svkashyap } 321144966Svkashyap SYSCTL_ADD_STRING(&sc->sysctl_ctxt, SYSCTL_CHILDREN(sc->sysctl_tree), 322144966Svkashyap OID_AUTO, "driver_version", CTLFLAG_RD, 323144966Svkashyap TW_OSL_DRIVER_VERSION_STRING, 0, "TWA driver version"); 324144966Svkashyap 325144966Svkashyap /* Force the busmaster enable bit on, in case the BIOS forgot. */ 326254306Sscottl pci_enable_busmaster(dev); 327144966Svkashyap 328144966Svkashyap /* Allocate the PCI register window. */ 329152213Svkashyap if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM, 330152213Svkashyap &bar_num, &bar0_offset, &bar_size))) { 331152213Svkashyap tw_osli_printf(sc, "error = %d", 332152213Svkashyap TW_CL_SEVERITY_ERROR_STRING, 333152213Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 334152213Svkashyap 0x201F, 335152213Svkashyap "Can't get PCI BAR info", 336152213Svkashyap error); 337152213Svkashyap tw_osli_free_resources(sc); 338152213Svkashyap return(error); 339152213Svkashyap } 340152213Svkashyap sc->reg_res_id = PCIR_BARS + bar0_offset; 341152213Svkashyap if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 342144966Svkashyap &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE)) 343144966Svkashyap == NULL) { 344144966Svkashyap tw_osli_printf(sc, "error = %d", 345144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 346144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 347144966Svkashyap 0x2002, 348144966Svkashyap "Can't allocate register window", 349144966Svkashyap ENXIO); 350144966Svkashyap tw_osli_free_resources(sc); 351144966Svkashyap return(ENXIO); 352144966Svkashyap } 353144966Svkashyap sc->bus_tag = rman_get_bustag(sc->reg_res); 354144966Svkashyap sc->bus_handle = rman_get_bushandle(sc->reg_res); 355144966Svkashyap 356144966Svkashyap /* Allocate and register our interrupt. */ 357144966Svkashyap sc->irq_res_id = 0; 358144966Svkashyap if ((sc->irq_res = bus_alloc_resource(sc->bus_dev, SYS_RES_IRQ, 359144966Svkashyap &(sc->irq_res_id), 0, ~0, 1, 360144966Svkashyap RF_SHAREABLE | RF_ACTIVE)) == NULL) { 361144966Svkashyap tw_osli_printf(sc, "error = %d", 362144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 363144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 364144966Svkashyap 0x2003, 365144966Svkashyap "Can't allocate interrupt", 366144966Svkashyap ENXIO); 367144966Svkashyap tw_osli_free_resources(sc); 368144966Svkashyap return(ENXIO); 369144966Svkashyap } 370212008Sdelphij if ((error = twa_setup_intr(sc))) { 371144966Svkashyap tw_osli_printf(sc, "error = %d", 372144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 373144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 374144966Svkashyap 0x2004, 375144966Svkashyap "Can't set up interrupt", 376144966Svkashyap error); 377144966Svkashyap tw_osli_free_resources(sc); 378144966Svkashyap return(error); 379144966Svkashyap } 380144966Svkashyap 381144966Svkashyap if ((error = tw_osli_alloc_mem(sc))) { 382144966Svkashyap tw_osli_printf(sc, "error = %d", 383144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 384144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 385144966Svkashyap 0x2005, 386144966Svkashyap "Memory allocation failure", 387144966Svkashyap error); 388144966Svkashyap tw_osli_free_resources(sc); 389144966Svkashyap return(error); 390144966Svkashyap } 391144966Svkashyap 392144966Svkashyap /* Initialize the Common Layer for this controller. */ 393152213Svkashyap if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id, 394208969Sdelphij TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS, 395144966Svkashyap sc->non_dma_mem, sc->dma_mem, 396144966Svkashyap sc->dma_mem_phys 397144966Svkashyap ))) { 398144966Svkashyap tw_osli_printf(sc, "error = %d", 399144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 400144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 401144966Svkashyap 0x2006, 402144966Svkashyap "Failed to initialize Common Layer/controller", 403144966Svkashyap error); 404144966Svkashyap tw_osli_free_resources(sc); 405144966Svkashyap return(error); 406144966Svkashyap } 407144966Svkashyap 408144966Svkashyap /* Create the control device. */ 409144966Svkashyap sc->ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->bus_dev), 410144966Svkashyap UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, 411144966Svkashyap "twa%d", device_get_unit(sc->bus_dev)); 412144966Svkashyap sc->ctrl_dev->si_drv1 = sc; 413144966Svkashyap 414144966Svkashyap if ((error = tw_osli_cam_attach(sc))) { 415144966Svkashyap tw_osli_free_resources(sc); 416144966Svkashyap tw_osli_printf(sc, "error = %d", 417144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 418144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 419144966Svkashyap 0x2007, 420144966Svkashyap "Failed to initialize CAM", 421144966Svkashyap error); 422144966Svkashyap return(error); 423144966Svkashyap } 424144966Svkashyap 425212008Sdelphij sc->watchdog_index = 0; 426212008Sdelphij callout_init(&(sc->watchdog_callout[0]), CALLOUT_MPSAFE); 427212008Sdelphij callout_init(&(sc->watchdog_callout[1]), CALLOUT_MPSAFE); 428212008Sdelphij callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle); 429212008Sdelphij 430144966Svkashyap return(0); 431144966Svkashyap} 432144966Svkashyap 433144966Svkashyap 434212008Sdelphijstatic TW_VOID 435212008Sdelphijtwa_watchdog(TW_VOID *arg) 436212008Sdelphij{ 437212008Sdelphij struct tw_cl_ctlr_handle *ctlr_handle = 438212008Sdelphij (struct tw_cl_ctlr_handle *)arg; 439212008Sdelphij struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt; 440212008Sdelphij int i; 441212008Sdelphij int i_need_a_reset = 0; 442212008Sdelphij int driver_is_active = 0; 443212008Sdelphij int my_watchdog_was_pending = 1234; 444212008Sdelphij TW_UINT64 current_time; 445212008Sdelphij struct tw_osli_req_context *my_req; 446144966Svkashyap 447212008Sdelphij 448212008Sdelphij//============================================================================== 449212008Sdelphij current_time = (TW_UINT64) (tw_osl_get_local_time()); 450212008Sdelphij 451212008Sdelphij for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) { 452212008Sdelphij my_req = &(sc->req_ctx_buf[i]); 453212008Sdelphij 454212008Sdelphij if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) && 455212008Sdelphij (my_req->deadline) && 456212008Sdelphij (my_req->deadline < current_time)) { 457212008Sdelphij tw_cl_set_reset_needed(ctlr_handle); 458212008Sdelphij#ifdef TW_OSL_DEBUG 459212210Sbz device_printf((sc)->bus_dev, "Request %d timed out! d = %llu, c = %llu\n", i, my_req->deadline, current_time); 460212008Sdelphij#else /* TW_OSL_DEBUG */ 461212008Sdelphij device_printf((sc)->bus_dev, "Request %d timed out!\n", i); 462212008Sdelphij#endif /* TW_OSL_DEBUG */ 463212008Sdelphij break; 464212008Sdelphij } 465212008Sdelphij } 466212008Sdelphij//============================================================================== 467212008Sdelphij 468212008Sdelphij i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle); 469212008Sdelphij 470212008Sdelphij i = (int) ((sc->watchdog_index++) & 1); 471212008Sdelphij 472212008Sdelphij driver_is_active = tw_cl_is_active(ctlr_handle); 473212008Sdelphij 474212008Sdelphij if (i_need_a_reset) { 475212008Sdelphij#ifdef TW_OSL_DEBUG 476212008Sdelphij device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n"); 477212008Sdelphij#endif /* TW_OSL_DEBUG */ 478212008Sdelphij my_watchdog_was_pending = 479212008Sdelphij callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle); 480212008Sdelphij tw_cl_reset_ctlr(ctlr_handle); 481212008Sdelphij#ifdef TW_OSL_DEBUG 482212008Sdelphij device_printf((sc)->bus_dev, "Watchdog reset completed!\n"); 483212008Sdelphij#endif /* TW_OSL_DEBUG */ 484212008Sdelphij } else if (driver_is_active) { 485212008Sdelphij my_watchdog_was_pending = 486212008Sdelphij callout_reset(&(sc->watchdog_callout[i]), 5*hz, twa_watchdog, &sc->ctlr_handle); 487212008Sdelphij } 488212008Sdelphij#ifdef TW_OSL_DEBUG 489212008Sdelphij if (i_need_a_reset || my_watchdog_was_pending) 490212008Sdelphij device_printf((sc)->bus_dev, "i_need_a_reset = %d, " 491212008Sdelphij "driver_is_active = %d, my_watchdog_was_pending = %d\n", 492212008Sdelphij i_need_a_reset, driver_is_active, my_watchdog_was_pending); 493212008Sdelphij#endif /* TW_OSL_DEBUG */ 494212008Sdelphij} 495212008Sdelphij 496212008Sdelphij 497144966Svkashyap/* 498144966Svkashyap * Function name: tw_osli_alloc_mem 499144966Svkashyap * Description: Allocates memory needed both by CL and OSL. 500144966Svkashyap * 501144966Svkashyap * Input: sc -- OSL internal controller context 502144966Svkashyap * Output: None 503144966Svkashyap * Return value: 0 -- success 504144966Svkashyap * non-zero-- failure 505144966Svkashyap */ 506144966Svkashyapstatic TW_INT32 507144966Svkashyaptw_osli_alloc_mem(struct twa_softc *sc) 508144966Svkashyap{ 509144966Svkashyap struct tw_osli_req_context *req; 510144966Svkashyap TW_UINT32 max_sg_elements; 511144966Svkashyap TW_UINT32 non_dma_mem_size; 512144966Svkashyap TW_UINT32 dma_mem_size; 513144966Svkashyap TW_INT32 error; 514144966Svkashyap TW_INT32 i; 515144966Svkashyap 516144966Svkashyap tw_osli_dbg_dprintf(3, sc, "entered"); 517144966Svkashyap 518144966Svkashyap sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0; 519144966Svkashyap sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0; 520144966Svkashyap 521144966Svkashyap max_sg_elements = (sizeof(bus_addr_t) == 8) ? 522144966Svkashyap TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS; 523144966Svkashyap 524144966Svkashyap if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags, 525208969Sdelphij sc->device_id, TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS, 526144966Svkashyap &(sc->alignment), &(sc->sg_size_factor), 527144966Svkashyap &non_dma_mem_size, &dma_mem_size 528144966Svkashyap ))) { 529144966Svkashyap tw_osli_printf(sc, "error = %d", 530144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 531144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 532144966Svkashyap 0x2008, 533144966Svkashyap "Can't get Common Layer's memory requirements", 534144966Svkashyap error); 535144966Svkashyap return(error); 536144966Svkashyap } 537144966Svkashyap 538144966Svkashyap if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS, 539144966Svkashyap M_WAITOK)) == NULL) { 540144966Svkashyap tw_osli_printf(sc, "error = %d", 541144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 542144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 543144966Svkashyap 0x2009, 544144966Svkashyap "Can't allocate non-dma memory", 545144966Svkashyap ENOMEM); 546144966Svkashyap return(ENOMEM); 547144966Svkashyap } 548144966Svkashyap 549144966Svkashyap /* Create the parent dma tag. */ 550233705Sjhb if (bus_dma_tag_create(bus_get_dma_tag(sc->bus_dev), /* parent */ 551144966Svkashyap sc->alignment, /* alignment */ 552233705Sjhb 0, /* boundary */ 553190329Sjhb BUS_SPACE_MAXADDR, /* lowaddr */ 554144966Svkashyap BUS_SPACE_MAXADDR, /* highaddr */ 555144966Svkashyap NULL, NULL, /* filter, filterarg */ 556144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsize */ 557144966Svkashyap max_sg_elements, /* nsegments */ 558144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsegsize */ 559144966Svkashyap 0, /* flags */ 560144966Svkashyap NULL, /* lockfunc */ 561144966Svkashyap NULL, /* lockfuncarg */ 562144966Svkashyap &sc->parent_tag /* tag */)) { 563144966Svkashyap tw_osli_printf(sc, "error = %d", 564144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 565144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 566144966Svkashyap 0x200A, 567144966Svkashyap "Can't allocate parent DMA tag", 568144966Svkashyap ENOMEM); 569144966Svkashyap return(ENOMEM); 570144966Svkashyap } 571144966Svkashyap 572144966Svkashyap /* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */ 573144966Svkashyap if (bus_dma_tag_create(sc->parent_tag, /* parent */ 574144966Svkashyap sc->alignment, /* alignment */ 575144966Svkashyap 0, /* boundary */ 576190329Sjhb BUS_SPACE_MAXADDR, /* lowaddr */ 577144966Svkashyap BUS_SPACE_MAXADDR, /* highaddr */ 578144966Svkashyap NULL, NULL, /* filter, filterarg */ 579144966Svkashyap dma_mem_size, /* maxsize */ 580144966Svkashyap 1, /* nsegments */ 581144966Svkashyap BUS_SPACE_MAXSIZE, /* maxsegsize */ 582144966Svkashyap 0, /* flags */ 583144966Svkashyap NULL, /* lockfunc */ 584144966Svkashyap NULL, /* lockfuncarg */ 585144966Svkashyap &sc->cmd_tag /* tag */)) { 586144966Svkashyap tw_osli_printf(sc, "error = %d", 587144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 588144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 589144966Svkashyap 0x200B, 590144966Svkashyap "Can't allocate DMA tag for Common Layer's " 591144966Svkashyap "DMA'able memory", 592144966Svkashyap ENOMEM); 593144966Svkashyap return(ENOMEM); 594144966Svkashyap } 595144966Svkashyap 596144966Svkashyap if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, 597144966Svkashyap BUS_DMA_NOWAIT, &sc->cmd_map)) { 598144966Svkashyap /* Try a second time. */ 599144966Svkashyap if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, 600144966Svkashyap BUS_DMA_NOWAIT, &sc->cmd_map)) { 601144966Svkashyap tw_osli_printf(sc, "error = %d", 602144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 603144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 604144966Svkashyap 0x200C, 605144966Svkashyap "Can't allocate DMA'able memory for the" 606144966Svkashyap "Common Layer", 607144966Svkashyap ENOMEM); 608144966Svkashyap return(ENOMEM); 609144966Svkashyap } 610144966Svkashyap } 611144966Svkashyap 612144966Svkashyap bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem, 613144966Svkashyap dma_mem_size, twa_map_load_callback, 614144966Svkashyap &sc->dma_mem_phys, 0); 615144966Svkashyap 616144966Svkashyap /* 617144966Svkashyap * Create a dma tag for data buffers; size will be the maximum 618144966Svkashyap * possible I/O size (128kB). 619144966Svkashyap */ 620144966Svkashyap if (bus_dma_tag_create(sc->parent_tag, /* parent */ 621144966Svkashyap sc->alignment, /* alignment */ 622144966Svkashyap 0, /* boundary */ 623190329Sjhb BUS_SPACE_MAXADDR, /* lowaddr */ 624144966Svkashyap BUS_SPACE_MAXADDR, /* highaddr */ 625144966Svkashyap NULL, NULL, /* filter, filterarg */ 626144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsize */ 627144966Svkashyap max_sg_elements, /* nsegments */ 628144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsegsize */ 629144966Svkashyap BUS_DMA_ALLOCNOW, /* flags */ 630144966Svkashyap twa_busdma_lock, /* lockfunc */ 631144966Svkashyap sc->io_lock, /* lockfuncarg */ 632144966Svkashyap &sc->dma_tag /* tag */)) { 633144966Svkashyap tw_osli_printf(sc, "error = %d", 634144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 635144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 636144966Svkashyap 0x200F, 637144966Svkashyap "Can't allocate DMA tag for data buffers", 638144966Svkashyap ENOMEM); 639144966Svkashyap return(ENOMEM); 640144966Svkashyap } 641144966Svkashyap 642144966Svkashyap /* 643144966Svkashyap * Create a dma tag for ioctl data buffers; size will be the maximum 644144966Svkashyap * possible I/O size (128kB). 645144966Svkashyap */ 646144966Svkashyap if (bus_dma_tag_create(sc->parent_tag, /* parent */ 647144966Svkashyap sc->alignment, /* alignment */ 648144966Svkashyap 0, /* boundary */ 649190329Sjhb BUS_SPACE_MAXADDR, /* lowaddr */ 650144966Svkashyap BUS_SPACE_MAXADDR, /* highaddr */ 651144966Svkashyap NULL, NULL, /* filter, filterarg */ 652144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsize */ 653144966Svkashyap max_sg_elements, /* nsegments */ 654144966Svkashyap TW_CL_MAX_IO_SIZE, /* maxsegsize */ 655144966Svkashyap BUS_DMA_ALLOCNOW, /* flags */ 656144966Svkashyap twa_busdma_lock, /* lockfunc */ 657144966Svkashyap sc->io_lock, /* lockfuncarg */ 658144966Svkashyap &sc->ioctl_tag /* tag */)) { 659144966Svkashyap tw_osli_printf(sc, "error = %d", 660144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 661144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 662144966Svkashyap 0x2010, 663144966Svkashyap "Can't allocate DMA tag for ioctl data buffers", 664144966Svkashyap ENOMEM); 665144966Svkashyap return(ENOMEM); 666144966Svkashyap } 667144966Svkashyap 668144966Svkashyap /* Create just one map for all ioctl request data buffers. */ 669144966Svkashyap if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) { 670144966Svkashyap tw_osli_printf(sc, "error = %d", 671144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 672144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 673144966Svkashyap 0x2011, 674144966Svkashyap "Can't create ioctl map", 675144966Svkashyap ENOMEM); 676144966Svkashyap return(ENOMEM); 677144966Svkashyap } 678144966Svkashyap 679144966Svkashyap 680144966Svkashyap /* Initialize request queues. */ 681144966Svkashyap tw_osli_req_q_init(sc, TW_OSLI_FREE_Q); 682144966Svkashyap tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q); 683144966Svkashyap 684208969Sdelphij if ((sc->req_ctx_buf = (struct tw_osli_req_context *) 685144966Svkashyap malloc((sizeof(struct tw_osli_req_context) * 686208969Sdelphij TW_OSLI_MAX_NUM_REQUESTS), 687144966Svkashyap TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) { 688144966Svkashyap tw_osli_printf(sc, "error = %d", 689144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 690144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 691144966Svkashyap 0x2012, 692144966Svkashyap "Failed to allocate request packets", 693144966Svkashyap ENOMEM); 694144966Svkashyap return(ENOMEM); 695144966Svkashyap } 696208969Sdelphij bzero(sc->req_ctx_buf, 697208969Sdelphij sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS); 698144966Svkashyap 699208969Sdelphij for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) { 700208969Sdelphij req = &(sc->req_ctx_buf[i]); 701144966Svkashyap req->ctlr = sc; 702144966Svkashyap if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) { 703144966Svkashyap tw_osli_printf(sc, "request # = %d, error = %d", 704144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 705144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 706144966Svkashyap 0x2013, 707144966Svkashyap "Can't create dma map", 708144966Svkashyap i, ENOMEM); 709144966Svkashyap return(ENOMEM); 710144966Svkashyap } 711144966Svkashyap 712208969Sdelphij /* Initialize the ioctl wakeup/ timeout mutex */ 713208969Sdelphij req->ioctl_wake_timeout_lock = &(req->ioctl_wake_timeout_lock_handle); 714208969Sdelphij mtx_init(req->ioctl_wake_timeout_lock, "tw_ioctl_wake_timeout_lock", NULL, MTX_DEF); 715208969Sdelphij 716144966Svkashyap /* Insert request into the free queue. */ 717144966Svkashyap tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 718144966Svkashyap } 719144966Svkashyap 720144966Svkashyap return(0); 721144966Svkashyap} 722144966Svkashyap 723144966Svkashyap 724144966Svkashyap 725144966Svkashyap/* 726144966Svkashyap * Function name: tw_osli_free_resources 727144966Svkashyap * Description: Performs clean-up at the time of going down. 728144966Svkashyap * 729144966Svkashyap * Input: sc -- ptr to OSL internal ctlr context 730144966Svkashyap * Output: None 731144966Svkashyap * Return value: None 732144966Svkashyap */ 733144966Svkashyapstatic TW_VOID 734144966Svkashyaptw_osli_free_resources(struct twa_softc *sc) 735144966Svkashyap{ 736144966Svkashyap struct tw_osli_req_context *req; 737144966Svkashyap TW_INT32 error = 0; 738144966Svkashyap 739144966Svkashyap tw_osli_dbg_dprintf(3, sc, "entered"); 740144966Svkashyap 741144966Svkashyap /* Detach from CAM */ 742144966Svkashyap tw_osli_cam_detach(sc); 743144966Svkashyap 744208969Sdelphij if (sc->req_ctx_buf) 745144966Svkashyap while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) != 746208969Sdelphij NULL) { 747208969Sdelphij mtx_destroy(req->ioctl_wake_timeout_lock); 748208969Sdelphij 749144966Svkashyap if ((error = bus_dmamap_destroy(sc->dma_tag, 750144966Svkashyap req->dma_map))) 751144966Svkashyap tw_osli_dbg_dprintf(1, sc, 752144966Svkashyap "dmamap_destroy(dma) returned %d", 753144966Svkashyap error); 754208969Sdelphij } 755144966Svkashyap 756152213Svkashyap if ((sc->ioctl_tag) && (sc->ioctl_map)) 757152213Svkashyap if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map))) 758152213Svkashyap tw_osli_dbg_dprintf(1, sc, 759152213Svkashyap "dmamap_destroy(ioctl) returned %d", error); 760144966Svkashyap 761144966Svkashyap /* Free all memory allocated so far. */ 762208969Sdelphij if (sc->req_ctx_buf) 763208969Sdelphij free(sc->req_ctx_buf, TW_OSLI_MALLOC_CLASS); 764144966Svkashyap 765144966Svkashyap if (sc->non_dma_mem) 766144966Svkashyap free(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS); 767144966Svkashyap 768144966Svkashyap if (sc->dma_mem) { 769144966Svkashyap bus_dmamap_unload(sc->cmd_tag, sc->cmd_map); 770144966Svkashyap bus_dmamem_free(sc->cmd_tag, sc->dma_mem, 771144966Svkashyap sc->cmd_map); 772144966Svkashyap } 773144966Svkashyap if (sc->cmd_tag) 774144966Svkashyap if ((error = bus_dma_tag_destroy(sc->cmd_tag))) 775144966Svkashyap tw_osli_dbg_dprintf(1, sc, 776144966Svkashyap "dma_tag_destroy(cmd) returned %d", error); 777144966Svkashyap 778144966Svkashyap if (sc->dma_tag) 779144966Svkashyap if ((error = bus_dma_tag_destroy(sc->dma_tag))) 780144966Svkashyap tw_osli_dbg_dprintf(1, sc, 781144966Svkashyap "dma_tag_destroy(dma) returned %d", error); 782144966Svkashyap 783144966Svkashyap if (sc->ioctl_tag) 784144966Svkashyap if ((error = bus_dma_tag_destroy(sc->ioctl_tag))) 785144966Svkashyap tw_osli_dbg_dprintf(1, sc, 786144966Svkashyap "dma_tag_destroy(ioctl) returned %d", error); 787144966Svkashyap 788144966Svkashyap if (sc->parent_tag) 789144966Svkashyap if ((error = bus_dma_tag_destroy(sc->parent_tag))) 790144966Svkashyap tw_osli_dbg_dprintf(1, sc, 791144966Svkashyap "dma_tag_destroy(parent) returned %d", error); 792144966Svkashyap 793144966Svkashyap 794144966Svkashyap /* Disconnect the interrupt handler. */ 795212008Sdelphij if ((error = twa_teardown_intr(sc))) 796144966Svkashyap tw_osli_dbg_dprintf(1, sc, 797144966Svkashyap "teardown_intr returned %d", error); 798144966Svkashyap 799144966Svkashyap if (sc->irq_res != NULL) 800144966Svkashyap if ((error = bus_release_resource(sc->bus_dev, 801144966Svkashyap SYS_RES_IRQ, sc->irq_res_id, sc->irq_res))) 802144966Svkashyap tw_osli_dbg_dprintf(1, sc, 803144966Svkashyap "release_resource(irq) returned %d", error); 804144966Svkashyap 805144966Svkashyap 806144966Svkashyap /* Release the register window mapping. */ 807144966Svkashyap if (sc->reg_res != NULL) 808144966Svkashyap if ((error = bus_release_resource(sc->bus_dev, 809152213Svkashyap SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))) 810144966Svkashyap tw_osli_dbg_dprintf(1, sc, 811144966Svkashyap "release_resource(io) returned %d", error); 812144966Svkashyap 813144966Svkashyap 814144966Svkashyap /* Destroy the control device. */ 815144966Svkashyap if (sc->ctrl_dev != (struct cdev *)NULL) 816144966Svkashyap destroy_dev(sc->ctrl_dev); 817144966Svkashyap 818144966Svkashyap if ((error = sysctl_ctx_free(&sc->sysctl_ctxt))) 819144966Svkashyap tw_osli_dbg_dprintf(1, sc, 820144966Svkashyap "sysctl_ctx_free returned %d", error); 821144966Svkashyap 822144966Svkashyap} 823144966Svkashyap 824144966Svkashyap 825144966Svkashyap 826144966Svkashyap/* 827144966Svkashyap * Function name: twa_detach 828144966Svkashyap * Description: Called when the controller is being detached from 829144966Svkashyap * the pci bus. 830144966Svkashyap * 831144966Svkashyap * Input: dev -- bus device corresponding to the ctlr 832144966Svkashyap * Output: None 833144966Svkashyap * Return value: 0 -- success 834144966Svkashyap * non-zero-- failure 835144966Svkashyap */ 836144966Svkashyapstatic TW_INT32 837144966Svkashyaptwa_detach(device_t dev) 838144966Svkashyap{ 839144966Svkashyap struct twa_softc *sc = device_get_softc(dev); 840144966Svkashyap TW_INT32 error; 841144966Svkashyap 842144966Svkashyap tw_osli_dbg_dprintf(3, sc, "entered"); 843144966Svkashyap 844144966Svkashyap error = EBUSY; 845208969Sdelphij if (sc->open) { 846144966Svkashyap tw_osli_printf(sc, "error = %d", 847144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 848144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 849144966Svkashyap 0x2014, 850144966Svkashyap "Device open", 851144966Svkashyap error); 852144966Svkashyap goto out; 853144966Svkashyap } 854144966Svkashyap 855144966Svkashyap /* Shut the controller down. */ 856144966Svkashyap if ((error = twa_shutdown(dev))) 857144966Svkashyap goto out; 858144966Svkashyap 859144966Svkashyap /* Free all resources associated with this controller. */ 860144966Svkashyap tw_osli_free_resources(sc); 861144966Svkashyap error = 0; 862144966Svkashyap 863144966Svkashyapout: 864144966Svkashyap return(error); 865144966Svkashyap} 866144966Svkashyap 867144966Svkashyap 868144966Svkashyap 869144966Svkashyap/* 870144966Svkashyap * Function name: twa_shutdown 871144966Svkashyap * Description: Called at unload/shutdown time. Lets the controller 872144966Svkashyap * know that we are going down. 873144966Svkashyap * 874144966Svkashyap * Input: dev -- bus device corresponding to the ctlr 875144966Svkashyap * Output: None 876144966Svkashyap * Return value: 0 -- success 877144966Svkashyap * non-zero-- failure 878144966Svkashyap */ 879144966Svkashyapstatic TW_INT32 880144966Svkashyaptwa_shutdown(device_t dev) 881144966Svkashyap{ 882144966Svkashyap struct twa_softc *sc = device_get_softc(dev); 883144966Svkashyap TW_INT32 error = 0; 884144966Svkashyap 885144966Svkashyap tw_osli_dbg_dprintf(3, sc, "entered"); 886144966Svkashyap 887212008Sdelphij /* Disconnect interrupts. */ 888212008Sdelphij error = twa_teardown_intr(sc); 889212008Sdelphij 890212028Sdelphij /* Stop watchdog task. */ 891212028Sdelphij callout_drain(&(sc->watchdog_callout[0])); 892212028Sdelphij callout_drain(&(sc->watchdog_callout[1])); 893212028Sdelphij 894144966Svkashyap /* Disconnect from the controller. */ 895144966Svkashyap if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) { 896144966Svkashyap tw_osli_printf(sc, "error = %d", 897144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 898144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 899144966Svkashyap 0x2015, 900144966Svkashyap "Failed to shutdown Common Layer/controller", 901144966Svkashyap error); 902144966Svkashyap } 903144966Svkashyap return(error); 904144966Svkashyap} 905144966Svkashyap 906144966Svkashyap 907144966Svkashyap 908144966Svkashyap/* 909144966Svkashyap * Function name: twa_busdma_lock 910144966Svkashyap * Description: Function to provide synchronization during busdma_swi. 911144966Svkashyap * 912144966Svkashyap * Input: lock_arg -- lock mutex sent as argument 913144966Svkashyap * op -- operation (lock/unlock) expected of the function 914144966Svkashyap * Output: None 915144966Svkashyap * Return value: None 916144966Svkashyap */ 917144966SvkashyapTW_VOID 918144966Svkashyaptwa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op) 919144966Svkashyap{ 920144966Svkashyap struct mtx *lock; 921144966Svkashyap 922144966Svkashyap lock = (struct mtx *)lock_arg; 923144966Svkashyap switch (op) { 924144966Svkashyap case BUS_DMA_LOCK: 925144966Svkashyap mtx_lock_spin(lock); 926144966Svkashyap break; 927144966Svkashyap 928144966Svkashyap case BUS_DMA_UNLOCK: 929144966Svkashyap mtx_unlock_spin(lock); 930144966Svkashyap break; 931144966Svkashyap 932144966Svkashyap default: 933144966Svkashyap panic("Unknown operation 0x%x for twa_busdma_lock!", op); 934144966Svkashyap } 935144966Svkashyap} 936144966Svkashyap 937144966Svkashyap 938166901Spiso/* 939144966Svkashyap * Function name: twa_pci_intr 940144966Svkashyap * Description: Interrupt handler. Wrapper for twa_interrupt. 941144966Svkashyap * 942144966Svkashyap * Input: arg -- ptr to OSL internal ctlr context 943144966Svkashyap * Output: None 944144966Svkashyap * Return value: None 945144966Svkashyap */ 946144966Svkashyapstatic TW_VOID 947144966Svkashyaptwa_pci_intr(TW_VOID *arg) 948144966Svkashyap{ 949144966Svkashyap struct twa_softc *sc = (struct twa_softc *)arg; 950144966Svkashyap 951144966Svkashyap tw_osli_dbg_dprintf(10, sc, "entered"); 952208969Sdelphij tw_cl_interrupt(&(sc->ctlr_handle)); 953144966Svkashyap} 954144966Svkashyap 955152213Svkashyap 956144966Svkashyap/* 957144966Svkashyap * Function name: tw_osli_fw_passthru 958144966Svkashyap * Description: Builds a fw passthru cmd pkt, and submits it to CL. 959144966Svkashyap * 960144966Svkashyap * Input: sc -- ptr to OSL internal ctlr context 961144966Svkashyap * buf -- ptr to ioctl pkt understood by CL 962144966Svkashyap * Output: None 963144966Svkashyap * Return value: 0 -- success 964144966Svkashyap * non-zero-- failure 965144966Svkashyap */ 966144966SvkashyapTW_INT32 967144966Svkashyaptw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf) 968144966Svkashyap{ 969144966Svkashyap struct tw_osli_req_context *req; 970144966Svkashyap struct tw_osli_ioctl_no_data_buf *user_buf = 971144966Svkashyap (struct tw_osli_ioctl_no_data_buf *)buf; 972144966Svkashyap TW_TIME end_time; 973144966Svkashyap TW_UINT32 timeout = 60; 974144966Svkashyap TW_UINT32 data_buf_size_adjusted; 975144966Svkashyap struct tw_cl_req_packet *req_pkt; 976144966Svkashyap struct tw_cl_passthru_req_packet *pt_req; 977144966Svkashyap TW_INT32 error; 978144966Svkashyap 979144966Svkashyap tw_osli_dbg_dprintf(5, sc, "ioctl: passthru"); 980144966Svkashyap 981144966Svkashyap if ((req = tw_osli_get_request(sc)) == NULL) 982144966Svkashyap return(EBUSY); 983144966Svkashyap 984144966Svkashyap req->req_handle.osl_req_ctxt = req; 985144966Svkashyap req->orig_req = buf; 986144966Svkashyap req->flags |= TW_OSLI_REQ_FLAGS_PASSTHRU; 987144966Svkashyap 988144966Svkashyap req_pkt = &(req->req_pkt); 989144966Svkashyap req_pkt->status = 0; 990144966Svkashyap req_pkt->tw_osl_callback = tw_osl_complete_passthru; 991144966Svkashyap /* Let the Common Layer retry the request on cmd queue full. */ 992144966Svkashyap req_pkt->flags |= TW_CL_REQ_RETRY_ON_BUSY; 993144966Svkashyap 994144966Svkashyap pt_req = &(req_pkt->gen_req_pkt.pt_req); 995144966Svkashyap /* 996144966Svkashyap * Make sure that the data buffer sent to firmware is a 997144966Svkashyap * 512 byte multiple in size. 998144966Svkashyap */ 999144966Svkashyap data_buf_size_adjusted = 1000144966Svkashyap (user_buf->driver_pkt.buffer_length + 1001144966Svkashyap (sc->sg_size_factor - 1)) & ~(sc->sg_size_factor - 1); 1002144966Svkashyap if ((req->length = data_buf_size_adjusted)) { 1003144966Svkashyap if ((req->data = malloc(data_buf_size_adjusted, 1004144966Svkashyap TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) { 1005144966Svkashyap error = ENOMEM; 1006144966Svkashyap tw_osli_printf(sc, "error = %d", 1007144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1008144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1009144966Svkashyap 0x2016, 1010144966Svkashyap "Could not alloc mem for " 1011144966Svkashyap "fw_passthru data_buf", 1012144966Svkashyap error); 1013144966Svkashyap goto fw_passthru_err; 1014144966Svkashyap } 1015144966Svkashyap /* Copy the payload. */ 1016144966Svkashyap if ((error = copyin((TW_VOID *)(user_buf->pdata), 1017144966Svkashyap req->data, 1018144966Svkashyap user_buf->driver_pkt.buffer_length)) != 0) { 1019144966Svkashyap tw_osli_printf(sc, "error = %d", 1020144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1021144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1022144966Svkashyap 0x2017, 1023144966Svkashyap "Could not copyin fw_passthru data_buf", 1024144966Svkashyap error); 1025144966Svkashyap goto fw_passthru_err; 1026144966Svkashyap } 1027144966Svkashyap pt_req->sgl_entries = 1; /* will be updated during mapping */ 1028144966Svkashyap req->flags |= (TW_OSLI_REQ_FLAGS_DATA_IN | 1029144966Svkashyap TW_OSLI_REQ_FLAGS_DATA_OUT); 1030144966Svkashyap } else 1031144966Svkashyap pt_req->sgl_entries = 0; /* no payload */ 1032144966Svkashyap 1033144966Svkashyap pt_req->cmd_pkt = (TW_VOID *)(&(user_buf->cmd_pkt)); 1034144966Svkashyap pt_req->cmd_pkt_length = sizeof(struct tw_cl_command_packet); 1035144966Svkashyap 1036144966Svkashyap if ((error = tw_osli_map_request(req))) 1037144966Svkashyap goto fw_passthru_err; 1038144966Svkashyap 1039144966Svkashyap end_time = tw_osl_get_local_time() + timeout; 1040144966Svkashyap while (req->state != TW_OSLI_REQ_STATE_COMPLETE) { 1041208969Sdelphij mtx_lock(req->ioctl_wake_timeout_lock); 1042144966Svkashyap req->flags |= TW_OSLI_REQ_FLAGS_SLEEPING; 1043144966Svkashyap 1044208969Sdelphij error = mtx_sleep(req, req->ioctl_wake_timeout_lock, 0, 1045208969Sdelphij "twa_passthru", timeout*hz); 1046208969Sdelphij mtx_unlock(req->ioctl_wake_timeout_lock); 1047208969Sdelphij 1048144966Svkashyap if (!(req->flags & TW_OSLI_REQ_FLAGS_SLEEPING)) 1049144966Svkashyap error = 0; 1050144966Svkashyap req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING; 1051144966Svkashyap 1052144966Svkashyap if (! error) { 1053144966Svkashyap if (((error = req->error_code)) || 1054144966Svkashyap ((error = (req->state != 1055144966Svkashyap TW_OSLI_REQ_STATE_COMPLETE))) || 1056144966Svkashyap ((error = req_pkt->status))) 1057144966Svkashyap goto fw_passthru_err; 1058144966Svkashyap break; 1059144966Svkashyap } 1060144966Svkashyap 1061144966Svkashyap if (req_pkt->status) { 1062144966Svkashyap error = req_pkt->status; 1063144966Svkashyap goto fw_passthru_err; 1064144966Svkashyap } 1065144966Svkashyap 1066144966Svkashyap if (error == EWOULDBLOCK) { 1067144966Svkashyap /* Time out! */ 1068208969Sdelphij if ((!(req->error_code)) && 1069208969Sdelphij (req->state == TW_OSLI_REQ_STATE_COMPLETE) && 1070208969Sdelphij (!(req_pkt->status)) ) { 1071208969Sdelphij#ifdef TW_OSL_DEBUG 1072208969Sdelphij tw_osli_printf(sc, "request = %p", 1073208969Sdelphij TW_CL_SEVERITY_ERROR_STRING, 1074208969Sdelphij TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1075208969Sdelphij 0x7777, 1076208969Sdelphij "FALSE Passthru timeout!", 1077208969Sdelphij req); 1078208969Sdelphij#endif /* TW_OSL_DEBUG */ 1079208969Sdelphij error = 0; /* False error */ 1080208969Sdelphij break; 1081208969Sdelphij } 1082212008Sdelphij if (!(tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) { 1083212008Sdelphij#ifdef TW_OSL_DEBUG 1084212008Sdelphij tw_osli_printf(sc, "request = %p", 1085212008Sdelphij TW_CL_SEVERITY_ERROR_STRING, 1086212008Sdelphij TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1087212008Sdelphij 0x2018, 1088212008Sdelphij "Passthru request timed out!", 1089212008Sdelphij req); 1090212008Sdelphij#else /* TW_OSL_DEBUG */ 1091212008Sdelphij device_printf((sc)->bus_dev, "Passthru request timed out!\n"); 1092212008Sdelphij#endif /* TW_OSL_DEBUG */ 1093212008Sdelphij tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle)); 1094212008Sdelphij } 1095212008Sdelphij 1096212008Sdelphij error = 0; 1097212008Sdelphij end_time = tw_osl_get_local_time() + timeout; 1098212008Sdelphij continue; 1099144966Svkashyap /* 1100144966Svkashyap * Don't touch req after a reset. It (and any 1101212008Sdelphij * associated data) will be 1102172496Sscottl * unmapped by the callback. 1103144966Svkashyap */ 1104144966Svkashyap } 1105144966Svkashyap /* 1106144966Svkashyap * Either the request got completed, or we were woken up by a 1107144966Svkashyap * signal. Calculate the new timeout, in case it was the latter. 1108144966Svkashyap */ 1109144966Svkashyap timeout = (end_time - tw_osl_get_local_time()); 1110212008Sdelphij } /* End of while loop */ 1111144966Svkashyap 1112144966Svkashyap /* If there was a payload, copy it back. */ 1113144966Svkashyap if ((!error) && (req->length)) 1114144966Svkashyap if ((error = copyout(req->data, user_buf->pdata, 1115144966Svkashyap user_buf->driver_pkt.buffer_length))) 1116144966Svkashyap tw_osli_printf(sc, "error = %d", 1117144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1118144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1119144966Svkashyap 0x2019, 1120144966Svkashyap "Could not copyout fw_passthru data_buf", 1121144966Svkashyap error); 1122144966Svkashyap 1123144966Svkashyapfw_passthru_err: 1124144966Svkashyap 1125212008Sdelphij if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET) 1126212008Sdelphij error = EBUSY; 1127212008Sdelphij 1128144966Svkashyap user_buf->driver_pkt.os_status = error; 1129144966Svkashyap /* Free resources. */ 1130144966Svkashyap if (req->data) 1131144966Svkashyap free(req->data, TW_OSLI_MALLOC_CLASS); 1132144966Svkashyap tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 1133144966Svkashyap return(error); 1134144966Svkashyap} 1135144966Svkashyap 1136144966Svkashyap 1137144966Svkashyap 1138144966Svkashyap/* 1139144966Svkashyap * Function name: tw_osl_complete_passthru 1140144966Svkashyap * Description: Called to complete passthru requests. 1141144966Svkashyap * 1142144966Svkashyap * Input: req_handle -- ptr to request handle 1143144966Svkashyap * Output: None 1144144966Svkashyap * Return value: None 1145144966Svkashyap */ 1146144966SvkashyapTW_VOID 1147144966Svkashyaptw_osl_complete_passthru(struct tw_cl_req_handle *req_handle) 1148144966Svkashyap{ 1149144966Svkashyap struct tw_osli_req_context *req = req_handle->osl_req_ctxt; 1150212008Sdelphij struct tw_cl_req_packet *req_pkt = 1151212008Sdelphij (struct tw_cl_req_packet *)(&req->req_pkt); 1152144966Svkashyap struct twa_softc *sc = req->ctlr; 1153144966Svkashyap 1154144966Svkashyap tw_osli_dbg_dprintf(5, sc, "entered"); 1155144966Svkashyap 1156144966Svkashyap if (req->state != TW_OSLI_REQ_STATE_BUSY) { 1157144966Svkashyap tw_osli_printf(sc, "request = %p, status = %d", 1158144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1159144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1160144966Svkashyap 0x201B, 1161144966Svkashyap "Unposted command completed!!", 1162144966Svkashyap req, req->state); 1163144966Svkashyap } 1164144966Svkashyap 1165144966Svkashyap /* 1166144966Svkashyap * Remove request from the busy queue. Just mark it complete. 1167144966Svkashyap * There's no need to move it into the complete queue as we are 1168144966Svkashyap * going to be done with it right now. 1169144966Svkashyap */ 1170144966Svkashyap req->state = TW_OSLI_REQ_STATE_COMPLETE; 1171144966Svkashyap tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q); 1172144966Svkashyap 1173144966Svkashyap tw_osli_unmap_request(req); 1174144966Svkashyap 1175144966Svkashyap /* 1176144966Svkashyap * Don't do a wake up if there was an error even before the request 1177144966Svkashyap * was sent down to the Common Layer, and we hadn't gotten an 1178144966Svkashyap * EINPROGRESS. The request originator will then be returned an 1179144966Svkashyap * error, and he can do the clean-up. 1180144966Svkashyap */ 1181208969Sdelphij if ((req->error_code) && (!(req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS))) 1182144966Svkashyap return; 1183144966Svkashyap 1184144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) { 1185144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_SLEEPING) { 1186144966Svkashyap /* Wake up the sleeping command originator. */ 1187144966Svkashyap tw_osli_dbg_dprintf(5, sc, 1188144966Svkashyap "Waking up originator of request %p", req); 1189144966Svkashyap req->flags &= ~TW_OSLI_REQ_FLAGS_SLEEPING; 1190144966Svkashyap wakeup_one(req); 1191144966Svkashyap } else { 1192144966Svkashyap /* 1193208969Sdelphij * If the request completed even before mtx_sleep 1194144966Svkashyap * was called, simply return. 1195144966Svkashyap */ 1196144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED) 1197144966Svkashyap return; 1198144966Svkashyap 1199212008Sdelphij if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET) 1200212008Sdelphij return; 1201212008Sdelphij 1202144966Svkashyap tw_osli_printf(sc, "request = %p", 1203144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1204144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1205144966Svkashyap 0x201C, 1206144966Svkashyap "Passthru callback called, " 1207144966Svkashyap "and caller not sleeping", 1208144966Svkashyap req); 1209144966Svkashyap } 1210144966Svkashyap } else { 1211144966Svkashyap tw_osli_printf(sc, "request = %p", 1212144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1213144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1214144966Svkashyap 0x201D, 1215144966Svkashyap "Passthru callback called for non-passthru request", 1216144966Svkashyap req); 1217144966Svkashyap } 1218144966Svkashyap} 1219144966Svkashyap 1220144966Svkashyap 1221144966Svkashyap 1222144966Svkashyap/* 1223144966Svkashyap * Function name: tw_osli_get_request 1224144966Svkashyap * Description: Gets a request pkt from the free queue. 1225144966Svkashyap * 1226144966Svkashyap * Input: sc -- ptr to OSL internal ctlr context 1227144966Svkashyap * Output: None 1228144966Svkashyap * Return value: ptr to request pkt -- success 1229144966Svkashyap * NULL -- failure 1230144966Svkashyap */ 1231144966Svkashyapstruct tw_osli_req_context * 1232144966Svkashyaptw_osli_get_request(struct twa_softc *sc) 1233144966Svkashyap{ 1234144966Svkashyap struct tw_osli_req_context *req; 1235144966Svkashyap 1236144966Svkashyap tw_osli_dbg_dprintf(4, sc, "entered"); 1237144966Svkashyap 1238144966Svkashyap /* Get a free request packet. */ 1239144966Svkashyap req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q); 1240144966Svkashyap 1241144966Svkashyap /* Initialize some fields to their defaults. */ 1242144966Svkashyap if (req) { 1243144966Svkashyap req->req_handle.osl_req_ctxt = NULL; 1244144966Svkashyap req->req_handle.cl_req_ctxt = NULL; 1245208969Sdelphij req->req_handle.is_io = 0; 1246144966Svkashyap req->data = NULL; 1247144966Svkashyap req->length = 0; 1248212008Sdelphij req->deadline = 0; 1249144966Svkashyap req->real_data = NULL; 1250144966Svkashyap req->real_length = 0; 1251144966Svkashyap req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */ 1252144966Svkashyap req->flags = 0; 1253144966Svkashyap req->error_code = 0; 1254144966Svkashyap req->orig_req = NULL; 1255144966Svkashyap 1256144966Svkashyap bzero(&(req->req_pkt), sizeof(struct tw_cl_req_packet)); 1257144966Svkashyap 1258144966Svkashyap } 1259144966Svkashyap return(req); 1260144966Svkashyap} 1261144966Svkashyap 1262144966Svkashyap 1263144966Svkashyap 1264144966Svkashyap/* 1265144966Svkashyap * Function name: twa_map_load_data_callback 1266144966Svkashyap * Description: Callback of bus_dmamap_load for the buffer associated 1267144966Svkashyap * with data. Updates the cmd pkt (size/sgl_entries 1268144966Svkashyap * fields, as applicable) to reflect the number of sg 1269144966Svkashyap * elements. 1270144966Svkashyap * 1271144966Svkashyap * Input: arg -- ptr to OSL internal request context 1272144966Svkashyap * segs -- ptr to a list of segment descriptors 1273144966Svkashyap * nsegments--# of segments 1274144966Svkashyap * error -- 0 if no errors encountered before callback, 1275144966Svkashyap * non-zero if errors were encountered 1276144966Svkashyap * Output: None 1277144966Svkashyap * Return value: None 1278144966Svkashyap */ 1279144966Svkashyapstatic TW_VOID 1280144966Svkashyaptwa_map_load_data_callback(TW_VOID *arg, bus_dma_segment_t *segs, 1281144966Svkashyap TW_INT32 nsegments, TW_INT32 error) 1282144966Svkashyap{ 1283144966Svkashyap struct tw_osli_req_context *req = 1284144966Svkashyap (struct tw_osli_req_context *)arg; 1285144966Svkashyap struct twa_softc *sc = req->ctlr; 1286144966Svkashyap struct tw_cl_req_packet *req_pkt = &(req->req_pkt); 1287144966Svkashyap 1288144966Svkashyap tw_osli_dbg_dprintf(10, sc, "entered"); 1289144966Svkashyap 1290212008Sdelphij if (error == EINVAL) { 1291212008Sdelphij req->error_code = error; 1292212008Sdelphij return; 1293212008Sdelphij } 1294212008Sdelphij 1295144966Svkashyap /* Mark the request as currently being processed. */ 1296144966Svkashyap req->state = TW_OSLI_REQ_STATE_BUSY; 1297144966Svkashyap /* Move the request into the busy queue. */ 1298144966Svkashyap tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q); 1299144966Svkashyap 1300144966Svkashyap req->flags |= TW_OSLI_REQ_FLAGS_MAPPED; 1301144966Svkashyap 1302144966Svkashyap if (error == EFBIG) { 1303144966Svkashyap req->error_code = error; 1304144966Svkashyap goto out; 1305144966Svkashyap } 1306144966Svkashyap 1307144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) { 1308144966Svkashyap struct tw_cl_passthru_req_packet *pt_req; 1309144966Svkashyap 1310144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) 1311144966Svkashyap bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map, 1312144966Svkashyap BUS_DMASYNC_PREREAD); 1313144966Svkashyap 1314144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) { 1315144966Svkashyap /* 1316144966Svkashyap * If we're using an alignment buffer, and we're 1317144966Svkashyap * writing data, copy the real data out. 1318144966Svkashyap */ 1319144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) 1320144966Svkashyap bcopy(req->real_data, req->data, req->real_length); 1321144966Svkashyap bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map, 1322144966Svkashyap BUS_DMASYNC_PREWRITE); 1323144966Svkashyap } 1324144966Svkashyap 1325144966Svkashyap pt_req = &(req_pkt->gen_req_pkt.pt_req); 1326144966Svkashyap pt_req->sg_list = (TW_UINT8 *)segs; 1327144966Svkashyap pt_req->sgl_entries += (nsegments - 1); 1328144966Svkashyap error = tw_cl_fw_passthru(&(sc->ctlr_handle), req_pkt, 1329144966Svkashyap &(req->req_handle)); 1330144966Svkashyap } else { 1331144966Svkashyap struct tw_cl_scsi_req_packet *scsi_req; 1332144966Svkashyap 1333144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) 1334144966Svkashyap bus_dmamap_sync(sc->dma_tag, req->dma_map, 1335144966Svkashyap BUS_DMASYNC_PREREAD); 1336144966Svkashyap 1337144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) { 1338144966Svkashyap /* 1339144966Svkashyap * If we're using an alignment buffer, and we're 1340144966Svkashyap * writing data, copy the real data out. 1341144966Svkashyap */ 1342144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) 1343144966Svkashyap bcopy(req->real_data, req->data, req->real_length); 1344144966Svkashyap bus_dmamap_sync(sc->dma_tag, req->dma_map, 1345144966Svkashyap BUS_DMASYNC_PREWRITE); 1346144966Svkashyap } 1347144966Svkashyap 1348144966Svkashyap scsi_req = &(req_pkt->gen_req_pkt.scsi_req); 1349144966Svkashyap scsi_req->sg_list = (TW_UINT8 *)segs; 1350144966Svkashyap scsi_req->sgl_entries += (nsegments - 1); 1351144966Svkashyap error = tw_cl_start_io(&(sc->ctlr_handle), req_pkt, 1352144966Svkashyap &(req->req_handle)); 1353144966Svkashyap } 1354144966Svkashyap 1355144966Svkashyapout: 1356144966Svkashyap if (error) { 1357144966Svkashyap req->error_code = error; 1358144966Svkashyap req_pkt->tw_osl_callback(&(req->req_handle)); 1359144966Svkashyap /* 1360144966Svkashyap * If the caller had been returned EINPROGRESS, and he has 1361144966Svkashyap * registered a callback for handling completion, the callback 1362144966Svkashyap * will never get called because we were unable to submit the 1363144966Svkashyap * request. So, free up the request right here. 1364144966Svkashyap */ 1365144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_IN_PROGRESS) 1366144966Svkashyap tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 1367144966Svkashyap } 1368144966Svkashyap} 1369144966Svkashyap 1370144966Svkashyap 1371144966Svkashyap 1372144966Svkashyap/* 1373144966Svkashyap * Function name: twa_map_load_callback 1374144966Svkashyap * Description: Callback of bus_dmamap_load for the buffer associated 1375144966Svkashyap * with a cmd pkt. 1376144966Svkashyap * 1377144966Svkashyap * Input: arg -- ptr to variable to hold phys addr 1378144966Svkashyap * segs -- ptr to a list of segment descriptors 1379144966Svkashyap * nsegments--# of segments 1380144966Svkashyap * error -- 0 if no errors encountered before callback, 1381144966Svkashyap * non-zero if errors were encountered 1382144966Svkashyap * Output: None 1383144966Svkashyap * Return value: None 1384144966Svkashyap */ 1385144966Svkashyapstatic TW_VOID 1386144966Svkashyaptwa_map_load_callback(TW_VOID *arg, bus_dma_segment_t *segs, 1387144966Svkashyap TW_INT32 nsegments, TW_INT32 error) 1388144966Svkashyap{ 1389208969Sdelphij *((bus_addr_t *)arg) = segs[0].ds_addr; 1390144966Svkashyap} 1391144966Svkashyap 1392144966Svkashyap 1393144966Svkashyap 1394144966Svkashyap/* 1395144966Svkashyap * Function name: tw_osli_map_request 1396144966Svkashyap * Description: Maps a cmd pkt and data associated with it, into 1397144966Svkashyap * DMA'able memory. 1398144966Svkashyap * 1399144966Svkashyap * Input: req -- ptr to request pkt 1400144966Svkashyap * Output: None 1401144966Svkashyap * Return value: 0 -- success 1402144966Svkashyap * non-zero-- failure 1403144966Svkashyap */ 1404144966SvkashyapTW_INT32 1405144966Svkashyaptw_osli_map_request(struct tw_osli_req_context *req) 1406144966Svkashyap{ 1407144966Svkashyap struct twa_softc *sc = req->ctlr; 1408144966Svkashyap TW_INT32 error = 0; 1409144966Svkashyap 1410144966Svkashyap tw_osli_dbg_dprintf(10, sc, "entered"); 1411144966Svkashyap 1412144966Svkashyap /* If the command involves data, map that too. */ 1413144966Svkashyap if (req->data != NULL) { 1414144966Svkashyap /* 1415144966Svkashyap * It's sufficient for the data pointer to be 4-byte aligned 1416144966Svkashyap * to work with 9000. However, if 4-byte aligned addresses 1417144966Svkashyap * are passed to bus_dmamap_load, we can get back sg elements 1418144966Svkashyap * that are not 512-byte multiples in size. So, we will let 1419144966Svkashyap * only those buffers that are 512-byte aligned to pass 1420144966Svkashyap * through, and bounce the rest, so as to make sure that we 1421144966Svkashyap * always get back sg elements that are 512-byte multiples 1422144966Svkashyap * in size. 1423144966Svkashyap */ 1424144966Svkashyap if (((vm_offset_t)req->data % sc->sg_size_factor) || 1425144966Svkashyap (req->length % sc->sg_size_factor)) { 1426144966Svkashyap req->flags |= TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED; 1427144966Svkashyap /* Save original data pointer and length. */ 1428144966Svkashyap req->real_data = req->data; 1429144966Svkashyap req->real_length = req->length; 1430144966Svkashyap req->length = (req->length + 1431144966Svkashyap (sc->sg_size_factor - 1)) & 1432144966Svkashyap ~(sc->sg_size_factor - 1); 1433144966Svkashyap req->data = malloc(req->length, TW_OSLI_MALLOC_CLASS, 1434144966Svkashyap M_NOWAIT); 1435144966Svkashyap if (req->data == NULL) { 1436144966Svkashyap tw_osli_printf(sc, "error = %d", 1437144966Svkashyap TW_CL_SEVERITY_ERROR_STRING, 1438144966Svkashyap TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1439144966Svkashyap 0x201E, 1440144966Svkashyap "Failed to allocate memory " 1441144966Svkashyap "for bounce buffer", 1442144966Svkashyap ENOMEM); 1443144966Svkashyap /* Restore original data pointer and length. */ 1444144966Svkashyap req->data = req->real_data; 1445144966Svkashyap req->length = req->real_length; 1446144966Svkashyap return(ENOMEM); 1447144966Svkashyap } 1448144966Svkashyap } 1449144966Svkashyap 1450144966Svkashyap /* 1451144966Svkashyap * Map the data buffer into bus space and build the SG list. 1452144966Svkashyap */ 1453144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) { 1454144966Svkashyap /* Lock against multiple simultaneous ioctl calls. */ 1455144966Svkashyap mtx_lock_spin(sc->io_lock); 1456144966Svkashyap error = bus_dmamap_load(sc->ioctl_tag, sc->ioctl_map, 1457144966Svkashyap req->data, req->length, 1458144966Svkashyap twa_map_load_data_callback, req, 1459144966Svkashyap BUS_DMA_WAITOK); 1460144966Svkashyap mtx_unlock_spin(sc->io_lock); 1461251874Sscottl } else if (req->flags & TW_OSLI_REQ_FLAGS_CCB) { 1462251874Sscottl error = bus_dmamap_load_ccb(sc->dma_tag, req->dma_map, 1463251938Smav req->orig_req, twa_map_load_data_callback, req, 1464251874Sscottl BUS_DMA_WAITOK); 1465144966Svkashyap } else { 1466144966Svkashyap /* 1467144966Svkashyap * There's only one CAM I/O thread running at a time. 1468144966Svkashyap * So, there's no need to hold the io_lock. 1469144966Svkashyap */ 1470144966Svkashyap error = bus_dmamap_load(sc->dma_tag, req->dma_map, 1471144966Svkashyap req->data, req->length, 1472144966Svkashyap twa_map_load_data_callback, req, 1473144966Svkashyap BUS_DMA_WAITOK); 1474144966Svkashyap } 1475144966Svkashyap 1476144966Svkashyap if (!error) 1477144966Svkashyap error = req->error_code; 1478144966Svkashyap else { 1479144966Svkashyap if (error == EINPROGRESS) { 1480144966Svkashyap /* 1481144966Svkashyap * Specifying sc->io_lock as the lockfuncarg 1482144966Svkashyap * in ...tag_create should protect the access 1483144966Svkashyap * of ...FLAGS_MAPPED from the callback. 1484144966Svkashyap */ 1485144966Svkashyap mtx_lock_spin(sc->io_lock); 1486208969Sdelphij if (!(req->flags & TW_OSLI_REQ_FLAGS_MAPPED)) 1487208969Sdelphij req->flags |= TW_OSLI_REQ_FLAGS_IN_PROGRESS; 1488208969Sdelphij tw_osli_disallow_new_requests(sc, &(req->req_handle)); 1489144966Svkashyap mtx_unlock_spin(sc->io_lock); 1490144966Svkashyap error = 0; 1491144966Svkashyap } else { 1492212008Sdelphij tw_osli_printf(sc, "error = %d", 1493212008Sdelphij TW_CL_SEVERITY_ERROR_STRING, 1494212008Sdelphij TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1495212008Sdelphij 0x9999, 1496212008Sdelphij "Failed to map DMA memory " 1497212008Sdelphij "for I/O request", 1498212008Sdelphij error); 1499212008Sdelphij req->flags |= TW_OSLI_REQ_FLAGS_FAILED; 1500144966Svkashyap /* Free alignment buffer if it was used. */ 1501144966Svkashyap if (req->flags & 1502144966Svkashyap TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) { 1503144966Svkashyap free(req->data, TW_OSLI_MALLOC_CLASS); 1504144966Svkashyap /* 1505144966Svkashyap * Restore original data pointer 1506144966Svkashyap * and length. 1507144966Svkashyap */ 1508144966Svkashyap req->data = req->real_data; 1509144966Svkashyap req->length = req->real_length; 1510144966Svkashyap } 1511144966Svkashyap } 1512144966Svkashyap } 1513144966Svkashyap 1514144966Svkashyap } else { 1515144966Svkashyap /* Mark the request as currently being processed. */ 1516144966Svkashyap req->state = TW_OSLI_REQ_STATE_BUSY; 1517144966Svkashyap /* Move the request into the busy queue. */ 1518144966Svkashyap tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q); 1519144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) 1520144966Svkashyap error = tw_cl_fw_passthru(&sc->ctlr_handle, 1521144966Svkashyap &(req->req_pkt), &(req->req_handle)); 1522144966Svkashyap else 1523144966Svkashyap error = tw_cl_start_io(&sc->ctlr_handle, 1524144966Svkashyap &(req->req_pkt), &(req->req_handle)); 1525144966Svkashyap if (error) { 1526144966Svkashyap req->error_code = error; 1527144966Svkashyap req->req_pkt.tw_osl_callback(&(req->req_handle)); 1528144966Svkashyap } 1529144966Svkashyap } 1530144966Svkashyap return(error); 1531144966Svkashyap} 1532144966Svkashyap 1533144966Svkashyap 1534144966Svkashyap 1535144966Svkashyap/* 1536144966Svkashyap * Function name: tw_osli_unmap_request 1537144966Svkashyap * Description: Undoes the mapping done by tw_osli_map_request. 1538144966Svkashyap * 1539144966Svkashyap * Input: req -- ptr to request pkt 1540144966Svkashyap * Output: None 1541144966Svkashyap * Return value: None 1542144966Svkashyap */ 1543144966SvkashyapTW_VOID 1544144966Svkashyaptw_osli_unmap_request(struct tw_osli_req_context *req) 1545144966Svkashyap{ 1546144966Svkashyap struct twa_softc *sc = req->ctlr; 1547144966Svkashyap 1548144966Svkashyap tw_osli_dbg_dprintf(10, sc, "entered"); 1549144966Svkashyap 1550144966Svkashyap /* If the command involved data, unmap that too. */ 1551144966Svkashyap if (req->data != NULL) { 1552144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_PASSTHRU) { 1553144966Svkashyap /* Lock against multiple simultaneous ioctl calls. */ 1554144966Svkashyap mtx_lock_spin(sc->io_lock); 1555144966Svkashyap 1556144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) { 1557144966Svkashyap bus_dmamap_sync(sc->ioctl_tag, 1558144966Svkashyap sc->ioctl_map, BUS_DMASYNC_POSTREAD); 1559144966Svkashyap 1560144966Svkashyap /* 1561144966Svkashyap * If we are using a bounce buffer, and we are 1562144966Svkashyap * reading data, copy the real data in. 1563144966Svkashyap */ 1564144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) 1565144966Svkashyap bcopy(req->data, req->real_data, 1566144966Svkashyap req->real_length); 1567144966Svkashyap } 1568144966Svkashyap 1569144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) 1570144966Svkashyap bus_dmamap_sync(sc->ioctl_tag, sc->ioctl_map, 1571144966Svkashyap BUS_DMASYNC_POSTWRITE); 1572144966Svkashyap 1573144966Svkashyap bus_dmamap_unload(sc->ioctl_tag, sc->ioctl_map); 1574144966Svkashyap 1575144966Svkashyap mtx_unlock_spin(sc->io_lock); 1576144966Svkashyap } else { 1577144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_IN) { 1578144966Svkashyap bus_dmamap_sync(sc->dma_tag, 1579144966Svkashyap req->dma_map, BUS_DMASYNC_POSTREAD); 1580144966Svkashyap 1581144966Svkashyap /* 1582144966Svkashyap * If we are using a bounce buffer, and we are 1583144966Svkashyap * reading data, copy the real data in. 1584144966Svkashyap */ 1585144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) 1586144966Svkashyap bcopy(req->data, req->real_data, 1587144966Svkashyap req->real_length); 1588144966Svkashyap } 1589144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_OUT) 1590144966Svkashyap bus_dmamap_sync(sc->dma_tag, req->dma_map, 1591144966Svkashyap BUS_DMASYNC_POSTWRITE); 1592144966Svkashyap 1593144966Svkashyap bus_dmamap_unload(sc->dma_tag, req->dma_map); 1594144966Svkashyap } 1595144966Svkashyap } 1596144966Svkashyap 1597144966Svkashyap /* Free alignment buffer if it was used. */ 1598144966Svkashyap if (req->flags & TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) { 1599144966Svkashyap free(req->data, TW_OSLI_MALLOC_CLASS); 1600144966Svkashyap /* Restore original data pointer and length. */ 1601144966Svkashyap req->data = req->real_data; 1602144966Svkashyap req->length = req->real_length; 1603144966Svkashyap } 1604144966Svkashyap} 1605144966Svkashyap 1606144966Svkashyap 1607144966Svkashyap 1608144966Svkashyap#ifdef TW_OSL_DEBUG 1609144966Svkashyap 1610144966SvkashyapTW_VOID twa_report_stats(TW_VOID); 1611144966SvkashyapTW_VOID twa_reset_stats(TW_VOID); 1612144966SvkashyapTW_VOID tw_osli_print_ctlr_stats(struct twa_softc *sc); 1613144966SvkashyapTW_VOID twa_print_req_info(struct tw_osli_req_context *req); 1614144966Svkashyap 1615144966Svkashyap 1616144966Svkashyap/* 1617144966Svkashyap * Function name: twa_report_stats 1618144966Svkashyap * Description: For being called from ddb. Calls functions that print 1619144966Svkashyap * OSL and CL internal stats for the controller. 1620144966Svkashyap * 1621144966Svkashyap * Input: None 1622144966Svkashyap * Output: None 1623144966Svkashyap * Return value: None 1624144966Svkashyap */ 1625144966SvkashyapTW_VOID 1626144966Svkashyaptwa_report_stats(TW_VOID) 1627144966Svkashyap{ 1628144966Svkashyap struct twa_softc *sc; 1629144966Svkashyap TW_INT32 i; 1630144966Svkashyap 1631144966Svkashyap for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) { 1632144966Svkashyap tw_osli_print_ctlr_stats(sc); 1633144966Svkashyap tw_cl_print_ctlr_stats(&sc->ctlr_handle); 1634144966Svkashyap } 1635144966Svkashyap} 1636144966Svkashyap 1637144966Svkashyap 1638144966Svkashyap 1639144966Svkashyap/* 1640144966Svkashyap * Function name: tw_osli_print_ctlr_stats 1641144966Svkashyap * Description: For being called from ddb. Prints OSL controller stats 1642144966Svkashyap * 1643144966Svkashyap * Input: sc -- ptr to OSL internal controller context 1644144966Svkashyap * Output: None 1645144966Svkashyap * Return value: None 1646144966Svkashyap */ 1647144966SvkashyapTW_VOID 1648144966Svkashyaptw_osli_print_ctlr_stats(struct twa_softc *sc) 1649144966Svkashyap{ 1650144966Svkashyap twa_printf(sc, "osl_ctlr_ctxt = %p\n", sc); 1651144966Svkashyap twa_printf(sc, "OSLq type current max\n"); 1652144966Svkashyap twa_printf(sc, "free %04d %04d\n", 1653144966Svkashyap sc->q_stats[TW_OSLI_FREE_Q].cur_len, 1654144966Svkashyap sc->q_stats[TW_OSLI_FREE_Q].max_len); 1655144966Svkashyap twa_printf(sc, "busy %04d %04d\n", 1656144966Svkashyap sc->q_stats[TW_OSLI_BUSY_Q].cur_len, 1657144966Svkashyap sc->q_stats[TW_OSLI_BUSY_Q].max_len); 1658144966Svkashyap} 1659144966Svkashyap 1660144966Svkashyap 1661144966Svkashyap 1662144966Svkashyap/* 1663144966Svkashyap * Function name: twa_print_req_info 1664144966Svkashyap * Description: For being called from ddb. Calls functions that print 1665144966Svkashyap * OSL and CL internal details for the request. 1666144966Svkashyap * 1667144966Svkashyap * Input: req -- ptr to OSL internal request context 1668144966Svkashyap * Output: None 1669144966Svkashyap * Return value: None 1670144966Svkashyap */ 1671144966SvkashyapTW_VOID 1672144966Svkashyaptwa_print_req_info(struct tw_osli_req_context *req) 1673144966Svkashyap{ 1674144966Svkashyap struct twa_softc *sc = req->ctlr; 1675144966Svkashyap 1676144966Svkashyap twa_printf(sc, "OSL details for request:\n"); 1677144966Svkashyap twa_printf(sc, "osl_req_ctxt = %p, cl_req_ctxt = %p\n" 1678144966Svkashyap "data = %p, length = 0x%x, real_data = %p, real_length = 0x%x\n" 1679144966Svkashyap "state = 0x%x, flags = 0x%x, error = 0x%x, orig_req = %p\n" 1680144966Svkashyap "next_req = %p, prev_req = %p, dma_map = %p\n", 1681144966Svkashyap req->req_handle.osl_req_ctxt, req->req_handle.cl_req_ctxt, 1682144966Svkashyap req->data, req->length, req->real_data, req->real_length, 1683144966Svkashyap req->state, req->flags, req->error_code, req->orig_req, 1684144966Svkashyap req->link.next, req->link.prev, req->dma_map); 1685144966Svkashyap tw_cl_print_req_info(&(req->req_handle)); 1686144966Svkashyap} 1687144966Svkashyap 1688144966Svkashyap 1689144966Svkashyap 1690144966Svkashyap/* 1691144966Svkashyap * Function name: twa_reset_stats 1692144966Svkashyap * Description: For being called from ddb. 1693144966Svkashyap * Resets some OSL controller stats. 1694144966Svkashyap * 1695144966Svkashyap * Input: None 1696144966Svkashyap * Output: None 1697144966Svkashyap * Return value: None 1698144966Svkashyap */ 1699144966SvkashyapTW_VOID 1700144966Svkashyaptwa_reset_stats(TW_VOID) 1701144966Svkashyap{ 1702144966Svkashyap struct twa_softc *sc; 1703144966Svkashyap TW_INT32 i; 1704144966Svkashyap 1705144966Svkashyap for (i = 0; (sc = devclass_get_softc(twa_devclass, i)) != NULL; i++) { 1706144966Svkashyap sc->q_stats[TW_OSLI_FREE_Q].max_len = 0; 1707144966Svkashyap sc->q_stats[TW_OSLI_BUSY_Q].max_len = 0; 1708144966Svkashyap tw_cl_reset_stats(&sc->ctlr_handle); 1709144966Svkashyap } 1710144966Svkashyap} 1711144966Svkashyap 1712144966Svkashyap#endif /* TW_OSL_DEBUG */ 1713