1 /* 2 * Copyright (c) 2010, LSI Corp. 3 * All rights reserved. 4 * Author : Manjunath Ranganathaiah 5 * Support: freebsdraid@lsi.com 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of the <ORGANIZATION> nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/dev/tws/tws.c,v 1.3 2007/05/09 04:16:32 mrangana Exp $ 35 */ 36 37 #include <dev/raid/tws/tws.h> 38 #include <dev/raid/tws/tws_services.h> 39 #include <dev/raid/tws/tws_hdm.h> 40 41 #include <bus/cam/cam.h> 42 #include <bus/cam/cam_ccb.h> 43 44 static int tws_msi_enable = 1; 45 46 MALLOC_DEFINE(M_TWS, "twsbuf", "buffers used by tws driver"); 47 int tws_queue_depth = TWS_MAX_REQS; 48 49 /* externs */ 50 extern int tws_cam_attach(struct tws_softc *sc); 51 extern void tws_cam_detach(struct tws_softc *sc); 52 extern int tws_init_ctlr(struct tws_softc *sc); 53 extern boolean tws_ctlr_ready(struct tws_softc *sc); 54 extern void tws_turn_off_interrupts(struct tws_softc *sc); 55 extern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 56 u_int8_t q_type ); 57 extern struct tws_request *tws_q_remove_request(struct tws_softc *sc, 58 struct tws_request *req, u_int8_t q_type ); 59 extern struct tws_request *tws_q_remove_head(struct tws_softc *sc, 60 u_int8_t q_type ); 61 extern boolean tws_get_response(struct tws_softc *sc, u_int16_t *req_id); 62 extern boolean tws_ctlr_reset(struct tws_softc *sc); 63 extern void tws_intr(void *arg); 64 extern int tws_use_32bit_sgls; 65 66 67 struct tws_request *tws_get_request(struct tws_softc *sc, u_int16_t type); 68 int tws_init_connect(struct tws_softc *sc, u_int16_t mc); 69 void tws_send_event(struct tws_softc *sc, u_int8_t event); 70 uint8_t tws_get_state(struct tws_softc *sc); 71 void tws_release_request(struct tws_request *req); 72 73 74 75 /* Function prototypes */ 76 static d_open_t tws_open; 77 static d_close_t tws_close; 78 static d_read_t tws_read; 79 static d_write_t tws_write; 80 extern d_ioctl_t tws_ioctl; 81 82 static int tws_init(struct tws_softc *sc); 83 static void tws_dmamap_cmds_load_cbfn(void *arg, bus_dma_segment_t *segs, 84 int nseg, int error); 85 86 static int tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size); 87 static int tws_init_aen_q(struct tws_softc *sc); 88 static int tws_init_trace_q(struct tws_softc *sc); 89 static int tws_setup_irq(struct tws_softc *sc); 90 91 92 /* Character device entry points */ 93 94 static struct dev_ops tws_ops = { 95 { "tws", 0, 0 }, 96 .d_open = tws_open, 97 .d_close = tws_close, 98 .d_read = tws_read, 99 .d_write = tws_write, 100 .d_ioctl = tws_ioctl, 101 }; 102 103 /* 104 * In the cdevsw routines, we find our softc by using the si_drv1 member 105 * of struct cdev. We set this variable to point to our softc in our 106 * attach routine when we create the /dev entry. 107 */ 108 109 int 110 tws_open(struct dev_open_args *ap) 111 { 112 cdev_t dev = ap->a_head.a_dev; 113 struct tws_softc *sc = dev->si_drv1; 114 115 if ( sc ) 116 TWS_TRACE_DEBUG(sc, "entry", dev, oflags); 117 return (0); 118 } 119 120 int 121 tws_close(struct dev_close_args *ap) 122 { 123 cdev_t dev = ap->a_head.a_dev; 124 struct tws_softc *sc = dev->si_drv1; 125 126 if ( sc ) 127 TWS_TRACE_DEBUG(sc, "entry", dev, fflag); 128 return (0); 129 } 130 131 int 132 tws_read(struct dev_read_args *ap) 133 { 134 cdev_t dev = ap->a_head.a_dev; 135 struct tws_softc *sc = dev->si_drv1; 136 137 if ( sc ) 138 TWS_TRACE_DEBUG(sc, "entry", dev, ioflag); 139 return (0); 140 } 141 142 int 143 tws_write(struct dev_write_args *ap) 144 { 145 cdev_t dev = ap->a_head.a_dev; 146 struct tws_softc *sc = dev->si_drv1; 147 148 if ( sc ) 149 TWS_TRACE_DEBUG(sc, "entry", dev, ioflag); 150 return (0); 151 } 152 153 /* PCI Support Functions */ 154 155 /* 156 * Compare the device ID of this device against the IDs that this driver 157 * supports. If there is a match, set the description and return success. 158 */ 159 static int 160 tws_probe(device_t dev) 161 { 162 static u_int8_t first_ctlr = 1; 163 164 if ((pci_get_vendor(dev) == TWS_VENDOR_ID) && 165 (pci_get_device(dev) == TWS_DEVICE_ID)) { 166 device_set_desc(dev, "LSI 3ware SAS/SATA Storage Controller"); 167 if (first_ctlr) { 168 kprintf("LSI 3ware device driver for SAS/SATA storage " 169 "controllers, version: %s\n", TWS_DRIVER_VERSION_STRING); 170 first_ctlr = 0; 171 } 172 173 return(0); 174 } 175 return (ENXIO); 176 } 177 178 /* Attach function is only called if the probe is successful. */ 179 180 static int 181 tws_attach(device_t dev) 182 { 183 struct tws_softc *sc = device_get_softc(dev); 184 u_int32_t cmd, bar; 185 int error=0; 186 187 /* no tracing yet */ 188 /* Look up our softc and initialize its fields. */ 189 sc->tws_dev = dev; 190 sc->device_id = pci_get_device(dev); 191 sc->subvendor_id = pci_get_subvendor(dev); 192 sc->subdevice_id = pci_get_subdevice(dev); 193 194 /* Intialize mutexes */ 195 lockinit(&sc->q_lock, "tws_q_lock", 0, LK_CANRECURSE); 196 lockinit(&sc->sim_lock, "tws_sim_lock", 0, LK_CANRECURSE); 197 lockinit(&sc->gen_lock, "tws_gen_lock", 0, LK_CANRECURSE); 198 lockinit(&sc->io_lock, "tws_io_lock", 0, LK_CANRECURSE); 199 200 if ( tws_init_trace_q(sc) == FAILURE ) 201 kprintf("trace init failure\n"); 202 /* send init event */ 203 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 204 tws_send_event(sc, TWS_INIT_START); 205 lockmgr(&sc->gen_lock, LK_RELEASE); 206 207 208 #if _BYTE_ORDER == _BIG_ENDIAN 209 TWS_TRACE(sc, "BIG endian", 0, 0); 210 #endif 211 SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), 212 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 213 OID_AUTO, "driver_version", CTLFLAG_RD, 214 TWS_DRIVER_VERSION_STRING, 0, "TWS driver version"); 215 216 cmd = pci_read_config(dev, PCIR_COMMAND, 2); 217 if ( (cmd & PCIM_CMD_PORTEN) == 0) { 218 tws_log(sc, PCI_COMMAND_READ); 219 goto attach_fail_1; 220 } 221 /* Force the busmaster enable bit on. */ 222 cmd |= PCIM_CMD_BUSMASTEREN; 223 pci_write_config(dev, PCIR_COMMAND, cmd, 2); 224 225 bar = pci_read_config(dev, TWS_PCI_BAR0, 4); 226 TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0); 227 bar = pci_read_config(dev, TWS_PCI_BAR1, 4); 228 bar = bar & ~TWS_BIT2; 229 TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0); 230 231 /* MFA base address is BAR2 register used for 232 * push mode. Firmware will evatualy move to 233 * pull mode during witch this needs to change 234 */ 235 #ifndef TWS_PULL_MODE_ENABLE 236 sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4); 237 sc->mfa_base = sc->mfa_base & ~TWS_BIT2; 238 TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0); 239 #endif 240 241 /* allocate MMIO register space */ 242 sc->reg_res_id = TWS_PCI_BAR1; /* BAR1 offset */ 243 if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 244 &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE)) 245 == NULL) { 246 tws_log(sc, ALLOC_MEMORY_RES); 247 goto attach_fail_1; 248 } 249 sc->bus_tag = rman_get_bustag(sc->reg_res); 250 sc->bus_handle = rman_get_bushandle(sc->reg_res); 251 252 #ifndef TWS_PULL_MODE_ENABLE 253 /* Allocate bus space for inbound mfa */ 254 sc->mfa_res_id = TWS_PCI_BAR2; /* BAR2 offset */ 255 if ((sc->mfa_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 256 &(sc->mfa_res_id), 0, ~0, 0x100000, RF_ACTIVE)) 257 == NULL) { 258 tws_log(sc, ALLOC_MEMORY_RES); 259 goto attach_fail_2; 260 } 261 sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res); 262 sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res); 263 #endif 264 265 /* Allocate and register our interrupt. */ 266 if ( tws_setup_irq(sc) == FAILURE ) { 267 tws_log(sc, ALLOC_MEMORY_RES); 268 goto attach_fail_3; 269 } 270 271 /* Init callouts. */ 272 callout_init(&sc->print_stats_handle); 273 callout_init(&sc->reset_cb_handle); 274 callout_init(&sc->reinit_handle); 275 276 /* 277 * Create a /dev entry for this device. The kernel will assign us 278 * a major number automatically. We use the unit number of this 279 * device as the minor number and name the character device 280 * "tws<unit>". 281 */ 282 sc->tws_cdev = make_dev(&tws_ops, device_get_unit(dev), 283 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u", 284 device_get_unit(dev)); 285 sc->tws_cdev->si_drv1 = sc; 286 287 if ( tws_init(sc) == FAILURE ) { 288 tws_log(sc, TWS_INIT_FAILURE); 289 goto attach_fail_4; 290 } 291 if ( tws_init_ctlr(sc) == FAILURE ) { 292 tws_log(sc, TWS_CTLR_INIT_FAILURE); 293 goto attach_fail_4; 294 } 295 if ((error = tws_cam_attach(sc))) { 296 tws_log(sc, TWS_CAM_ATTACH); 297 goto attach_fail_4; 298 } 299 /* send init complete event */ 300 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 301 tws_send_event(sc, TWS_INIT_COMPLETE); 302 lockmgr(&sc->gen_lock, LK_RELEASE); 303 304 TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id); 305 return(0); 306 307 attach_fail_4: 308 if (sc->intr_handle) { 309 if ((error = bus_teardown_intr(sc->tws_dev, 310 sc->irq_res, sc->intr_handle))) 311 TWS_TRACE(sc, "bus teardown intr", 0, error); 312 } 313 destroy_dev(sc->tws_cdev); 314 dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev)); 315 attach_fail_3: 316 if (sc->irq_res) { 317 if (bus_release_resource(sc->tws_dev, 318 SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)) 319 TWS_TRACE(sc, "bus irq res", 0, 0); 320 } 321 #ifndef TWS_PULL_MODE_ENABLE 322 attach_fail_2: 323 #endif 324 if ( sc->mfa_res ){ 325 if (bus_release_resource(sc->tws_dev, 326 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res)) 327 TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id); 328 } 329 if ( sc->reg_res ){ 330 if (bus_release_resource(sc->tws_dev, 331 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)) 332 TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id); 333 } 334 attach_fail_1: 335 lockuninit(&sc->q_lock); 336 lockuninit(&sc->sim_lock); 337 lockuninit(&sc->gen_lock); 338 lockuninit(&sc->io_lock); 339 return (ENXIO); 340 } 341 342 /* Detach device. */ 343 344 static int 345 tws_detach(device_t dev) 346 { 347 struct tws_softc *sc = device_get_softc(dev); 348 int error; 349 u_int32_t reg; 350 351 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 352 353 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 354 tws_send_event(sc, TWS_UNINIT_START); 355 lockmgr(&sc->gen_lock, LK_RELEASE); 356 357 /* needs to disable interrupt before detaching from cam */ 358 tws_turn_off_interrupts(sc); 359 /* clear door bell */ 360 tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4); 361 reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4); 362 TWS_TRACE_DEBUG(sc, "turn-off-intr", reg, 0); 363 sc->obfl_q_overrun = false; 364 tws_init_connect(sc, 1); 365 366 /* Teardown the state in our softc created in our attach routine. */ 367 /* Disconnect the interrupt handler. */ 368 if (sc->intr_handle) { 369 if ((error = bus_teardown_intr(sc->tws_dev, 370 sc->irq_res, sc->intr_handle))) 371 TWS_TRACE(sc, "bus teardown intr", 0, error); 372 } 373 /* Release irq resource */ 374 if (sc->irq_res) { 375 if (bus_release_resource(sc->tws_dev, 376 SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)) 377 TWS_TRACE(sc, "bus release irq resource", 0, sc->irq_res_id); 378 } 379 if (sc->intr_type == PCI_INTR_TYPE_MSI) 380 pci_release_msi(sc->tws_dev); 381 382 tws_cam_detach(sc); 383 384 /* Release memory resource */ 385 if ( sc->mfa_res ){ 386 if (bus_release_resource(sc->tws_dev, 387 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res)) 388 TWS_TRACE(sc, "bus release mem resource", 0, sc->mfa_res_id); 389 } 390 if ( sc->reg_res ){ 391 if (bus_release_resource(sc->tws_dev, 392 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)) 393 TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id); 394 } 395 396 kfree(sc->reqs, M_TWS); 397 kfree(sc->sense_bufs, M_TWS); 398 kfree(sc->scan_ccb, M_TWS); 399 kfree(sc->aen_q.q, M_TWS); 400 kfree(sc->trace_q.q, M_TWS); 401 lockuninit(&sc->q_lock); 402 lockuninit(&sc->sim_lock); 403 lockuninit(&sc->gen_lock); 404 lockuninit(&sc->io_lock); 405 destroy_dev(sc->tws_cdev); 406 dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev)); 407 return (0); 408 } 409 410 static int 411 tws_setup_irq(struct tws_softc *sc) 412 { 413 u_int16_t cmd; 414 u_int irq_flags; 415 416 cmd = pci_read_config(sc->tws_dev, PCIR_COMMAND, 2); 417 418 if (tws_msi_enable) 419 cmd |= 0x0400; 420 else 421 cmd &= ~0x0400; 422 pci_write_config(sc->tws_dev, PCIR_COMMAND, cmd, 2); 423 sc->irq_res = 0; 424 sc->intr_type = pci_alloc_1intr(sc->tws_dev, tws_msi_enable, 425 &sc->irq_res_id, &irq_flags); 426 sc->irq_res = bus_alloc_resource_any(sc->tws_dev, SYS_RES_IRQ, 427 &sc->irq_res_id, irq_flags); 428 if (!sc->irq_res) 429 return(FAILURE); 430 if (bus_setup_intr(sc->tws_dev, sc->irq_res, INTR_MPSAFE, tws_intr, sc, 431 &sc->intr_handle, NULL)) { 432 tws_log(sc, SETUP_INTR_RES); 433 return(FAILURE); 434 } 435 if (sc->intr_type == PCI_INTR_TYPE_MSI) 436 device_printf(sc->tws_dev, "Using MSI\n"); 437 else 438 device_printf(sc->tws_dev, "Using legacy INTx\n"); 439 440 return(SUCCESS); 441 } 442 443 static int 444 tws_init(struct tws_softc *sc) 445 { 446 447 u_int32_t max_sg_elements; 448 u_int32_t dma_mem_size; 449 int error; 450 u_int32_t reg; 451 452 sc->seq_id = 0; 453 if ( tws_queue_depth > TWS_MAX_REQS ) 454 tws_queue_depth = TWS_MAX_REQS; 455 if (tws_queue_depth < TWS_RESERVED_REQS+1) 456 tws_queue_depth = TWS_RESERVED_REQS+1; 457 sc->is64bit = (sizeof(bus_addr_t) == 8) ? true : false; 458 max_sg_elements = (sc->is64bit && !tws_use_32bit_sgls) ? 459 TWS_MAX_64BIT_SG_ELEMENTS : 460 TWS_MAX_32BIT_SG_ELEMENTS; 461 dma_mem_size = (sizeof(struct tws_command_packet) * tws_queue_depth) + 462 (TWS_SECTOR_SIZE) ; 463 if ( bus_dma_tag_create(NULL, /* parent */ 464 TWS_ALIGNMENT, /* alignment */ 465 0, /* boundary */ 466 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 467 BUS_SPACE_MAXADDR, /* highaddr */ 468 NULL, NULL, /* filter, filterarg */ 469 BUS_SPACE_MAXSIZE, /* maxsize */ 470 max_sg_elements, /* numsegs */ 471 BUS_SPACE_MAXSIZE, /* maxsegsize */ 472 0, /* flags */ 473 &sc->parent_tag /* tag */ 474 )) { 475 TWS_TRACE_DEBUG(sc, "DMA parent tag Create fail", max_sg_elements, 476 sc->is64bit); 477 return(ENOMEM); 478 } 479 /* In bound message frame requires 16byte alignment. 480 * Outbound MF's can live with 4byte alignment - for now just 481 * use 16 for both. 482 */ 483 if ( bus_dma_tag_create(sc->parent_tag, /* parent */ 484 TWS_IN_MF_ALIGNMENT, /* alignment */ 485 0, /* boundary */ 486 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 487 BUS_SPACE_MAXADDR, /* highaddr */ 488 NULL, NULL, /* filter, filterarg */ 489 dma_mem_size, /* maxsize */ 490 1, /* numsegs */ 491 BUS_SPACE_MAXSIZE, /* maxsegsize */ 492 0, /* flags */ 493 &sc->cmd_tag /* tag */ 494 )) { 495 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); 496 return(ENOMEM); 497 } 498 499 if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, 500 BUS_DMA_NOWAIT, &sc->cmd_map)) { 501 TWS_TRACE_DEBUG(sc, "DMA mem alloc fail", max_sg_elements, sc->is64bit); 502 return(ENOMEM); 503 } 504 505 /* if bus_dmamem_alloc succeeds then bus_dmamap_load will succeed */ 506 sc->dma_mem_phys=0; 507 error = bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem, 508 dma_mem_size, tws_dmamap_cmds_load_cbfn, 509 &sc->dma_mem_phys, 0); 510 511 if ( error == EINPROGRESS ) 512 TWS_TRACE_DEBUG(sc, "req queued", max_sg_elements, sc->is64bit); 513 514 /* 515 * Create a dma tag for data buffers; size will be the maximum 516 * possible I/O size (128kB). 517 */ 518 if (bus_dma_tag_create(sc->parent_tag, /* parent */ 519 TWS_ALIGNMENT, /* alignment */ 520 0, /* boundary */ 521 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 522 BUS_SPACE_MAXADDR, /* highaddr */ 523 NULL, NULL, /* filter, filterarg */ 524 TWS_MAX_IO_SIZE, /* maxsize */ 525 max_sg_elements, /* nsegments */ 526 TWS_MAX_IO_SIZE, /* maxsegsize */ 527 BUS_DMA_ALLOCALL | /* flags */ 528 BUS_DMA_ALLOCNOW | 529 BUS_DMA_PRIVBZONE | 530 BUS_DMA_PROTECTED, 531 &sc->data_tag /* tag */)) { 532 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); 533 return(ENOMEM); 534 } 535 536 sc->reqs = kmalloc(sizeof(struct tws_request) * tws_queue_depth, M_TWS, 537 M_WAITOK | M_ZERO); 538 sc->sense_bufs = kmalloc(sizeof(struct tws_sense) * tws_queue_depth, M_TWS, 539 M_WAITOK | M_ZERO); 540 sc->scan_ccb = kmalloc(sizeof(union ccb), M_TWS, M_WAITOK | M_ZERO); 541 542 if ( !tws_ctlr_ready(sc) ) 543 if( !tws_ctlr_reset(sc) ) 544 return(FAILURE); 545 546 bzero(&sc->stats, sizeof(struct tws_stats)); 547 tws_init_qs(sc); 548 tws_turn_off_interrupts(sc); 549 550 /* 551 * enable pull mode by setting bit1 . 552 * setting bit0 to 1 will enable interrupt coalesing 553 * will revisit. 554 */ 555 556 #ifdef TWS_PULL_MODE_ENABLE 557 558 reg = tws_read_reg(sc, TWS_I2O0_CTL, 4); 559 TWS_TRACE_DEBUG(sc, "i20 ctl", reg, TWS_I2O0_CTL); 560 tws_write_reg(sc, TWS_I2O0_CTL, reg | TWS_BIT1, 4); 561 562 #endif 563 564 TWS_TRACE_DEBUG(sc, "dma_mem_phys", sc->dma_mem_phys, TWS_I2O0_CTL); 565 if ( tws_init_reqs(sc, dma_mem_size) == FAILURE ) 566 return(FAILURE); 567 if ( tws_init_aen_q(sc) == FAILURE ) 568 return(FAILURE); 569 570 return(SUCCESS); 571 572 } 573 574 static int 575 tws_init_aen_q(struct tws_softc *sc) 576 { 577 sc->aen_q.head=0; 578 sc->aen_q.tail=0; 579 sc->aen_q.depth=256; 580 sc->aen_q.overflow=0; 581 sc->aen_q.q = kmalloc(sizeof(struct tws_event_packet)*sc->aen_q.depth, 582 M_TWS, M_WAITOK | M_ZERO); 583 return(SUCCESS); 584 } 585 586 static int 587 tws_init_trace_q(struct tws_softc *sc) 588 { 589 sc->trace_q.head=0; 590 sc->trace_q.tail=0; 591 sc->trace_q.depth=256; 592 sc->trace_q.overflow=0; 593 sc->trace_q.q = kmalloc(sizeof(struct tws_trace_rec)*sc->trace_q.depth, 594 M_TWS, M_WAITOK | M_ZERO); 595 return(SUCCESS); 596 } 597 598 static int 599 tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size) 600 { 601 602 struct tws_command_packet *cmd_buf; 603 cmd_buf = (struct tws_command_packet *)sc->dma_mem; 604 int i; 605 606 bzero(cmd_buf, dma_mem_size); 607 TWS_TRACE_DEBUG(sc, "phy cmd", sc->dma_mem_phys, 0); 608 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 609 for ( i=0; i< tws_queue_depth; i++) 610 { 611 if (bus_dmamap_create(sc->data_tag, 0, &sc->reqs[i].dma_map)) { 612 /* log a ENOMEM failure msg here */ 613 lockmgr(&sc->q_lock, LK_RELEASE); 614 return(FAILURE); 615 } 616 sc->reqs[i].cmd_pkt = &cmd_buf[i]; 617 618 sc->sense_bufs[i].hdr = &cmd_buf[i].hdr ; 619 sc->sense_bufs[i].hdr_pkt_phy = sc->dma_mem_phys + 620 (i * sizeof(struct tws_command_packet)); 621 sc->sense_bufs[i].posted = false; 622 623 sc->reqs[i].cmd_pkt_phy = sc->dma_mem_phys + 624 sizeof(struct tws_command_header) + 625 (i * sizeof(struct tws_command_packet)); 626 sc->reqs[i].request_id = i; 627 sc->reqs[i].sc = sc; 628 629 sc->reqs[i].cmd_pkt->hdr.header_desc.size_header = 128; 630 631 sc->reqs[i].state = TWS_REQ_STATE_FREE; 632 if ( i >= TWS_RESERVED_REQS ) 633 tws_q_insert_tail(sc, &sc->reqs[i], TWS_FREE_Q); 634 } 635 lockmgr(&sc->q_lock, LK_RELEASE); 636 return(SUCCESS); 637 } 638 639 static void 640 tws_dmamap_cmds_load_cbfn(void *arg, bus_dma_segment_t *segs, 641 int nseg, int error) 642 { 643 644 /* kprintf("command load done \n"); */ 645 646 *((bus_addr_t *)arg) = segs[0].ds_addr; 647 } 648 649 void 650 tws_send_event(struct tws_softc *sc, u_int8_t event) 651 { 652 KKASSERT(lockstatus(&sc->gen_lock, curthread) != 0); 653 TWS_TRACE_DEBUG(sc, "received event ", 0, event); 654 switch (event) { 655 656 case TWS_INIT_START: 657 sc->tws_state = TWS_INIT; 658 break; 659 660 case TWS_INIT_COMPLETE: 661 KASSERT(sc->tws_state == TWS_INIT , ("invalid state transition")); 662 sc->tws_state = TWS_ONLINE; 663 break; 664 665 case TWS_RESET_START: 666 /* multiple reset ? */ 667 KASSERT(sc->tws_state != TWS_RESET, ("invalid state transition")); 668 669 /* we can transition to reset state from any state */ 670 sc->tws_prev_state = sc->tws_state; 671 sc->tws_state = TWS_RESET; 672 break; 673 674 case TWS_RESET_COMPLETE: 675 KASSERT(sc->tws_state == TWS_RESET, ("invalid state transition")); 676 sc->tws_state = sc->tws_prev_state; 677 break; 678 679 case TWS_SCAN_FAILURE: 680 KASSERT(sc->tws_state == TWS_ONLINE , ("invalid state transition")); 681 sc->tws_state = TWS_OFFLINE; 682 break; 683 684 case TWS_UNINIT_START: 685 KASSERT(sc->tws_state == TWS_ONLINE || sc->tws_state == TWS_OFFLINE, 686 ("invalid state transition")); 687 sc->tws_state = TWS_UNINIT; 688 break; 689 } 690 691 } 692 693 uint8_t 694 tws_get_state(struct tws_softc *sc) 695 { 696 697 return((u_int8_t)sc->tws_state); 698 699 } 700 701 /* Called during system shutdown after sync. */ 702 703 static int 704 tws_shutdown(device_t dev) 705 { 706 707 struct tws_softc *sc = device_get_softc(dev); 708 709 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 710 711 tws_turn_off_interrupts(sc); 712 tws_init_connect(sc, 1); 713 714 return (0); 715 } 716 717 /* 718 * Device suspend routine. 719 */ 720 static int 721 tws_suspend(device_t dev) 722 { 723 struct tws_softc *sc = device_get_softc(dev); 724 725 if ( sc ) 726 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 727 return (0); 728 } 729 730 /* 731 * Device resume routine. 732 */ 733 static int 734 tws_resume(device_t dev) 735 { 736 737 struct tws_softc *sc = device_get_softc(dev); 738 739 if ( sc ) 740 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 741 return (0); 742 } 743 744 745 struct tws_request * 746 tws_get_request(struct tws_softc *sc, u_int16_t type) 747 { 748 struct tws_request *r = NULL; 749 750 switch ( type ) { 751 case TWS_INTERNAL_CMD_REQ : 752 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 753 r = &sc->reqs[0]; 754 if ( r->state != TWS_REQ_STATE_FREE ) { 755 r = NULL; 756 } else { 757 r->state = TWS_REQ_STATE_BUSY; 758 } 759 lockmgr(&sc->gen_lock, LK_RELEASE); 760 break; 761 case TWS_AEN_FETCH_REQ : 762 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 763 r = &sc->reqs[1]; 764 if ( r->state != TWS_REQ_STATE_FREE ) { 765 r = NULL; 766 } else { 767 r->state = TWS_REQ_STATE_BUSY; 768 } 769 lockmgr(&sc->gen_lock, LK_RELEASE); 770 break; 771 case TWS_PASSTHRU_REQ : 772 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 773 r = &sc->reqs[2]; 774 if ( r->state != TWS_REQ_STATE_FREE ) { 775 r = NULL; 776 } else { 777 r->state = TWS_REQ_STATE_BUSY; 778 } 779 lockmgr(&sc->gen_lock, LK_RELEASE); 780 break; 781 case TWS_GETSET_PARAM_REQ : 782 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 783 r = &sc->reqs[3]; 784 if ( r->state != TWS_REQ_STATE_FREE ) { 785 r = NULL; 786 } else { 787 r->state = TWS_REQ_STATE_BUSY; 788 } 789 lockmgr(&sc->gen_lock, LK_RELEASE); 790 break; 791 case TWS_SCSI_IO_REQ : 792 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 793 r = tws_q_remove_head(sc, TWS_FREE_Q); 794 if ( r ) 795 r->state = TWS_REQ_STATE_TRAN; 796 lockmgr(&sc->q_lock, LK_RELEASE); 797 break; 798 default : 799 TWS_TRACE_DEBUG(sc, "Unknown req type", 0, type); 800 r = NULL; 801 802 } 803 804 if ( r ) { 805 bzero(&r->cmd_pkt->cmd, sizeof(struct tws_command_apache)); 806 callout_init(&r->thandle); 807 r->data = NULL; 808 r->length = 0; 809 r->type = type; 810 r->flags = TWS_DIR_UNKNOWN; 811 r->error_code = TWS_REQ_ERR_INVALID; 812 r->ccb_ptr = NULL; 813 r->cb = NULL; 814 r->next = r->prev = NULL; 815 } 816 return(r); 817 } 818 819 void 820 tws_release_request(struct tws_request *req) 821 { 822 823 struct tws_softc *sc = req->sc; 824 825 TWS_TRACE_DEBUG(sc, "entry", sc, 0); 826 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 827 tws_q_insert_tail(sc, req, TWS_FREE_Q); 828 lockmgr(&sc->q_lock, LK_RELEASE); 829 } 830 831 static device_method_t tws_methods[] = { 832 /* Device interface */ 833 DEVMETHOD(device_probe, tws_probe), 834 DEVMETHOD(device_attach, tws_attach), 835 DEVMETHOD(device_detach, tws_detach), 836 DEVMETHOD(device_shutdown, tws_shutdown), 837 DEVMETHOD(device_suspend, tws_suspend), 838 DEVMETHOD(device_resume, tws_resume), 839 840 DEVMETHOD(bus_print_child, bus_generic_print_child), 841 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 842 DEVMETHOD_END 843 }; 844 845 static driver_t tws_driver = { 846 "tws", 847 tws_methods, 848 sizeof(struct tws_softc) 849 }; 850 851 852 static devclass_t tws_devclass; 853 854 /* DEFINE_CLASS_0(tws, tws_driver, tws_methods, sizeof(struct tws_softc)); */ 855 DRIVER_MODULE(tws, pci, tws_driver, tws_devclass, NULL, NULL); 856 MODULE_DEPEND(tws, cam, 1, 1, 1); 857 MODULE_DEPEND(tws, pci, 1, 1, 1); 858 859 TUNABLE_INT("hw.tws.queue_depth", &tws_queue_depth); 860 TUNABLE_INT("hw.tws.msi.enable", &tws_msi_enable); 861