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