1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/errno.h> 28 #include <sys/types.h> 29 #include <sys/conf.h> 30 #include <sys/kmem.h> 31 #include <sys/ddi.h> 32 #include <sys/stat.h> 33 #include <sys/sunddi.h> 34 #include <sys/file.h> 35 #include <sys/open.h> 36 #include <sys/modctl.h> 37 #include <sys/ddi_impldefs.h> 38 #include <sys/sysmacros.h> 39 40 #include <sys/ioat.h> 41 42 static int ioat_open(dev_t *devp, int flag, int otyp, cred_t *cred); 43 static int ioat_close(dev_t devp, int flag, int otyp, cred_t *cred); 44 static int ioat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 45 static int ioat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 46 static int ioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 47 void **result); 48 49 static struct cb_ops ioat_cb_ops = { 50 ioat_open, /* cb_open */ 51 ioat_close, /* cb_close */ 52 nodev, /* cb_strategy */ 53 nodev, /* cb_print */ 54 nodev, /* cb_dump */ 55 nodev, /* cb_read */ 56 nodev, /* cb_write */ 57 ioat_ioctl, /* cb_ioctl */ 58 nodev, /* cb_devmap */ 59 nodev, /* cb_mmap */ 60 nodev, /* cb_segmap */ 61 nochpoll, /* cb_chpoll */ 62 ddi_prop_op, /* cb_prop_op */ 63 NULL, /* cb_stream */ 64 D_NEW | D_MP | D_64BIT | D_DEVMAP, /* cb_flag */ 65 CB_REV 66 }; 67 68 static struct dev_ops ioat_dev_ops = { 69 DEVO_REV, /* devo_rev */ 70 0, /* devo_refcnt */ 71 ioat_getinfo, /* devo_getinfo */ 72 nulldev, /* devo_identify */ 73 nulldev, /* devo_probe */ 74 ioat_attach, /* devo_attach */ 75 ioat_detach, /* devo_detach */ 76 nodev, /* devo_reset */ 77 &ioat_cb_ops, /* devo_cb_ops */ 78 NULL, /* devo_bus_ops */ 79 NULL /* power */ 80 }; 81 82 static struct modldrv ioat_modldrv = { 83 &mod_driverops, /* Type of module. This one is a driver */ 84 "ioat driver", /* Name of the module. */ 85 &ioat_dev_ops, /* driver ops */ 86 }; 87 88 static struct modlinkage ioat_modlinkage = { 89 MODREV_1, 90 (void *) &ioat_modldrv, 91 NULL 92 }; 93 94 95 void *ioat_statep; 96 97 static int ioat_chip_init(ioat_state_t *state); 98 static void ioat_chip_fini(ioat_state_t *state); 99 static int ioat_drv_init(ioat_state_t *state); 100 static void ioat_drv_fini(ioat_state_t *state); 101 static uint_t ioat_isr(caddr_t parm); 102 static void ioat_intr_enable(ioat_state_t *state); 103 static void ioat_intr_disable(ioat_state_t *state); 104 void ioat_detach_finish(ioat_state_t *state); 105 106 107 ddi_device_acc_attr_t ioat_acc_attr = { 108 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */ 109 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */ 110 DDI_STORECACHING_OK_ACC, /* devacc_attr_dataorder */ 111 DDI_DEFAULT_ACC /* devacc_attr_access */ 112 }; 113 114 /* dcopy callback interface */ 115 dcopy_device_cb_t ioat_cb = { 116 DCOPY_DEVICECB_V0, 117 0, /* reserved */ 118 ioat_channel_alloc, 119 ioat_channel_free, 120 ioat_cmd_alloc, 121 ioat_cmd_free, 122 ioat_cmd_post, 123 ioat_cmd_poll, 124 ioat_unregister_complete 125 }; 126 127 /* 128 * _init() 129 */ 130 int 131 _init(void) 132 { 133 int e; 134 135 e = ddi_soft_state_init(&ioat_statep, sizeof (ioat_state_t), 1); 136 if (e != 0) { 137 return (e); 138 } 139 140 e = mod_install(&ioat_modlinkage); 141 if (e != 0) { 142 ddi_soft_state_fini(&ioat_statep); 143 return (e); 144 } 145 146 return (0); 147 } 148 149 /* 150 * _info() 151 */ 152 int 153 _info(struct modinfo *modinfop) 154 { 155 return (mod_info(&ioat_modlinkage, modinfop)); 156 } 157 158 /* 159 * _fini() 160 */ 161 int 162 _fini(void) 163 { 164 int e; 165 166 e = mod_remove(&ioat_modlinkage); 167 if (e != 0) { 168 return (e); 169 } 170 171 ddi_soft_state_fini(&ioat_statep); 172 173 return (0); 174 } 175 176 /* 177 * ioat_attach() 178 */ 179 static int 180 ioat_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 181 { 182 ioat_state_t *state; 183 int instance; 184 int e; 185 186 187 switch (cmd) { 188 case DDI_ATTACH: 189 break; 190 191 case DDI_RESUME: 192 instance = ddi_get_instance(dip); 193 state = ddi_get_soft_state(ioat_statep, instance); 194 if (state == NULL) { 195 return (DDI_FAILURE); 196 } 197 e = ioat_channel_resume(state); 198 if (e != DDI_SUCCESS) { 199 return (DDI_FAILURE); 200 } 201 ioat_intr_enable(state); 202 return (DDI_SUCCESS); 203 204 default: 205 return (DDI_FAILURE); 206 } 207 208 instance = ddi_get_instance(dip); 209 e = ddi_soft_state_zalloc(ioat_statep, instance); 210 if (e != DDI_SUCCESS) { 211 return (DDI_FAILURE); 212 } 213 state = ddi_get_soft_state(ioat_statep, instance); 214 if (state == NULL) { 215 goto attachfail_get_soft_state; 216 } 217 218 state->is_dip = dip; 219 state->is_instance = instance; 220 221 /* setup the registers, save away some device info */ 222 e = ioat_chip_init(state); 223 if (e != DDI_SUCCESS) { 224 goto attachfail_chip_init; 225 } 226 227 /* initialize driver state, must be after chip init */ 228 e = ioat_drv_init(state); 229 if (e != DDI_SUCCESS) { 230 goto attachfail_drv_init; 231 } 232 233 /* create the minor node (for the ioctl) */ 234 e = ddi_create_minor_node(dip, "ioat", S_IFCHR, instance, DDI_PSEUDO, 235 0); 236 if (e != DDI_SUCCESS) { 237 goto attachfail_minor_node; 238 } 239 240 /* Enable device interrupts */ 241 ioat_intr_enable(state); 242 243 /* Report that driver was loaded */ 244 ddi_report_dev(dip); 245 246 /* register with dcopy */ 247 e = dcopy_device_register(state, &state->is_deviceinfo, 248 &state->is_device_handle); 249 if (e != DCOPY_SUCCESS) { 250 goto attachfail_register; 251 } 252 253 return (DDI_SUCCESS); 254 255 attachfail_register: 256 ioat_intr_disable(state); 257 ddi_remove_minor_node(dip, NULL); 258 attachfail_minor_node: 259 ioat_drv_fini(state); 260 attachfail_drv_init: 261 ioat_chip_fini(state); 262 attachfail_chip_init: 263 attachfail_get_soft_state: 264 (void) ddi_soft_state_free(ioat_statep, instance); 265 266 return (DDI_FAILURE); 267 } 268 269 /* 270 * ioat_detach() 271 */ 272 static int 273 ioat_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 274 { 275 ioat_state_t *state; 276 int instance; 277 int e; 278 279 280 instance = ddi_get_instance(dip); 281 state = ddi_get_soft_state(ioat_statep, instance); 282 if (state == NULL) { 283 return (DDI_FAILURE); 284 } 285 286 switch (cmd) { 287 case DDI_DETACH: 288 break; 289 290 case DDI_SUSPEND: 291 ioat_channel_suspend(state); 292 return (DDI_SUCCESS); 293 294 default: 295 return (DDI_FAILURE); 296 } 297 298 /* 299 * try to unregister from dcopy. Since this driver doesn't follow the 300 * traditional parent/child model, we may still be in use so we can't 301 * detach yet. 302 */ 303 e = dcopy_device_unregister(&state->is_device_handle); 304 if (e != DCOPY_SUCCESS) { 305 if (e == DCOPY_PENDING) { 306 cmn_err(CE_NOTE, "device busy, performing asynchronous" 307 " detach\n"); 308 } 309 return (DDI_FAILURE); 310 } 311 312 ioat_detach_finish(state); 313 314 return (DDI_SUCCESS); 315 } 316 317 /* 318 * ioat_getinfo() 319 */ 320 /*ARGSUSED*/ 321 static int 322 ioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 323 { 324 ioat_state_t *state; 325 int instance; 326 dev_t dev; 327 int e; 328 329 330 dev = (dev_t)arg; 331 instance = getminor(dev); 332 333 switch (cmd) { 334 case DDI_INFO_DEVT2DEVINFO: 335 state = ddi_get_soft_state(ioat_statep, instance); 336 if (state == NULL) { 337 return (DDI_FAILURE); 338 } 339 *result = (void *)state->is_dip; 340 e = DDI_SUCCESS; 341 break; 342 343 case DDI_INFO_DEVT2INSTANCE: 344 *result = (void *)(uintptr_t)instance; 345 e = DDI_SUCCESS; 346 break; 347 348 default: 349 e = DDI_FAILURE; 350 break; 351 } 352 353 return (e); 354 } 355 356 357 /* 358 * ioat_open() 359 */ 360 /*ARGSUSED*/ 361 static int 362 ioat_open(dev_t *devp, int flag, int otyp, cred_t *cred) 363 { 364 ioat_state_t *state; 365 int instance; 366 367 instance = getminor(*devp); 368 state = ddi_get_soft_state(ioat_statep, instance); 369 if (state == NULL) { 370 return (ENXIO); 371 } 372 373 return (0); 374 } 375 376 377 /* 378 * ioat_close() 379 */ 380 /*ARGSUSED*/ 381 static int 382 ioat_close(dev_t devp, int flag, int otyp, cred_t *cred) 383 { 384 return (0); 385 } 386 387 388 /* 389 * ioat_chip_init() 390 */ 391 static int 392 ioat_chip_init(ioat_state_t *state) 393 { 394 ddi_device_acc_attr_t attr; 395 int e; 396 397 398 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 399 attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 400 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 401 402 e = ddi_regs_map_setup(state->is_dip, 1, (caddr_t *)&state->is_genregs, 403 0, 0, &attr, &state->is_reg_handle); 404 if (e != DDI_SUCCESS) { 405 goto chipinitfail_regsmap; 406 } 407 408 /* save away ioat chip info */ 409 state->is_num_channels = (uint_t)ddi_get8(state->is_reg_handle, 410 &state->is_genregs[IOAT_CHANCNT]); 411 412 /* 413 * If we get a bogus value, something is wrong with the H/W, fail to 414 * attach. 415 */ 416 if (state->is_num_channels == 0) { 417 goto chipinitfail_numchan; 418 } 419 420 state->is_maxxfer = (uint_t)ddi_get8(state->is_reg_handle, 421 &state->is_genregs[IOAT_XFERCAP]); 422 state->is_chanoff = (uintptr_t)ddi_get16(state->is_reg_handle, 423 (uint16_t *)&state->is_genregs[IOAT_PERPORT_OFF]); 424 state->is_cbver = (uint_t)ddi_get8(state->is_reg_handle, 425 &state->is_genregs[IOAT_CBVER]); 426 state->is_intrdelay = (uint_t)ddi_get16(state->is_reg_handle, 427 (uint16_t *)&state->is_genregs[IOAT_INTRDELAY]); 428 state->is_status = (uint_t)ddi_get16(state->is_reg_handle, 429 (uint16_t *)&state->is_genregs[IOAT_CSSTATUS]); 430 state->is_capabilities = (uint_t)ddi_get32(state->is_reg_handle, 431 (uint32_t *)&state->is_genregs[IOAT_DMACAPABILITY]); 432 433 if (state->is_cbver & 0x10) { 434 state->is_ver = IOAT_CBv1; 435 } else if (state->is_cbver & 0x20) { 436 state->is_ver = IOAT_CBv2; 437 } else { 438 goto chipinitfail_version; 439 } 440 441 return (DDI_SUCCESS); 442 443 chipinitfail_version: 444 chipinitfail_numchan: 445 ddi_regs_map_free(&state->is_reg_handle); 446 chipinitfail_regsmap: 447 return (DDI_FAILURE); 448 } 449 450 451 /* 452 * ioat_chip_fini() 453 */ 454 static void 455 ioat_chip_fini(ioat_state_t *state) 456 { 457 ddi_regs_map_free(&state->is_reg_handle); 458 } 459 460 461 /* 462 * ioat_drv_init() 463 */ 464 static int 465 ioat_drv_init(ioat_state_t *state) 466 { 467 ddi_acc_handle_t handle; 468 int e; 469 470 471 mutex_init(&state->is_mutex, NULL, MUTEX_DRIVER, NULL); 472 473 state->is_deviceinfo.di_dip = state->is_dip; 474 state->is_deviceinfo.di_num_dma = state->is_num_channels; 475 state->is_deviceinfo.di_maxxfer = state->is_maxxfer; 476 state->is_deviceinfo.di_capabilities = state->is_capabilities; 477 state->is_deviceinfo.di_cb = &ioat_cb; 478 479 e = pci_config_setup(state->is_dip, &handle); 480 if (e != DDI_SUCCESS) { 481 goto drvinitfail_config_setup; 482 } 483 484 /* read in Vendor ID */ 485 state->is_deviceinfo.di_id = (uint64_t)pci_config_get16(handle, 0); 486 state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 16; 487 488 /* read in Device ID */ 489 state->is_deviceinfo.di_id |= (uint64_t)pci_config_get16(handle, 2); 490 state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 32; 491 492 /* Add in chipset version */ 493 state->is_deviceinfo.di_id |= (uint64_t)state->is_cbver; 494 pci_config_teardown(&handle); 495 496 e = ddi_intr_hilevel(state->is_dip, 0); 497 if (e != 0) { 498 cmn_err(CE_WARN, "hilevel interrupt not supported\n"); 499 goto drvinitfail_hilevel; 500 } 501 502 /* we don't support MSIs for v2 yet */ 503 e = ddi_add_intr(state->is_dip, 0, NULL, NULL, ioat_isr, 504 (caddr_t)state); 505 if (e != DDI_SUCCESS) { 506 goto drvinitfail_add_intr; 507 } 508 509 e = ddi_get_iblock_cookie(state->is_dip, 0, &state->is_iblock_cookie); 510 if (e != DDI_SUCCESS) { 511 goto drvinitfail_iblock_cookie; 512 } 513 514 e = ioat_channel_init(state); 515 if (e != DDI_SUCCESS) { 516 goto drvinitfail_channel_init; 517 } 518 519 return (DDI_SUCCESS); 520 521 drvinitfail_channel_init: 522 drvinitfail_iblock_cookie: 523 ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie); 524 drvinitfail_add_intr: 525 drvinitfail_hilevel: 526 drvinitfail_config_setup: 527 mutex_destroy(&state->is_mutex); 528 529 return (DDI_FAILURE); 530 } 531 532 533 /* 534 * ioat_drv_fini() 535 */ 536 static void 537 ioat_drv_fini(ioat_state_t *state) 538 { 539 ioat_channel_fini(state); 540 ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie); 541 mutex_destroy(&state->is_mutex); 542 } 543 544 545 /* 546 * ioat_unregister_complete() 547 */ 548 void 549 ioat_unregister_complete(void *device_private, int status) 550 { 551 ioat_state_t *state; 552 553 554 state = device_private; 555 556 if (status != DCOPY_SUCCESS) { 557 cmn_err(CE_WARN, "asynchronous detach aborted\n"); 558 return; 559 } 560 561 cmn_err(CE_CONT, "detach completing\n"); 562 ioat_detach_finish(state); 563 } 564 565 566 /* 567 * ioat_detach_finish() 568 */ 569 void 570 ioat_detach_finish(ioat_state_t *state) 571 { 572 ioat_intr_disable(state); 573 ddi_remove_minor_node(state->is_dip, NULL); 574 ioat_drv_fini(state); 575 ioat_chip_fini(state); 576 (void) ddi_soft_state_free(ioat_statep, state->is_instance); 577 } 578 579 580 /* 581 * ioat_intr_enable() 582 */ 583 static void 584 ioat_intr_enable(ioat_state_t *state) 585 { 586 uint32_t intr_status; 587 588 589 /* Clear any pending interrupts */ 590 intr_status = ddi_get32(state->is_reg_handle, 591 (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS]); 592 if (intr_status != 0) { 593 ddi_put32(state->is_reg_handle, 594 (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS], 595 intr_status); 596 } 597 598 /* Enable interrupts on the device */ 599 ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL], 600 IOAT_INTRCTL_MASTER_EN); 601 } 602 603 604 /* 605 * ioat_intr_disable() 606 */ 607 static void 608 ioat_intr_disable(ioat_state_t *state) 609 { 610 /* 611 * disable interrupts on the device. A read of the interrupt control 612 * register clears the enable bit. 613 */ 614 (void) ddi_get8(state->is_reg_handle, 615 &state->is_genregs[IOAT_INTRCTL]); 616 } 617 618 619 /* 620 * ioat_isr() 621 */ 622 static uint_t 623 ioat_isr(caddr_t parm) 624 { 625 uint32_t intr_status; 626 ioat_state_t *state; 627 uint8_t intrctrl; 628 uint32_t chan; 629 uint_t r; 630 int i; 631 632 state = (ioat_state_t *)parm; 633 634 intrctrl = ddi_get8(state->is_reg_handle, 635 &state->is_genregs[IOAT_INTRCTL]); 636 /* master interrupt enable should always be set */ 637 ASSERT(intrctrl & IOAT_INTRCTL_MASTER_EN); 638 639 /* If the interrupt status bit isn't set, it's not ours */ 640 if (!(intrctrl & IOAT_INTRCTL_INTR_STAT)) { 641 /* re-set master interrupt enable (since it clears on read) */ 642 ddi_put8(state->is_reg_handle, 643 &state->is_genregs[IOAT_INTRCTL], intrctrl); 644 return (DDI_INTR_UNCLAIMED); 645 } 646 647 /* see which channels generated the interrupt */ 648 intr_status = ddi_get32(state->is_reg_handle, 649 (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS]); 650 651 /* call the intr handler for the channels */ 652 r = DDI_INTR_UNCLAIMED; 653 chan = 1; 654 for (i = 0; i < state->is_num_channels; i++) { 655 if (intr_status & chan) { 656 ioat_channel_intr(&state->is_channel[i]); 657 r = DDI_INTR_CLAIMED; 658 } 659 chan = chan << 1; 660 } 661 662 /* 663 * if interrupt status bit was set, there should have been an 664 * attention status bit set too. 665 */ 666 ASSERT(r == DDI_INTR_CLAIMED); 667 668 /* re-set master interrupt enable (since it clears on read) */ 669 ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL], 670 intrctrl); 671 672 return (r); 673 } 674