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