Video PM Methods
Peter Jones
pjones at redhat.com
Wed May 17 08:45:51 PDT 2006
OK, update of the sample code I posted. This has a way to do detection
of "stealth" devices which don't properly identify themselves. The
detection of those devices can't be represented in e.g. XML, but I don't
think there's a way to solve that using DMI _or_ PCI IDs.
(note that we could adapt this table to have match data from PCI as well
as DMI, but unless we can show a large number of machines where that's
necessary, that's probably extra work for no reason).
So, new pseudocode:
typedef enum {
S3_BIOS = 0x1,
S3_MODE = 0x2,
SUSPEND_VGAMODE_3 = 0x4,
SUSPEND_DPMS_SUSPEND = 0x8,
...
RESUME_VBESTATE_RESTORE = 0x100,
RESUME_VBEMODE_RESTORE = 0x101,
RESUME_VBE_POST = 0x102,
RESUME_DPMS_ON = 0x104,
...
} suspend_resume_flags;
#define PCI_VENDOR_ANY 0x10000
#define PCI_VENDOR_NOT 0x20000
#define PCI_TABLE_END 0x40000
#define PCI_DEVICE_ANY PCI_VENDOR_ANY
#define PCI_DEVICE_NOT PCI_VENDOR_NOT
struct pci_device_table {
u32 vendor_id;
u32 device_id;
u32 subvendor_id;
u32 subdevice_id;
u32 flags;
int (*fixup)(struct pci_dev *dev);
} pci_devices[] = {
{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
PCI_VENDOR_ATI, PCI_DEVICE_ANY,
0, generic_ati_discovery_fixup },
{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
PCI_VENDOR_RETARDED, PCI_DEVICE_UNLABELED_CARD_12345,
SUSPEND_DPMS_SUSPEND },
{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
PCI_VENDOR_IBM, PCI_DEVICE_ANY | PCI_DEVICE_NOT | PCI_DEVICE_IBM_BADDEV,
SUSPEND_DPMS_SUSPEND },
{ PCI_VENDOR_ATI, PCI_DEVICE_ANY,
PCI_VENDOR_IBM, PCI_DEVICE_IBM_BADDEV,
some other set of flags },
{ PCI_VENDOR_INTEL, PCI_DEVICE_I915,
PCI_VENDOR_ANY, PCI_DEVICE_ANY,
S3_BIOS | S3_MODE },
{ .vendor_id = PCI_TABLE_END }
};
static inline struct pci_device_table * get_device_entry(struct pci_dev *dev, int fixup) {
struct pci_device_table *cur;
for (cur = pci_devices ; cur->vendor_id != PCI_TABLE_END ; cur++) {
if (cur->flags && cur->fixup || !cur->flags && !cur->fixup) {
/* XXX emit a warning about the table being bogus */
continue;
}
if (cur->vendor_id != PCI_VENDOR_ANY) {
if (dev->vendor_id != (cur->vendor_id & 0xffff) ||
(cur->vendor_id & PCI_VENDOR_NOT))
continue;
}
if (cur->device_id != PCI_DEVICE_ANY) {
if (dev->device_id != (cur->device_id & 0xffff) ||
(cur->device_id & PCI_DEVICE_NOT))
continue;
}
if (cur->subvendor_id != PCI_VENDOR_ANY) {
if (dev->subvendor_id != (cur->subvendor_id & 0xffff) ||
(cur->subvendor_id & PCI_VENDOR_NOT))
continue;
}
if (cur->subdevice_id != PCI_DEVICE_ANY) {
if (dev->subdevice_id != (cur->subdevice_id & 0xffff) ||
(cur->subdevice_id & PCI_DEVICE_NOT))
continue;
}
if (fixup && cur->fixup || !fixup && !cur->fixup)
return cur;
}
return NULL;
}
static inline int get_pci_flags(struct pci_dev *dev) {
struct pci_device_table *info;
u32 flags = 0;
info = get_device_entry(dev, 1);
if (info)
info->fixup(dev);
info = get_device_entry(dev, 0);
if (info)
flags = info->flags;
return flags;
}
--
Peter
More information about the hal
mailing list