All of lore.kernel.org
 help / color / mirror / Atom feed
* pci api question
@ 2002-12-13 17:07 Jason Lunz
  0 siblings, 0 replies; only message in thread
From: Jason Lunz @ 2002-12-13 17:07 UTC (permalink / raw)
  To: linux-kernel


I have a userspace program that I'd like to port to the kernel. The only
thing it really does is flip a bit in a pci config register of my Via
northbridge.

I've got it mostly done, except that I'm not sure how to express what
the userspace program does using the linux pci api. The (very ugly)
userspace program, in a nutshell, does this:

	#define DWORD unsigned long

	DWORD PCIRead(int reg, int fn=0, int dev=0,int bus=0, int port=0xcf8)
	{
		DWORD r=0x80000000;
		DWORD ret,org;
		
		r|=(( bus & 0xff) <<16);
		r|=(( dev & 0x1f) <<11);
		r|=(( fn &  0x7 ) << 8);
		r|=(( reg & 0xfc) );
		
		org=inl(port);
		outl(r,port);
		ret=inl(port+4);
		outl(org,port);
		
		return ret;
	}

	void PCIWrite(DWORD val, int reg, int fn=0, int dev=0,int bus=0, int port=0xcf8)
	{
		DWORD r=0x80000000;
		DWORD org;
		
		r|=(( bus & 0xff) <<16);
		r|=(( dev & 0x1f) <<11);
		r|=(( fn &  0x7 ) << 8);
		r|=(( reg & 0xfc) );

		org=inl(port);
		outl(r,port);
		outl(val,port+4);
		outl(org,port);
	}
		
	void main(void) {
		DWORD res;

		res =PCIRead(0x52,0,0,0);
		printf("read %#.8x\n", res);
		res |= 0x00800000;
		printf("writing %#.8x\n", res);
		PCIWrite(res,0x52,0,0,0);
	}

this prints out

	read 0xb46ba417
	writing 0xb4eba417

I want to do this within the kernel. I have this (abridged):

	#include <linux/module.h>
	#include <linux/pci.h>

	static int __devinit via_nb_init(struct pci_dev *pdev, const struct pci_device_id *ent);
	static void __devexit via_nb_remove(struct pci_dev *pdev);

	static struct pci_device_id via_nb_tbl[] __devinitdata = {
		{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, PCI_ANY_ID, PCI_ANY_ID,},
		{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_0, PCI_ANY_ID, PCI_ANY_ID,},
		{0,}
	};

	static struct pci_driver via_nb_driver = {
		name:		"via83xx_pm-nb",
		id_table:	via_nb_tbl,
		probe:		via_nb_init,
		remove:		via_nb_remove,
	};

	static int __devinit
	via_nb_init(struct pci_dev *pdev, const struct pci_device_id *ent)
	{
		u32 enable;
		printk(KERN_INFO "via83xx_pm: Initializing northbridge %s\n", pdev->name);

		pci_read_config_dword(pdev, 0x52, &enable);
		printk(KERN_INFO "read %#.8x\n", enable);
		enable |= 0x00800000;
		printk(KERN_INFO "writing %#.8x to 0x52\n", enable);
		pci_write_config_dword(pdev, 0x52, enable);
		return 0;
	}

	static void __devexit
	via_nb_remove(struct pci_dev *pdev)
	{
		u32 enable;
		pci_read_config_dword(pdev, 0x52, &enable);
		printk(KERN_INFO "0x52 is %#.8x\n", enable);
		enable &= ~0x00800000;
		printk(KERN_INFO "would write %#.8x to 0x52\n", enable);
		pci_write_config_dword(pdev, 0x52, enable);
	}

	static int __init
	via83xx_pm_init(void)
	{
		found = pci_module_init(&via_nb_driver);
		if (found < 0) {
			printk(KERN_ERR "via83xx_pm: Could not find northbridge\n");
			return 1;
		}

		return 0;
	}

	static void __exit
	via83xx_pm_cleanup(void)
	{
		pci_unregister_driver(&via_nb_driver);
	}

	MODULE_LICENSE("GPL");
	module_init(via83xx_pm_init);
	module_exit(via83xx_pm_cleanup);

however, the pci_(read|write)_config_dword() calls seem to be changing
a different register than the userspace program. The kernel module
prints out these (very different) values:

	read 0xc12cc400
	would write 0xc1acc400

The userspace version works. The kernel one doesn't.  Any idea what I'm
doing wrong?

thanks, Jason

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-12-13 17:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-13 17:07 pci api question Jason Lunz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.