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-2013 Solarflare Communications Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/ddi.h>
  29 #include <sys/sunddi.h>
  30 #include <sys/stream.h>
  31 #include <sys/dlpi.h>
  32 
  33 #include "sfxge.h"
  34 
  35 int
  36 sfxge_bar_init(sfxge_t *sp)
  37 {
  38         efsys_bar_t *esbp = &(sp->s_bar);
  39         ddi_device_acc_attr_t devacc;
  40         int rc;
  41 
  42         devacc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
  43         devacc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
  44         devacc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
  45 
  46         if (ddi_regs_map_setup(sp->s_dip, EFX_MEM_BAR, &(esbp->esb_base), 0, 0,
  47             &devacc, &(esbp->esb_handle)) != DDI_SUCCESS) {
  48                 rc = ENODEV;
  49                 goto fail1;
  50         }
  51 
  52         mutex_init(&(esbp->esb_lock), NULL, MUTEX_DRIVER, NULL);
  53 
  54         return (0);
  55 
  56 fail1:
  57         DTRACE_PROBE1(fail1, int, rc);
  58 
  59         return (rc);
  60 }
  61 
  62 int
  63 sfxge_bar_ioctl(sfxge_t *sp, sfxge_bar_ioc_t *sbip)
  64 {
  65         efsys_bar_t *esbp = &(sp->s_bar);
  66         efx_oword_t oword;
  67         int rc;
  68 
  69         if (!IS_P2ALIGNED(sbip->sbi_addr, sizeof (efx_oword_t))) {
  70                 rc = EINVAL;
  71                 goto fail1;
  72         }
  73 
  74         switch (sbip->sbi_op) {
  75         case SFXGE_BAR_OP_READ:
  76                 EFSYS_BAR_READO(esbp, sbip->sbi_addr, &oword, B_TRUE);
  77 
  78                 sbip->sbi_data[0] = EFX_OWORD_FIELD(oword, EFX_DWORD_0);
  79                 sbip->sbi_data[1] = EFX_OWORD_FIELD(oword, EFX_DWORD_1);
  80                 sbip->sbi_data[2] = EFX_OWORD_FIELD(oword, EFX_DWORD_2);
  81                 sbip->sbi_data[3] = EFX_OWORD_FIELD(oword, EFX_DWORD_3);
  82 
  83                 break;
  84 
  85         case SFXGE_BAR_OP_WRITE:
  86                 EFX_POPULATE_OWORD_4(oword,
  87                     EFX_DWORD_0, sbip->sbi_data[0],
  88                     EFX_DWORD_1, sbip->sbi_data[1],
  89                     EFX_DWORD_2, sbip->sbi_data[2],
  90                     EFX_DWORD_3, sbip->sbi_data[3]);
  91 
  92                 EFSYS_BAR_WRITEO(esbp, sbip->sbi_addr, &oword, B_TRUE);
  93                 break;
  94 
  95         default:
  96                 rc = ENOTSUP;
  97                 goto fail2;
  98         }
  99 
 100         return (0);
 101 
 102 fail2:
 103         DTRACE_PROBE(fail2);
 104 fail1:
 105         DTRACE_PROBE1(fail1, int, rc);
 106 
 107         return (rc);
 108 }
 109 
 110 void
 111 sfxge_bar_fini(sfxge_t *sp)
 112 {
 113         efsys_bar_t *esbp = &(sp->s_bar);
 114 
 115         ddi_regs_map_free(&(esbp->esb_handle));
 116 
 117         mutex_destroy(&(esbp->esb_lock));
 118 
 119         esbp->esb_base = NULL;
 120         esbp->esb_handle = NULL;
 121 }