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