1 /*
   2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 #pragma ident   "%Z%%M% %I%     %E% SMI"
   7 
   8 #include <sys/kstat.h>
   9 #include <sys/ddi.h>
  10 #include <sys/sunddi.h>
  11 #include <sys/sunldi.h>
  12 #include <sys/agpgart.h>
  13 #include <sys/agp/agpdefs.h>
  14 #include <sys/agp/agpgart_impl.h>
  15 
  16 /*
  17  * The values of type agp_arc_type_t are used as indices into arc_name
  18  * So if agp_arc_type_t's values are changed in the future, the content
  19  * of arc_name must be changed accordingly.
  20  */
  21 static const char *arc_name[] = {
  22         "IGD_810",
  23         "IGD_830",
  24         "INTEL_AGP",
  25         "AMD64_AGP",
  26         "AMD64_NONAGP",
  27         "UNKNOWN"
  28 };
  29 
  30 static char *agpkstat_name[] = {
  31         "&arc_type",
  32         "master_dev_id",
  33         "master_dev_version",
  34         "master_dev_status",
  35         "$prealloc_size",
  36         "target_dev_id",
  37         "target_dev_version",
  38         "target_dev_status",
  39         "$aper_base",
  40         "$aper_size",
  41         "&agp_enabled",
  42         "agp_mode_set",
  43         "$aper_used",
  44         NULL
  45 };
  46 
  47 static void
  48 agp_set_char_kstat(kstat_named_t *knp, const char *s)
  49 {
  50         (void) strlcpy(knp->value.c, s, sizeof (knp->value.c));
  51 }
  52 
  53 static int
  54 agp_kstat_update(kstat_t *ksp, int flag)
  55 {
  56         agpgart_softstate_t *sc;
  57         kstat_named_t *knp;
  58         int tmp;
  59 
  60         if (flag != KSTAT_READ)
  61                 return (EACCES);
  62 
  63         sc = ksp->ks_private;
  64         knp = ksp->ks_data;
  65 
  66         agp_set_char_kstat(knp++, arc_name[sc->asoft_devreg.agprd_arctype]);
  67         (knp++)->value.ui32 = sc->asoft_info.agpki_mdevid;
  68         (knp++)->value.ui32 = (sc->asoft_info.agpki_mver.agpv_major<<16) |
  69             sc->asoft_info.agpki_mver.agpv_minor;
  70         (knp++)->value.ui32 = sc->asoft_info.agpki_mstatus;
  71         (knp++)->value.ui64 = (sc->asoft_info.agpki_presize << 10) & UI32_MASK;
  72         (knp++)->value.ui32 = sc->asoft_info.agpki_tdevid;
  73         (knp++)->value.ui32 = (sc->asoft_info.agpki_tver.agpv_major<<16) |
  74             sc->asoft_info.agpki_tver.agpv_minor;
  75         (knp++)->value.ui32 = sc->asoft_info.agpki_tstatus;
  76         (knp++)->value.ui64 = sc->asoft_info.agpki_aperbase;
  77         (knp++)->value.ui64 =
  78             (sc->asoft_info.agpki_apersize << 20) & UI32_MASK;
  79 
  80         tmp = sc->asoft_agpen;
  81         agp_set_char_kstat(knp++, (tmp > 0) ? "yes" : "no");
  82 
  83         (knp++)->value.ui32 = sc->asoft_mode;
  84         (knp++)->value.ui64 = (sc->asoft_pgused << 12) & UI32_MASK;
  85 
  86         return (0);
  87 }
  88 
  89 int
  90 agp_init_kstats(agpgart_softstate_t *sc)
  91 {
  92         int instance;
  93         kstat_t *ksp;
  94         kstat_named_t *knp;
  95         char *np;
  96         int type;
  97         char **aknp;
  98 
  99         instance = ddi_get_instance(sc->asoft_dip);
 100         aknp = agpkstat_name;
 101         ksp = kstat_create(AGPGART_DEVNODE, instance, "agpinfo", "agp",
 102             KSTAT_TYPE_NAMED, sizeof (agpkstat_name)/sizeof (char *) - 1,
 103             KSTAT_FLAG_PERSISTENT);
 104         if (ksp == NULL)
 105                 return (NULL);
 106 
 107         ksp->ks_private = sc;
 108         ksp->ks_update = agp_kstat_update;
 109         for (knp = ksp->ks_data; (np = (*aknp)) != NULL; knp++, aknp++) {
 110                 switch (*np) {
 111                 case '$':
 112                         np += 1;
 113                         type = KSTAT_DATA_UINT64;
 114                         break;
 115                 case '&':
 116                         np += 1;
 117                         type = KSTAT_DATA_CHAR;
 118                         break;
 119                 default:
 120                         type = KSTAT_DATA_UINT32;
 121                         break;
 122 
 123                 }
 124                 kstat_named_init(knp, np, type);
 125         }
 126         kstat_install(ksp);
 127 
 128         sc->asoft_ksp = ksp;
 129 
 130         return (0);
 131 }
 132 
 133 void
 134 agp_fini_kstats(agpgart_softstate_t *sc)
 135 {
 136         ASSERT(sc->asoft_ksp);
 137         kstat_delete(sc->asoft_ksp);
 138 }