Print this page
*** NO COMMENTS ***


   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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  *
  28  * nv_sata is a combo SATA HBA driver for ck804/mcp5x (mcp5x = mcp55/mcp51)
  29  * based chipsets.
  30  *
  31  * NCQ
  32  * ---
  33  *
  34  * A portion of the NCQ is in place, but is incomplete.  NCQ is disabled
  35  * and is likely to be revisited in the future.
  36  *
  37  *
  38  * Power Management
  39  * ----------------
  40  *
  41  * Normally power management would be responsible for ensuring the device
  42  * is quiescent and then changing power states to the device, such as
  43  * powering down parts or all of the device.  mcp5x/ck804 is unique in
  44  * that it is only available as part of a larger southbridge chipset, so
  45  * removing power to the device isn't possible.  Switches to control
  46  * power management states D0/D3 in the PCI configuration space appear to
  47  * be supported but changes to these states are apparently are ignored.
  48  * The only further PM that the driver _could_ do is shut down the PHY,
  49  * but in order to deliver the first rev of the driver sooner than later,


 295 /*
 296  * Request Sense CDB for ATAPI
 297  */
 298 static const uint8_t nv_rqsense_cdb[16] = {
 299         SCMD_REQUEST_SENSE,
 300         0,
 301         0,
 302         0,
 303         SATA_ATAPI_MIN_RQSENSE_LEN,
 304         0,
 305         0, 0, 0, 0, 0, 0, 0, 0, 0, 0    /* pad out to max CDB length */
 306 };
 307 
 308 
 309 static sata_tran_hotplug_ops_t nv_hotplug_ops;
 310 
 311 extern struct mod_ops mod_driverops;
 312 
 313 static  struct modldrv modldrv = {
 314         &mod_driverops,     /* driverops */
 315         "Nvidia ck804/mcp51/mcp55 HBA",
 316         &nv_dev_ops,        /* driver ops */
 317 };
 318 
 319 static  struct modlinkage modlinkage = {
 320         MODREV_1,
 321         &modldrv,
 322         NULL
 323 };
 324 
 325 /*
 326  * Maximum number of consecutive interrupts processed in the loop in the
 327  * single invocation of the port interrupt routine.
 328  */
 329 int nv_max_intr_loops = NV_MAX_INTR_PER_DEV;
 330 
 331 /*
 332  * wait between checks of reg status
 333  */
 334 int nv_usec_delay = NV_WAIT_REG_CHECK;
 335 


 582 
 583         case DDI_ATTACH:
 584 
 585                 attach_state = ATTACH_PROGRESS_NONE;
 586 
 587                 status = ddi_soft_state_zalloc(nv_statep, inst);
 588 
 589                 if (status != DDI_SUCCESS) {
 590                         break;
 591                 }
 592 
 593                 nvc = ddi_get_soft_state(nv_statep, inst);
 594 
 595                 nvc->nvc_dip = dip;
 596 
 597                 NVLOG(NVDBG_INIT, nvc, NULL, "nv_attach(): DDI_ATTACH", NULL);
 598 
 599                 attach_state |= ATTACH_PROGRESS_STATEP_ALLOC;
 600 
 601                 if (pci_config_setup(dip, &pci_conf_handle) == DDI_SUCCESS) {


 602                         nvc->nvc_revid = pci_config_get8(pci_conf_handle,
 603                             PCI_CONF_REVID);
 604                         NVLOG(NVDBG_INIT, nvc, NULL,
 605                             "inst %d: silicon revid is %x nv_debug_flags=%x",
 606                             inst, nvc->nvc_revid, nv_debug_flags);

 607                 } else {
 608                         break;
 609                 }
 610 
 611                 attach_state |= ATTACH_PROGRESS_CONF_HANDLE;
 612 
 613                 /*
 614                  * Set the PCI command register: enable IO/MEM/Master.
 615                  */
 616                 command = pci_config_get16(pci_conf_handle, PCI_CONF_COMM);
 617                 pci_config_put16(pci_conf_handle, PCI_CONF_COMM,
 618                     command|PCI_COMM_IO|PCI_COMM_MAE|PCI_COMM_ME);
 619 
 620                 subclass = pci_config_get8(pci_conf_handle, PCI_CONF_SUBCLASS);
 621 
 622                 if (subclass & PCI_MASS_RAID) {
 623                         cmn_err(CE_WARN,
 624                             "attach failed: RAID mode not supported");
 625 
 626                         break;


2477 
2478 
2479         serr = nv_get32(bar5_hdl, nvp->nvp_serror);
2480         DTRACE_PROBE1(last_serror_h, int, serr);
2481 
2482         if (reset_success == B_FALSE) {
2483                 NVLOG(NVDBG_RESET, nvc, nvp, "nv_reset not succeeded "
2484                     "after %d attempts. serr: 0x%x", i, serr);
2485         } else {
2486                 NVLOG(NVDBG_RESET, nvc, nvp, "nv_reset succeeded"
2487                     " after %dms. serr: 0x%x", TICK_TO_MSEC(ddi_get_lbolt() -
2488                     nvp->nvp_reset_time), serr);
2489         }
2490 
2491         nvp->nvp_wait_sig  = NV_WAIT_SIG;
2492         nv_setup_timeout(nvp, nvp->nvp_wait_sig);
2493 }
2494 
2495 
2496 /*
2497  * Initialize register handling specific to mcp51/mcp55
2498  */
2499 /* ARGSUSED */
2500 static void
2501 mcp5x_reg_init(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2502 {
2503         nv_port_t *nvp;
2504         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2505         uint8_t off, port;
2506 
2507         nvc->nvc_mcp5x_ctl = (uint32_t *)(bar5 + MCP5X_CTL);
2508         nvc->nvc_mcp5x_ncq = (uint32_t *)(bar5 + MCP5X_NCQ);
2509 
2510         for (port = 0, off = 0; port < NV_MAX_PORTS(nvc); port++, off += 2) {
2511                 nvp = &(nvc->nvc_port[port]);
2512                 nvp->nvp_mcp5x_int_status =
2513                     (uint16_t *)(bar5 + MCP5X_INT_STATUS + off);
2514                 nvp->nvp_mcp5x_int_ctl =
2515                     (uint16_t *)(bar5 + MCP5X_INT_CTL + off);
2516 
2517                 /*


2532                 nv_put16(nvc->nvc_bar_hdl[5], nvp->nvp_mcp5x_int_ctl,
2533                     ~(MCP5X_INT_IGNORE));
2534         }
2535 
2536         /*
2537          * Allow the driver to program the BM on the first command instead
2538          * of waiting for an interrupt.
2539          */
2540 #ifdef NCQ
2541         flags = MCP_SATA_AE_NCQ_PDEV_FIRST_CMD | MCP_SATA_AE_NCQ_SDEV_FIRST_CMD;
2542         nv_put32(nvc->nvc_bar_hdl[5], nvc->nvc_mcp5x_ncq, flags);
2543         flags = MCP_SATA_AE_CTL_PRI_SWNCQ | MCP_SATA_AE_CTL_SEC_SWNCQ;
2544         nv_put32(nvc->nvc_bar_hdl[5], nvc->nvc_mcp5x_ctl, flags);
2545 #endif
2546 
2547         /*
2548          * mcp55 rev A03 and above supports 40-bit physical addressing.
2549          * Enable DMA to take advantage of that.
2550          *
2551          */
2552         if (nvc->nvc_revid >= 0xa3) {

2553                 if (nv_sata_40bit_dma == B_TRUE) {
2554                         uint32_t reg32;
2555                         NVLOG(NVDBG_INIT, nvp->nvp_ctlp, nvp,
2556                             "rev id is %X.  40-bit DMA addressing"
2557                             " enabled", nvc->nvc_revid);

2558                         nvc->dma_40bit = B_TRUE;
2559 
2560                         reg32 = pci_config_get32(pci_conf_handle,
2561                             NV_SATA_CFG_20);
2562                         pci_config_put32(pci_conf_handle, NV_SATA_CFG_20,
2563                             reg32 | NV_40BIT_PRD);
2564 
2565                         /*
2566                          * CFG_23 bits 0-7 contain the top 8 bits (of 40
2567                          * bits) for the primary PRD table, and bits 8-15
2568                          * contain the top 8 bits for the secondary.  Set
2569                          * to zero because the DMA attribute table for PRD
2570                          * allocation forces it into 32 bit address space
2571                          * anyway.
2572                          */
2573                         reg32 = pci_config_get32(pci_conf_handle,
2574                             NV_SATA_CFG_23);
2575                         pci_config_put32(pci_conf_handle, NV_SATA_CFG_23,
2576                             reg32 & 0xffff0000);
2577                 } else {
2578                         NVLOG(NVDBG_INIT, nvp->nvp_ctlp, nvp,
2579                             "40-bit DMA disabled by nv_sata_40bit_dma", NULL);
2580                 }
2581         } else {
2582                 nv_cmn_err(CE_NOTE, nvp->nvp_ctlp, nvp, "rev id is %X and is "
2583                     "not capable of 40-bit DMA addressing", nvc->nvc_revid);

2584         }
2585 }
2586 
2587 
2588 /*
2589  * Initialize register handling specific to ck804
2590  */
2591 static void
2592 ck804_reg_init(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2593 {
2594         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2595         uint32_t reg32;
2596         uint16_t reg16;
2597         nv_port_t *nvp;
2598         int j;
2599 
2600         /*
2601          * delay hotplug interrupts until PHYRDY.
2602          */
2603         reg32 = pci_config_get32(pci_conf_handle, NV_SATA_CFG_42);


2625          */
2626         for (j = 0; j < NV_MAX_PORTS(nvc); j++) {
2627                 nvp = &(nvc->nvc_port[j]);
2628                 mutex_enter(&nvp->nvp_mutex);
2629                 (*(nvp->nvp_ctlp->nvc_set_intr))(nvp,
2630                     NV_INTR_CLEAR_ALL|NV_INTR_ENABLE);
2631                 mutex_exit(&nvp->nvp_mutex);
2632         }
2633 }
2634 
2635 
2636 /*
2637  * Initialize the controller and set up driver data structures.
2638  * determine if ck804 or mcp5x class.
2639  */
2640 static int
2641 nv_init_ctl(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2642 {
2643         struct sata_hba_tran stran;
2644         nv_port_t *nvp;
2645         int j, ck804;
2646         uchar_t *cmd_addr, *ctl_addr, *bm_addr;
2647         ddi_acc_handle_t bar5_hdl = nvc->nvc_bar_hdl[5];
2648         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2649         uint32_t reg32;
2650         uint8_t reg8, reg8_save;
2651 
2652         NVLOG(NVDBG_INIT, nvc, NULL, "nv_init_ctl entered", NULL);
2653 
2654         ck804 = B_TRUE;
2655 #ifdef SGPIO_SUPPORT
2656         nvc->nvc_mcp5x_flag = B_FALSE;
2657 #endif
2658 
2659         /*
2660          * Need to set bit 2 to 1 at config offset 0x50
2661          * to enable access to the bar5 registers.
2662          */
2663         reg32 = pci_config_get32(pci_conf_handle, NV_SATA_CFG_20);
2664         if (!(reg32 & NV_BAR5_SPACE_EN)) {
2665                 pci_config_put32(pci_conf_handle, NV_SATA_CFG_20,
2666                     reg32 | NV_BAR5_SPACE_EN);
2667         }
2668 
2669         /*
2670          * Determine if this is ck804 or mcp5x.  ck804 will map in the
2671          * task file registers into bar5 while mcp5x won't.  The offset of
2672          * the task file registers in mcp5x's space is unused, so it will
2673          * return zero.  So check one of the task file registers to see if it is
2674          * writable and reads back what was written.  If it's mcp5x it will
2675          * return back 0xff whereas ck804 will return the value written.
2676          */
2677         reg8_save = nv_get8(bar5_hdl,
2678             (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X));
2679 
2680 
2681         for (j = 1; j < 3; j++) {
2682 
2683                 nv_put8(bar5_hdl, (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X), j);
2684                 reg8 = nv_get8(bar5_hdl,
2685                     (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X));
2686 
2687                 if (reg8 != j) {
2688                         ck804 = B_FALSE;
2689                         nvc->nvc_mcp5x_flag = B_TRUE;
2690                         break;
2691                 }
2692         }
2693 
2694         nv_put8(bar5_hdl, (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X), reg8_save);
2695 
2696         if (ck804 == B_TRUE) {
2697                 NVLOG(NVDBG_INIT, nvc, NULL, "controller is CK804", NULL);

2698                 nvc->nvc_interrupt = ck804_intr;
2699                 nvc->nvc_reg_init = ck804_reg_init;
2700                 nvc->nvc_set_intr = ck804_set_intr;
2701         } else {
2702                 NVLOG(NVDBG_INIT, nvc, NULL, "controller is MCP51/MCP55", NULL);

2703                 nvc->nvc_interrupt = mcp5x_intr;
2704                 nvc->nvc_reg_init = mcp5x_reg_init;
2705                 nvc->nvc_set_intr = mcp5x_set_intr;
2706         }
2707 
2708 
2709         stran.sata_tran_hba_rev = SATA_TRAN_HBA_REV;
2710         stran.sata_tran_hba_dip = nvc->nvc_dip;
2711         stran.sata_tran_hba_num_cports = NV_NUM_PORTS;
2712         stran.sata_tran_hba_features_support =
2713             SATA_CTLF_HOTPLUG | SATA_CTLF_ASN | SATA_CTLF_ATAPI;
2714         stran.sata_tran_hba_qdepth = NV_QUEUE_SLOTS;
2715         stran.sata_tran_probe_port = nv_sata_probe;
2716         stran.sata_tran_start = nv_sata_start;
2717         stran.sata_tran_abort = nv_sata_abort;
2718         stran.sata_tran_reset_dport = nv_sata_reset;
2719         stran.sata_tran_selftest = NULL;
2720         stran.sata_tran_hotplug_ops = &nv_hotplug_ops;
2721         stran.sata_tran_pwrmgt_ops = NULL;
2722         stran.sata_tran_ioctl = NULL;




   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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  *
  29  * nv_sata is a combo SATA HBA driver for CK804/MCP04 (ck804) and
  30  * MCP55/MCP51/MCP61 (mcp5x) based chipsets.
  31  *
  32  * NCQ
  33  * ---
  34  *
  35  * A portion of the NCQ is in place, but is incomplete.  NCQ is disabled
  36  * and is likely to be revisited in the future.
  37  *
  38  *
  39  * Power Management
  40  * ----------------
  41  *
  42  * Normally power management would be responsible for ensuring the device
  43  * is quiescent and then changing power states to the device, such as
  44  * powering down parts or all of the device.  mcp5x/ck804 is unique in
  45  * that it is only available as part of a larger southbridge chipset, so
  46  * removing power to the device isn't possible.  Switches to control
  47  * power management states D0/D3 in the PCI configuration space appear to
  48  * be supported but changes to these states are apparently are ignored.
  49  * The only further PM that the driver _could_ do is shut down the PHY,
  50  * but in order to deliver the first rev of the driver sooner than later,


 296 /*
 297  * Request Sense CDB for ATAPI
 298  */
 299 static const uint8_t nv_rqsense_cdb[16] = {
 300         SCMD_REQUEST_SENSE,
 301         0,
 302         0,
 303         0,
 304         SATA_ATAPI_MIN_RQSENSE_LEN,
 305         0,
 306         0, 0, 0, 0, 0, 0, 0, 0, 0, 0    /* pad out to max CDB length */
 307 };
 308 
 309 
 310 static sata_tran_hotplug_ops_t nv_hotplug_ops;
 311 
 312 extern struct mod_ops mod_driverops;
 313 
 314 static  struct modldrv modldrv = {
 315         &mod_driverops,     /* driverops */
 316         "NVIDIA CK804/MCP04/MCP51/MCP55/MCP61 HBA",
 317         &nv_dev_ops,        /* driver ops */
 318 };
 319 
 320 static  struct modlinkage modlinkage = {
 321         MODREV_1,
 322         &modldrv,
 323         NULL
 324 };
 325 
 326 /*
 327  * Maximum number of consecutive interrupts processed in the loop in the
 328  * single invocation of the port interrupt routine.
 329  */
 330 int nv_max_intr_loops = NV_MAX_INTR_PER_DEV;
 331 
 332 /*
 333  * wait between checks of reg status
 334  */
 335 int nv_usec_delay = NV_WAIT_REG_CHECK;
 336 


 583 
 584         case DDI_ATTACH:
 585 
 586                 attach_state = ATTACH_PROGRESS_NONE;
 587 
 588                 status = ddi_soft_state_zalloc(nv_statep, inst);
 589 
 590                 if (status != DDI_SUCCESS) {
 591                         break;
 592                 }
 593 
 594                 nvc = ddi_get_soft_state(nv_statep, inst);
 595 
 596                 nvc->nvc_dip = dip;
 597 
 598                 NVLOG(NVDBG_INIT, nvc, NULL, "nv_attach(): DDI_ATTACH", NULL);
 599 
 600                 attach_state |= ATTACH_PROGRESS_STATEP_ALLOC;
 601 
 602                 if (pci_config_setup(dip, &pci_conf_handle) == DDI_SUCCESS) {
 603                         nvc->nvc_devid = pci_config_get16(pci_conf_handle,
 604                             PCI_CONF_DEVID);
 605                         nvc->nvc_revid = pci_config_get8(pci_conf_handle,
 606                             PCI_CONF_REVID);
 607                         NVLOG(NVDBG_INIT, nvc, NULL,
 608                             "inst %d: devid is %x silicon revid is %x"
 609                             " nv_debug_flags=%x", inst, nvc->nvc_devid,
 610                             nvc->nvc_revid, nv_debug_flags);
 611                 } else {
 612                         break;
 613                 }
 614 
 615                 attach_state |= ATTACH_PROGRESS_CONF_HANDLE;
 616 
 617                 /*
 618                  * Set the PCI command register: enable IO/MEM/Master.
 619                  */
 620                 command = pci_config_get16(pci_conf_handle, PCI_CONF_COMM);
 621                 pci_config_put16(pci_conf_handle, PCI_CONF_COMM,
 622                     command|PCI_COMM_IO|PCI_COMM_MAE|PCI_COMM_ME);
 623 
 624                 subclass = pci_config_get8(pci_conf_handle, PCI_CONF_SUBCLASS);
 625 
 626                 if (subclass & PCI_MASS_RAID) {
 627                         cmn_err(CE_WARN,
 628                             "attach failed: RAID mode not supported");
 629 
 630                         break;


2481 
2482 
2483         serr = nv_get32(bar5_hdl, nvp->nvp_serror);
2484         DTRACE_PROBE1(last_serror_h, int, serr);
2485 
2486         if (reset_success == B_FALSE) {
2487                 NVLOG(NVDBG_RESET, nvc, nvp, "nv_reset not succeeded "
2488                     "after %d attempts. serr: 0x%x", i, serr);
2489         } else {
2490                 NVLOG(NVDBG_RESET, nvc, nvp, "nv_reset succeeded"
2491                     " after %dms. serr: 0x%x", TICK_TO_MSEC(ddi_get_lbolt() -
2492                     nvp->nvp_reset_time), serr);
2493         }
2494 
2495         nvp->nvp_wait_sig  = NV_WAIT_SIG;
2496         nv_setup_timeout(nvp, nvp->nvp_wait_sig);
2497 }
2498 
2499 
2500 /*
2501  * Initialize register handling specific to mcp51/mcp55/mcp61
2502  */
2503 /* ARGSUSED */
2504 static void
2505 mcp5x_reg_init(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2506 {
2507         nv_port_t *nvp;
2508         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2509         uint8_t off, port;
2510 
2511         nvc->nvc_mcp5x_ctl = (uint32_t *)(bar5 + MCP5X_CTL);
2512         nvc->nvc_mcp5x_ncq = (uint32_t *)(bar5 + MCP5X_NCQ);
2513 
2514         for (port = 0, off = 0; port < NV_MAX_PORTS(nvc); port++, off += 2) {
2515                 nvp = &(nvc->nvc_port[port]);
2516                 nvp->nvp_mcp5x_int_status =
2517                     (uint16_t *)(bar5 + MCP5X_INT_STATUS + off);
2518                 nvp->nvp_mcp5x_int_ctl =
2519                     (uint16_t *)(bar5 + MCP5X_INT_CTL + off);
2520 
2521                 /*


2536                 nv_put16(nvc->nvc_bar_hdl[5], nvp->nvp_mcp5x_int_ctl,
2537                     ~(MCP5X_INT_IGNORE));
2538         }
2539 
2540         /*
2541          * Allow the driver to program the BM on the first command instead
2542          * of waiting for an interrupt.
2543          */
2544 #ifdef NCQ
2545         flags = MCP_SATA_AE_NCQ_PDEV_FIRST_CMD | MCP_SATA_AE_NCQ_SDEV_FIRST_CMD;
2546         nv_put32(nvc->nvc_bar_hdl[5], nvc->nvc_mcp5x_ncq, flags);
2547         flags = MCP_SATA_AE_CTL_PRI_SWNCQ | MCP_SATA_AE_CTL_SEC_SWNCQ;
2548         nv_put32(nvc->nvc_bar_hdl[5], nvc->nvc_mcp5x_ctl, flags);
2549 #endif
2550 
2551         /*
2552          * mcp55 rev A03 and above supports 40-bit physical addressing.
2553          * Enable DMA to take advantage of that.
2554          *
2555          */
2556         if ((nvc->nvc_devid > 0x37f) ||
2557             ((nvc->nvc_devid == 0x37f) && (nvc->nvc_revid >= 0xa3))) {
2558                 if (nv_sata_40bit_dma == B_TRUE) {
2559                         uint32_t reg32;
2560                         NVLOG(NVDBG_INIT, nvp->nvp_ctlp, nvp,
2561                             "devid is %X revid is %X. 40-bit DMA"
2562                             " addressing enabled", nvc->nvc_devid,
2563                             nvc->nvc_revid);
2564                         nvc->dma_40bit = B_TRUE;
2565 
2566                         reg32 = pci_config_get32(pci_conf_handle,
2567                             NV_SATA_CFG_20);
2568                         pci_config_put32(pci_conf_handle, NV_SATA_CFG_20,
2569                             reg32 | NV_40BIT_PRD);
2570 
2571                         /*
2572                          * CFG_23 bits 0-7 contain the top 8 bits (of 40
2573                          * bits) for the primary PRD table, and bits 8-15
2574                          * contain the top 8 bits for the secondary.  Set
2575                          * to zero because the DMA attribute table for PRD
2576                          * allocation forces it into 32 bit address space
2577                          * anyway.
2578                          */
2579                         reg32 = pci_config_get32(pci_conf_handle,
2580                             NV_SATA_CFG_23);
2581                         pci_config_put32(pci_conf_handle, NV_SATA_CFG_23,
2582                             reg32 & 0xffff0000);
2583                 } else {
2584                         NVLOG(NVDBG_INIT, nvp->nvp_ctlp, nvp,
2585                             "40-bit DMA disabled by nv_sata_40bit_dma", NULL);
2586                 }
2587         } else {
2588                 nv_cmn_err(CE_NOTE, nvp->nvp_ctlp, nvp, "devid is %X revid is"
2589                     " %X. Not capable of 40-bit DMA addressing",
2590                     nvc->nvc_devid, nvc->nvc_revid);
2591         }
2592 }
2593 
2594 
2595 /*
2596  * Initialize register handling specific to ck804
2597  */
2598 static void
2599 ck804_reg_init(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2600 {
2601         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2602         uint32_t reg32;
2603         uint16_t reg16;
2604         nv_port_t *nvp;
2605         int j;
2606 
2607         /*
2608          * delay hotplug interrupts until PHYRDY.
2609          */
2610         reg32 = pci_config_get32(pci_conf_handle, NV_SATA_CFG_42);


2632          */
2633         for (j = 0; j < NV_MAX_PORTS(nvc); j++) {
2634                 nvp = &(nvc->nvc_port[j]);
2635                 mutex_enter(&nvp->nvp_mutex);
2636                 (*(nvp->nvp_ctlp->nvc_set_intr))(nvp,
2637                     NV_INTR_CLEAR_ALL|NV_INTR_ENABLE);
2638                 mutex_exit(&nvp->nvp_mutex);
2639         }
2640 }
2641 
2642 
2643 /*
2644  * Initialize the controller and set up driver data structures.
2645  * determine if ck804 or mcp5x class.
2646  */
2647 static int
2648 nv_init_ctl(nv_ctl_t *nvc, ddi_acc_handle_t pci_conf_handle)
2649 {
2650         struct sata_hba_tran stran;
2651         nv_port_t *nvp;
2652         int j;
2653         uchar_t *cmd_addr, *ctl_addr, *bm_addr;
2654         ddi_acc_handle_t bar5_hdl = nvc->nvc_bar_hdl[5];
2655         uchar_t *bar5  = nvc->nvc_bar_addr[5];
2656         uint32_t reg32;
2657         uint8_t reg8, reg8_save;
2658 
2659         NVLOG(NVDBG_INIT, nvc, NULL, "nv_init_ctl entered", NULL);
2660 


2661         nvc->nvc_mcp5x_flag = B_FALSE;

2662 
2663         /*
2664          * Need to set bit 2 to 1 at config offset 0x50
2665          * to enable access to the bar5 registers.
2666          */
2667         reg32 = pci_config_get32(pci_conf_handle, NV_SATA_CFG_20);
2668         if (!(reg32 & NV_BAR5_SPACE_EN)) {
2669                 pci_config_put32(pci_conf_handle, NV_SATA_CFG_20,
2670                     reg32 | NV_BAR5_SPACE_EN);
2671         }
2672 
2673         /*
2674          * Determine if this is ck804 or mcp5x.  ck804 will map in the
2675          * task file registers into bar5 while mcp5x won't.  The offset of
2676          * the task file registers in mcp5x's space is unused, so it will
2677          * return zero.  So check one of the task file registers to see if it is
2678          * writable and reads back what was written.  If it's mcp5x it will
2679          * return back 0xff whereas ck804 will return the value written.
2680          */
2681         reg8_save = nv_get8(bar5_hdl,
2682             (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X));
2683 
2684 
2685         for (j = 1; j < 3; j++) {
2686 
2687                 nv_put8(bar5_hdl, (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X), j);
2688                 reg8 = nv_get8(bar5_hdl,
2689                     (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X));
2690 
2691                 if (reg8 != j) {

2692                         nvc->nvc_mcp5x_flag = B_TRUE;
2693                         break;
2694                 }
2695         }
2696 
2697         nv_put8(bar5_hdl, (uint8_t *)(bar5 + NV_BAR5_TRAN_LEN_CH_X), reg8_save);
2698 
2699         if (nvc->nvc_mcp5x_flag == B_FALSE) {
2700                 NVLOG(NVDBG_INIT, nvc, NULL, "controller is CK804/MCP04",
2701                     NULL);
2702                 nvc->nvc_interrupt = ck804_intr;
2703                 nvc->nvc_reg_init = ck804_reg_init;
2704                 nvc->nvc_set_intr = ck804_set_intr;
2705         } else {
2706                 NVLOG(NVDBG_INIT, nvc, NULL, "controller is MCP51/MCP55/MCP61",
2707                     NULL);
2708                 nvc->nvc_interrupt = mcp5x_intr;
2709                 nvc->nvc_reg_init = mcp5x_reg_init;
2710                 nvc->nvc_set_intr = mcp5x_set_intr;
2711         }
2712 
2713 
2714         stran.sata_tran_hba_rev = SATA_TRAN_HBA_REV;
2715         stran.sata_tran_hba_dip = nvc->nvc_dip;
2716         stran.sata_tran_hba_num_cports = NV_NUM_PORTS;
2717         stran.sata_tran_hba_features_support =
2718             SATA_CTLF_HOTPLUG | SATA_CTLF_ASN | SATA_CTLF_ATAPI;
2719         stran.sata_tran_hba_qdepth = NV_QUEUE_SLOTS;
2720         stran.sata_tran_probe_port = nv_sata_probe;
2721         stran.sata_tran_start = nv_sata_start;
2722         stran.sata_tran_abort = nv_sata_abort;
2723         stran.sata_tran_reset_dport = nv_sata_reset;
2724         stran.sata_tran_selftest = NULL;
2725         stran.sata_tran_hotplug_ops = &nv_hotplug_ops;
2726         stran.sata_tran_pwrmgt_ops = NULL;
2727         stran.sata_tran_ioctl = NULL;