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  * Copyright 2007 Sun Microsystems, Inc.
  23  * All rights reserved.  Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.
  28  * Copyright 2014 Pluribus Networks, Inc.
  29  */
  30 
  31 /*
  32  * ddi_dki_comm.inc - Part of a pseudo-kernel to use when analyzing drivers
  33  * with warlock.
  34  *
  35  * The main idea here is to represent all of the ways that the kernel can
  36  * call into the driver, so that warlock has the correct view of the call
  37  * graph.
  38  *
  39  * This file represents the stuff in common between the DDI/DKI spec and
  40  * the current implementation.  It is included by both ddi_dki_{spec,impl}.c
  41  *
  42  * This is a SPARC version; some functions (e.g. ddi_dma_nextwin) should
  43  * be changed for an x86 version.
  44  */
  45 
  46 #include <sys/note.h>
  47 #include <sys/devops.h>
  48 #include <sys/ddi.h>
  49 #include <sys/sunddi.h>
  50 #include <sys/proc.h>
  51 
  52 _NOTE(DATA_READABLE_WITHOUT_LOCK( dev_ops cb_ops bus_ops ))
  53 
  54 /*
  55  * Now define a dev_ops, a cb_ops, and a bus_ops with 0 for each
  56  * entry point, so that warlock doesn't complain that these
  57  * function pointers have no bindings.
  58  *      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
  59  */
  60 struct dev_ops *devops_p, warlock_dev_ops = {
  61         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  62 };
  63 
  64 struct cb_ops *cbops_p, warlock_cb_ops = {
  65         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  66 };
  67 
  68 struct bus_ops *busops_p, warlock_bus_ops = {
  69         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  70 };
  71 
  72 
  73 /* This rendition of mod_remove() tells warlock that it calls detach. */
  74 int
  75 mod_remove(struct modlinkage *a) {
  76         (*devops_p->devo_detach)(NULL, 0);
  77 }
  78 
  79 /* This rendition of physio() shows that it calls its func ptr args. */
  80 int
  81 physio(
  82         int (*strategy)(struct buf *),
  83         struct buf *a,
  84         dev_t b,
  85         int c,
  86         void (*mincnt)(struct buf *),
  87         struct uio *d)
  88 {
  89         (*strategy)(0);
  90         (*mincnt)(0);
  91 }
  92 
  93 /*
  94  * Tell warlock that args to some funcs get called back as separate threads.
  95  */
  96 timeout_id_t
  97 timeout(void (*fp)(void *), void *a, clock_t b)
  98 {
  99         thread_create(0, 0, (void (*)())fp, 0, 0, 0, 0, 0);
 100 }
 101 
 102 int
 103 ddi_add_intr(dev_info_t *a, uint_t b, ddi_iblock_cookie_t *c,
 104         ddi_idevice_cookie_t *d, uint_t (*fp)(caddr_t), caddr_t e)
 105 {
 106         thread_create(0, 0, (void (*)())fp, 0, 0, 0, 0, 0);
 107 }
 108 
 109 int
 110 ddi_add_softintr(dev_info_t *a, int b, ddi_softintr_t *c,
 111     ddi_iblock_cookie_t *d, ddi_idevice_cookie_t *e, uint_t (*fp)(caddr_t),
 112     caddr_t f)
 113 {
 114         thread_create(0, 0, (void (*)())fp, 0, 0, 0, 0, 0);
 115 }
 116 
 117 int
 118 ddi_intr_add_handler(ddi_intr_handle_t h, ddi_intr_handler_t inthandler,
 119     void *arg1, void *arg2)
 120 {
 121         thread_create(0, 0, (void (*)())inthandler, 0, 0, 0, 0, 0);
 122 }
 123 
 124 int
 125 ddi_intr_add_softint(dev_info_t *dip, ddi_softint_handle_t *h_p, int soft_pri,
 126     ddi_intr_handler_t handler, void *arg1)
 127 {
 128         thread_create(0, 0, (void (*)())handler, 0, 0, 0, 0, 0);
 129 }
 130 
 131 void
 132 ddi_set_callback(
 133         int (*fp)(caddr_t),
 134         caddr_t a,
 135         uintptr_t *b)
 136 {
 137         thread_create(0, 0, (void (*)())fp, 0, 0, 0, 0, 0);
 138 }
 139 
 140 int
 141 ddi_dma_map(
 142         dev_info_t *a,
 143         dev_info_t *b,
 144         struct ddi_dma_req *c,
 145         ddi_dma_handle_t *d)
 146 {
 147         struct bus_ops *ops;
 148         (*ops->bus_dma_map)(0, 0, 0, 0);
 149 }
 150 
 151 int
 152 ddi_dma_mctl(dev_info_t *a, dev_info_t *b, ddi_dma_handle_t c,
 153         enum ddi_dma_ctlops d, off_t *e, size_t *f, caddr_t *g,
 154         uint_t h)
 155 {
 156         struct bus_ops *ops;
 157         (*ops->bus_dma_ctl)(0, 0, 0, 0, 0, 0, 0, 0);
 158 }
 159 
 160 int
 161 ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom)
 162 {
 163         struct bus_ops *ops;
 164         (*ops->bus_dma_ctl)(0, 0, 0, 0, 0, 0, 0, 0);
 165 }
 166 
 167 int
 168 ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
 169     char *name, caddr_t valuep, int *lengthp)
 170 {
 171         struct bus_ops *ops;
 172         (*ops->bus_prop_op)(0, 0, 0, 0, 0, 0, 0, 0);
 173 }
 174 
 175 int
 176 ddi_add_event_handler(dev_info_t *dip, ddi_eventcookie_t event,
 177     void (*handler)(dev_info_t *, ddi_eventcookie_t, void *, void *),
 178     void *arg, ddi_callback_id_t *id)
 179 {
 180         struct bus_ops *ops;
 181         return ((*ops->bus_add_eventcall)(dip, dip, event, handler, arg, id));
 182 }
 183 
 184 int
 185 ddi_remove_event_handler(ddi_callback_id_t id)
 186 {
 187         dev_info_t *dip;
 188         struct bus_ops *ops;
 189         return ((*ops->bus_remove_eventcall)(dip, id));
 190 }
 191 
 192 
 193 int
 194 ddi_get_eventcookie(dev_info_t *dip, char *name,
 195     ddi_eventcookie_t *event_cookiep)
 196 {
 197         struct bus_ops *ops;
 198         return ((*ops->bus_get_eventcookie)(dip, dip,
 199             name, event_cookiep));
 200 }