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 cmd = cmd | 0x0400; 479 pci_write_config(sc->tws_dev, PCIR_COMMAND, cmd, 2); 480 sc->irqs = 1; 481 sc->irq_res_id[0] = 1; 482 messages = 1; 483 if (pci_alloc_msi(sc->tws_dev, &messages) != 0 ) { 484 TWS_TRACE(sc, "pci alloc msi fail", 0, messages); 485 return(FAILURE); 486 } 487 sc->irq_res[0] = bus_alloc_resource_any(sc->tws_dev, SYS_RES_IRQ, 488 &sc->irq_res_id[0], RF_SHAREABLE | RF_ACTIVE); 489 490 if ( !sc->irq_res[0] ) 491 return(FAILURE); 492 if ( tws_setup_intr(sc, sc->irqs) == FAILURE ) 493 return(FAILURE); 494 device_printf(sc->tws_dev, "Using MSI\n"); 495 break; 496 497 } 498 499 return(SUCCESS); 500 } 501 502 static int 503 tws_init(struct tws_softc *sc) 504 { 505 506 u_int32_t max_sg_elements; 507 u_int32_t dma_mem_size; 508 int error; 509 u_int32_t reg; 510 511 sc->seq_id = 0; 512 if ( tws_queue_depth > TWS_MAX_REQS ) 513 tws_queue_depth = TWS_MAX_REQS; 514 if (tws_queue_depth < TWS_RESERVED_REQS+1) 515 tws_queue_depth = TWS_RESERVED_REQS+1; 516 sc->is64bit = (sizeof(bus_addr_t) == 8) ? true : false; 517 max_sg_elements = (sc->is64bit && !tws_use_32bit_sgls) ? 518 TWS_MAX_64BIT_SG_ELEMENTS : 519 TWS_MAX_32BIT_SG_ELEMENTS; 520 dma_mem_size = (sizeof(struct tws_command_packet) * tws_queue_depth) + 521 (TWS_SECTOR_SIZE) ; 522 if ( bus_dma_tag_create(NULL, /* parent */ 523 TWS_ALIGNMENT, /* alignment */ 524 0, /* boundary */ 525 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 526 BUS_SPACE_MAXADDR, /* highaddr */ 527 NULL, NULL, /* filter, filterarg */ 528 BUS_SPACE_MAXSIZE, /* maxsize */ 529 max_sg_elements, /* numsegs */ 530 BUS_SPACE_MAXSIZE, /* maxsegsize */ 531 0, /* flags */ 532 &sc->parent_tag /* tag */ 533 )) { 534 TWS_TRACE_DEBUG(sc, "DMA parent tag Create fail", max_sg_elements, 535 sc->is64bit); 536 return(ENOMEM); 537 } 538 /* In bound message frame requires 16byte alignment. 539 * Outbound MF's can live with 4byte alignment - for now just 540 * use 16 for both. 541 */ 542 if ( bus_dma_tag_create(sc->parent_tag, /* parent */ 543 TWS_IN_MF_ALIGNMENT, /* alignment */ 544 0, /* boundary */ 545 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 546 BUS_SPACE_MAXADDR, /* highaddr */ 547 NULL, NULL, /* filter, filterarg */ 548 dma_mem_size, /* maxsize */ 549 1, /* numsegs */ 550 BUS_SPACE_MAXSIZE, /* maxsegsize */ 551 0, /* flags */ 552 &sc->cmd_tag /* tag */ 553 )) { 554 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); 555 return(ENOMEM); 556 } 557 558 if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, 559 BUS_DMA_NOWAIT, &sc->cmd_map)) { 560 TWS_TRACE_DEBUG(sc, "DMA mem alloc fail", max_sg_elements, sc->is64bit); 561 return(ENOMEM); 562 } 563 564 /* if bus_dmamem_alloc succeeds then bus_dmamap_load will succeed */ 565 sc->dma_mem_phys=0; 566 error = bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem, 567 dma_mem_size, tws_dmamap_cmds_load_cbfn, 568 &sc->dma_mem_phys, 0); 569 570 if ( error == EINPROGRESS ) 571 TWS_TRACE_DEBUG(sc, "req queued", max_sg_elements, sc->is64bit); 572 573 /* 574 * Create a dma tag for data buffers; size will be the maximum 575 * possible I/O size (128kB). 576 */ 577 if (bus_dma_tag_create(sc->parent_tag, /* parent */ 578 TWS_ALIGNMENT, /* alignment */ 579 0, /* boundary */ 580 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 581 BUS_SPACE_MAXADDR, /* highaddr */ 582 NULL, NULL, /* filter, filterarg */ 583 TWS_MAX_IO_SIZE, /* maxsize */ 584 max_sg_elements, /* nsegments */ 585 TWS_MAX_IO_SIZE, /* maxsegsize */ 586 BUS_DMA_ALLOCALL | /* flags */ 587 BUS_DMA_ALLOCNOW | 588 BUS_DMA_PRIVBZONE | 589 BUS_DMA_PROTECTED, 590 &sc->data_tag /* tag */)) { 591 TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); 592 return(ENOMEM); 593 } 594 595 sc->reqs = kmalloc(sizeof(struct tws_request) * tws_queue_depth, M_TWS, 596 M_WAITOK | M_ZERO); 597 sc->sense_bufs = kmalloc(sizeof(struct tws_sense) * tws_queue_depth, M_TWS, 598 M_WAITOK | M_ZERO); 599 sc->scan_ccb = kmalloc(sizeof(union ccb), M_TWS, M_WAITOK | M_ZERO); 600 601 if ( !tws_ctlr_ready(sc) ) 602 if( !tws_ctlr_reset(sc) ) 603 return(FAILURE); 604 605 bzero(&sc->stats, sizeof(struct tws_stats)); 606 tws_init_qs(sc); 607 tws_turn_off_interrupts(sc); 608 609 /* 610 * enable pull mode by setting bit1 . 611 * setting bit0 to 1 will enable interrupt coalesing 612 * will revisit. 613 */ 614 615 #ifdef TWS_PULL_MODE_ENABLE 616 617 reg = tws_read_reg(sc, TWS_I2O0_CTL, 4); 618 TWS_TRACE_DEBUG(sc, "i20 ctl", reg, TWS_I2O0_CTL); 619 tws_write_reg(sc, TWS_I2O0_CTL, reg | TWS_BIT1, 4); 620 621 #endif 622 623 TWS_TRACE_DEBUG(sc, "dma_mem_phys", sc->dma_mem_phys, TWS_I2O0_CTL); 624 if ( tws_init_reqs(sc, dma_mem_size) == FAILURE ) 625 return(FAILURE); 626 if ( tws_init_aen_q(sc) == FAILURE ) 627 return(FAILURE); 628 629 return(SUCCESS); 630 631 } 632 633 static int 634 tws_init_aen_q(struct tws_softc *sc) 635 { 636 sc->aen_q.head=0; 637 sc->aen_q.tail=0; 638 sc->aen_q.depth=256; 639 sc->aen_q.overflow=0; 640 sc->aen_q.q = kmalloc(sizeof(struct tws_event_packet)*sc->aen_q.depth, 641 M_TWS, M_WAITOK | M_ZERO); 642 return(SUCCESS); 643 } 644 645 static int 646 tws_init_trace_q(struct tws_softc *sc) 647 { 648 sc->trace_q.head=0; 649 sc->trace_q.tail=0; 650 sc->trace_q.depth=256; 651 sc->trace_q.overflow=0; 652 sc->trace_q.q = kmalloc(sizeof(struct tws_trace_rec)*sc->trace_q.depth, 653 M_TWS, M_WAITOK | M_ZERO); 654 return(SUCCESS); 655 } 656 657 static int 658 tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size) 659 { 660 661 struct tws_command_packet *cmd_buf; 662 cmd_buf = (struct tws_command_packet *)sc->dma_mem; 663 int i; 664 665 bzero(cmd_buf, dma_mem_size); 666 TWS_TRACE_DEBUG(sc, "phy cmd", sc->dma_mem_phys, 0); 667 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 668 for ( i=0; i< tws_queue_depth; i++) 669 { 670 if (bus_dmamap_create(sc->data_tag, 0, &sc->reqs[i].dma_map)) { 671 /* log a ENOMEM failure msg here */ 672 return(FAILURE); 673 } 674 sc->reqs[i].cmd_pkt = &cmd_buf[i]; 675 676 sc->sense_bufs[i].hdr = &cmd_buf[i].hdr ; 677 sc->sense_bufs[i].hdr_pkt_phy = sc->dma_mem_phys + 678 (i * sizeof(struct tws_command_packet)); 679 sc->sense_bufs[i].posted = false; 680 681 sc->reqs[i].cmd_pkt_phy = sc->dma_mem_phys + 682 sizeof(struct tws_command_header) + 683 (i * sizeof(struct tws_command_packet)); 684 sc->reqs[i].request_id = i; 685 sc->reqs[i].sc = sc; 686 687 sc->reqs[i].cmd_pkt->hdr.header_desc.size_header = 128; 688 689 sc->reqs[i].state = TWS_REQ_STATE_FREE; 690 if ( i >= TWS_RESERVED_REQS ) 691 tws_q_insert_tail(sc, &sc->reqs[i], TWS_FREE_Q); 692 } 693 lockmgr(&sc->q_lock, LK_RELEASE); 694 return(SUCCESS); 695 } 696 697 static void 698 tws_dmamap_cmds_load_cbfn(void *arg, bus_dma_segment_t *segs, 699 int nseg, int error) 700 { 701 702 /* kprintf("command load done \n"); */ 703 704 *((bus_addr_t *)arg) = segs[0].ds_addr; 705 } 706 707 void 708 tws_send_event(struct tws_softc *sc, u_int8_t event) 709 { 710 KKASSERT(lockstatus(&sc->gen_lock, curthread) != 0); 711 TWS_TRACE_DEBUG(sc, "received event ", 0, event); 712 switch (event) { 713 714 case TWS_INIT_START: 715 sc->tws_state = TWS_INIT; 716 break; 717 718 case TWS_INIT_COMPLETE: 719 KASSERT(sc->tws_state == TWS_INIT , ("invalid state transition")); 720 sc->tws_state = TWS_ONLINE; 721 break; 722 723 case TWS_RESET_START: 724 /* multiple reset ? */ 725 KASSERT(sc->tws_state != TWS_RESET, ("invalid state transition")); 726 727 /* we can transition to reset state from any state */ 728 sc->tws_prev_state = sc->tws_state; 729 sc->tws_state = TWS_RESET; 730 break; 731 732 case TWS_RESET_COMPLETE: 733 KASSERT(sc->tws_state == TWS_RESET, ("invalid state transition")); 734 sc->tws_state = sc->tws_prev_state; 735 break; 736 737 case TWS_SCAN_FAILURE: 738 KASSERT(sc->tws_state == TWS_ONLINE , ("invalid state transition")); 739 sc->tws_state = TWS_OFFLINE; 740 break; 741 742 case TWS_UNINIT_START: 743 KASSERT(sc->tws_state == TWS_ONLINE || sc->tws_state == TWS_OFFLINE, 744 ("invalid state transition")); 745 sc->tws_state = TWS_UNINIT; 746 break; 747 } 748 749 } 750 751 uint8_t 752 tws_get_state(struct tws_softc *sc) 753 { 754 755 return((u_int8_t)sc->tws_state); 756 757 } 758 759 /* Called during system shutdown after sync. */ 760 761 static int 762 tws_shutdown(device_t dev) 763 { 764 765 struct tws_softc *sc = device_get_softc(dev); 766 767 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 768 769 tws_turn_off_interrupts(sc); 770 tws_init_connect(sc, 1); 771 772 return (0); 773 } 774 775 /* 776 * Device suspend routine. 777 */ 778 static int 779 tws_suspend(device_t dev) 780 { 781 struct tws_softc *sc = device_get_softc(dev); 782 783 if ( sc ) 784 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 785 return (0); 786 } 787 788 /* 789 * Device resume routine. 790 */ 791 static int 792 tws_resume(device_t dev) 793 { 794 795 struct tws_softc *sc = device_get_softc(dev); 796 797 if ( sc ) 798 TWS_TRACE_DEBUG(sc, "entry", 0, 0); 799 return (0); 800 } 801 802 803 struct tws_request * 804 tws_get_request(struct tws_softc *sc, u_int16_t type) 805 { 806 struct tws_request *r = NULL; 807 808 switch ( type ) { 809 case TWS_INTERNAL_CMD_REQ : 810 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 811 r = &sc->reqs[0]; 812 if ( r->state != TWS_REQ_STATE_FREE ) { 813 r = NULL; 814 } else { 815 r->state = TWS_REQ_STATE_BUSY; 816 } 817 lockmgr(&sc->gen_lock, LK_RELEASE); 818 break; 819 case TWS_AEN_FETCH_REQ : 820 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 821 r = &sc->reqs[1]; 822 if ( r->state != TWS_REQ_STATE_FREE ) { 823 r = NULL; 824 } else { 825 r->state = TWS_REQ_STATE_BUSY; 826 } 827 lockmgr(&sc->gen_lock, LK_RELEASE); 828 break; 829 case TWS_PASSTHRU_REQ : 830 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 831 r = &sc->reqs[2]; 832 if ( r->state != TWS_REQ_STATE_FREE ) { 833 r = NULL; 834 } else { 835 r->state = TWS_REQ_STATE_BUSY; 836 } 837 lockmgr(&sc->gen_lock, LK_RELEASE); 838 break; 839 case TWS_GETSET_PARAM_REQ : 840 lockmgr(&sc->gen_lock, LK_EXCLUSIVE); 841 r = &sc->reqs[3]; 842 if ( r->state != TWS_REQ_STATE_FREE ) { 843 r = NULL; 844 } else { 845 r->state = TWS_REQ_STATE_BUSY; 846 } 847 lockmgr(&sc->gen_lock, LK_RELEASE); 848 break; 849 case TWS_SCSI_IO_REQ : 850 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 851 r = tws_q_remove_head(sc, TWS_FREE_Q); 852 if ( r ) 853 r->state = TWS_REQ_STATE_TRAN; 854 lockmgr(&sc->q_lock, LK_RELEASE); 855 break; 856 default : 857 TWS_TRACE_DEBUG(sc, "Unknown req type", 0, type); 858 r = NULL; 859 860 } 861 862 if ( r ) { 863 bzero(&r->cmd_pkt->cmd, sizeof(struct tws_command_apache)); 864 callout_init(&r->thandle); 865 r->data = NULL; 866 r->length = 0; 867 r->type = type; 868 r->flags = TWS_DIR_UNKNOWN; 869 r->error_code = TWS_REQ_ERR_INVALID; 870 r->ccb_ptr = NULL; 871 r->cb = NULL; 872 r->next = r->prev = NULL; 873 } 874 return(r); 875 } 876 877 void 878 tws_release_request(struct tws_request *req) 879 { 880 881 struct tws_softc *sc = req->sc; 882 883 TWS_TRACE_DEBUG(sc, "entry", sc, 0); 884 lockmgr(&sc->q_lock, LK_EXCLUSIVE); 885 tws_q_insert_tail(sc, req, TWS_FREE_Q); 886 lockmgr(&sc->q_lock, LK_RELEASE); 887 } 888 889 static device_method_t tws_methods[] = { 890 /* Device interface */ 891 DEVMETHOD(device_probe, tws_probe), 892 DEVMETHOD(device_attach, tws_attach), 893 DEVMETHOD(device_detach, tws_detach), 894 DEVMETHOD(device_shutdown, tws_shutdown), 895 DEVMETHOD(device_suspend, tws_suspend), 896 DEVMETHOD(device_resume, tws_resume), 897 898 DEVMETHOD(bus_print_child, bus_generic_print_child), 899 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 900 { 0, 0 } 901 }; 902 903 static driver_t tws_driver = { 904 "tws", 905 tws_methods, 906 sizeof(struct tws_softc) 907 }; 908 909 910 static devclass_t tws_devclass; 911 912 /* DEFINE_CLASS_0(tws, tws_driver, tws_methods, sizeof(struct tws_softc)); */ 913 DRIVER_MODULE(tws, pci, tws_driver, tws_devclass, 0, 0); 914 MODULE_DEPEND(tws, cam, 1, 1, 1); 915 MODULE_DEPEND(tws, pci, 1, 1, 1); 916 917 TUNABLE_INT("hw.tws.queue_depth", &tws_queue_depth); 918 #if 0 /* XXX swildner */ 919 TUNABLE_INT("hw.tws.enable_msi", &tws_enable_msi); 920 #endif 921