Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci add support for the per-device power management ...



details:   https://anonhg.NetBSD.org/src/rev/35ff9137dae2
branches:  trunk
changeset: 532974:35ff9137dae2
user:      tshiozak <tshiozak%NetBSD.org@localhost>
date:      Tue Jun 18 13:18:37 2002 +0000

description:
add support for the per-device power management capability.

int pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int newstate)
        set power state of the device to newstate.
int pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag)
        get current power state of the device.

In the future, these functions will be used for ACPI support.

diffstat:

 sys/dev/pci/pci.c    |  83 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/pci/pcireg.h |  10 +++++-
 sys/dev/pci/pcivar.h |  13 +++++++-
 3 files changed, 101 insertions(+), 5 deletions(-)

diffs (154 lines):

diff -r f44138191299 -r 35ff9137dae2 sys/dev/pci/pci.c
--- a/sys/dev/pci/pci.c Tue Jun 18 13:01:30 2002 +0000
+++ b/sys/dev/pci/pci.c Tue Jun 18 13:18:37 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pci.c,v 1.65 2002/05/18 21:40:41 sommerfeld Exp $      */
+/*     $NetBSD: pci.c,v 1.66 2002/06/18 13:18:37 tshiozak Exp $        */
 
 /*
  * Copyright (c) 1995, 1996, 1997, 1998
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.65 2002/05/18 21:40:41 sommerfeld Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.66 2002/06/18 13:18:37 tshiozak Exp $");
 
 #include "opt_pci.h"
 
@@ -448,3 +448,82 @@
        }
        return (0);
 }
+
+/*
+ * Power Management Capability (Rev 2.2)
+ */
+
+int
+pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int newstate)
+{
+       int offset;
+       pcireg_t value, cap, now;
+
+       if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value))
+               return (EOPNOTSUPP);
+
+       cap = value >> 16;
+       value = pci_conf_read(pc, tag, offset+PCI_PMCSR);
+       now    = value & PCI_PMCSR_STATE_MASK;
+       value &= ~PCI_PMCSR_STATE_MASK;
+       switch (newstate) {
+       case PCI_PWR_D0:
+               if (now == PCI_PMCSR_STATE_D0)
+                       return (0);
+               value |= PCI_PMCSR_STATE_D0;
+               break;
+       case PCI_PWR_D1:
+               if (now == PCI_PMCSR_STATE_D1)
+                       return (0);
+               if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3)
+                       return (EINVAL);
+               if (!(cap & PCI_PMCR_D1SUPP))
+                       return (EOPNOTSUPP);
+               value |= PCI_PMCSR_STATE_D1;
+               break;
+       case PCI_PWR_D2:
+               if (now == PCI_PMCSR_STATE_D2)
+                       return (0);
+               if (now == PCI_PMCSR_STATE_D3)
+                       return (EINVAL);
+               if (!(cap & PCI_PMCR_D2SUPP))
+                       return (EOPNOTSUPP);
+               value |= PCI_PMCSR_STATE_D2;
+               break;
+       case PCI_PWR_D3:
+               if (now == PCI_PMCSR_STATE_D3)
+                       return (0);
+               value |= PCI_PMCSR_STATE_D3;
+               break;
+       default:
+               return (EINVAL);
+       }
+       pci_conf_write(pc, tag, offset+PCI_PMCSR, value);
+       DELAY(1000);
+
+       return (0);
+}
+
+int
+pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag)
+{
+       int offset;
+       pcireg_t value;
+
+       if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value))
+               return (PCI_PWR_D0);
+       value = pci_conf_read(pc, tag, offset+PCI_PMCSR);
+       value &= PCI_PMCSR_STATE_MASK;
+       switch (value) {
+       case PCI_PMCSR_STATE_D0:
+               return (PCI_PWR_D0);
+       case PCI_PMCSR_STATE_D1:
+               return (PCI_PWR_D1);
+       case PCI_PMCSR_STATE_D2:
+               return (PCI_PWR_D2);
+       case PCI_PMCSR_STATE_D3:
+               return (PCI_PWR_D3);
+       }
+
+       return (PCI_PWR_D0);
+}
diff -r f44138191299 -r 35ff9137dae2 sys/dev/pci/pcireg.h
--- a/sys/dev/pci/pcireg.h      Tue Jun 18 13:01:30 2002 +0000
+++ b/sys/dev/pci/pcireg.h      Tue Jun 18 13:18:37 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pcireg.h,v 1.37 2002/03/22 20:03:20 drochner Exp $     */
+/*     $NetBSD: pcireg.h,v 1.38 2002/06/18 13:18:37 tshiozak Exp $     */
 
 /*
  * Copyright (c) 1995, 1996, 1999, 2000
@@ -418,9 +418,15 @@
 #define        PCI_CAP_HOTPLUG         0x0c
 
 /*
- * Power Management Control Status Register; access via capability pointer.
+ * Power Management Capability; access via capability pointer.
  */
 
+/* Power Management Capability Register */
+#define PCI_PMCR               0x02
+#define PCI_PMCR_D1SUPP                0x0200
+#define PCI_PMCR_D2SUPP                0x0400
+/* Power Management Control Status Register */
+#define PCI_PMCSR              0x04
 #define PCI_PMCSR_STATE_MASK   0x03
 #define PCI_PMCSR_STATE_D0      0x00
 #define PCI_PMCSR_STATE_D1      0x01
diff -r f44138191299 -r 35ff9137dae2 sys/dev/pci/pcivar.h
--- a/sys/dev/pci/pcivar.h      Tue Jun 18 13:01:30 2002 +0000
+++ b/sys/dev/pci/pcivar.h      Tue Jun 18 13:18:37 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pcivar.h,v 1.52 2002/05/30 12:06:43 drochner Exp $     */
+/*     $NetBSD: pcivar.h,v 1.53 2002/06/18 13:18:37 tshiozak Exp $     */
 
 /*
  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
@@ -210,6 +210,17 @@
            int flag, struct proc *));
 
 /*
+ * Power Management (PCI 2.2)
+ */
+
+#define PCI_PWR_D0     0
+#define PCI_PWR_D1     1
+#define PCI_PWR_D2     2
+#define PCI_PWR_D3     3
+int    pci_set_powerstate __P((pci_chipset_tag_t, pcitag_t, int));
+int    pci_get_powerstate __P((pci_chipset_tag_t, pcitag_t));
+
+/*
  * Misc.
  */
 char   *pci_findvendor __P((pcireg_t));



Home | Main Index | Thread Index | Old Index