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.
This commit is contained in:
parent
3c5f05720a
commit
fe6f56bfb7
@ -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 @@ pci_enumerate_bus_generic(struct pci_softc *sc,
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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 @@ typedef u_int8_t pci_revision_t;
|
||||
#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
|
||||
|
@ -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.
|
||||
@ -209,6 +209,17 @@ struct proc;
|
||||
int pci_devioctl __P((pci_chipset_tag_t, pcitag_t, u_long, caddr_t,
|
||||
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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user