Subject: Re: pci_read_config_byte
To: Hubert Feyrer <hubert@feyrer.de>
From: Ed <garbageout@sbcglobal.net>
List: tech-kern
Date: 05/28/2005 13:26:29
Hubert Feyrer wrote:
> On Sat, 28 May 2005, Ed wrote:
> 
>> I'm borrowing some code from Linux.  What is the NetBSD equivalent of 
>> the Linux functions pci_read_config_byte and pci_write_config_byte?  I 
>> found pci_conf_read and pci_conf_write, but that seems to read and 
>> write a whole dword.  If this is not the correct forum for kernel 
>> hacking, please advise.
> 
> 
> Maybe say (on the list!) what you want to do and/or what 
> pci_read_config_byte etc. actually do? A prototype or so may help.
> 
> 
>  - Hubert

So here's the piece of code I'm borrowing from Linux followed by my 
implementation in NetBSD.  Note that it SEEMS to work correctly, but I 
am concerned about whether or not it IS correct.  Also, this is a pretty 
important patch because it fixes a bunch of siside lost interrupt 
problems.  Please advise.

Here's the original Linux code:

#define SIS_DETECT_REGISTER 0x40

static void __init quirk_sis_503(struct pci_dev *dev)
{
	u8 reg;
	u16 devid;

	pci_read_config_byte(dev, SIS_DETECT_REGISTER, &reg);
	pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg | (1 << 6));
	pci_read_config_word(dev, PCI_DEVICE_ID, &devid);
	if (((devid & 0xfff0) != 0x0960) && (devid != 0x0018)) {
		pci_write_config_byte(dev, SIS_DETECT_REGISTER, reg);
		return;
	}

	/* Make people aware that we changed the config.. */
	printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 
(compatible=%d)\n", devid, sis_96x_compatible);

	/*
	 * Ok, it now shows up as a 96x.. The 96x quirks are after
	 * the 503 quirk in the quirk table, so they'll automatically
	 * run and enable things like the SMBus device
	 */
	dev->device = devid;
}

Here's my (working, but questionably correct) implementation for NetBSD:

static int
sis_hostbr_quirk(struct pci_attach_args *pa)
{
     pcireg_t id, reg;

	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SIS ||
         PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_SIS_85C503) {
		return 0;
     }

     reg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
     pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, reg | (1 << 6));
     id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
     if (((PCI_PRODUCT(id) & 0xfff0) != 0x0960)
         && (PCI_PRODUCT(id) != 0x0018)) {
         pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, reg);
         return 0;
     }

     aprint_normal("hidden ");
     pa->pa_id = id;
     return 1;
}