public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:50 [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci Jesse Barnes
@ 2004-12-16 16:39 ` Randy.Dunlap
  2004-12-16 17:07   ` Jesse Barnes
  2004-12-16 17:55   ` Doug Maxey
  2004-12-16 16:56 ` Christoph Hellwig
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Randy.Dunlap @ 2004-12-16 16:39 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, linux-ia64, linux-kernel, willy

Jesse Barnes wrote:
> This patch documents the /proc/bus/pci interface and adds some optional 
> architecture specific APIs for accessing legacy I/O port and memory space.  
> This is necessary on platforms where legacy I/O port space doesn't 'soft 
> fail' like it does on PCs, and is useful for systems that can route legacy 
> space to different PCI busses.
> 
> I've incorporated all the feedback I've received so far, so I think it's ready 
> to send on to Andrew for inclusion, if someone could give the proc-pci.txt 
> documentation a last read (and/or comment on other stuff I may have missed).

meta-comment:
Would you (and not just you :) include a diffstat summary so we
can see which files are being changed?  something like this:


  Documentation/filesystems/proc-pci.txt |  126 
+++++++++++++++++++++++++++++++++
  arch/ia64/pci/pci.c                    |  105 
+++++++++++++++++++++++++++
  arch/ia64/sn/pci/pci_dma.c             |   74 +++++++++++++++++++
  drivers/pci/proc.c                     |  100 +++++++++++++++++++++++---
  include/asm-ia64/machvec.h             |   24 ++++++
  include/asm-ia64/machvec_init.h        |    3
  include/asm-ia64/machvec_sn2.h         |    6 +
  include/asm-ia64/pci.h                 |    4 +
  include/asm-ia64/sn/sn_sal.h           |   47 ++++++++++++
  include/linux/pci.h                    |   12 ++-
  10 files changed, 488 insertions(+), 13 deletions(-)

-- 
~Randy

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
@ 2004-12-16 16:50 Jesse Barnes
  2004-12-16 16:39 ` Randy.Dunlap
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 16:50 UTC (permalink / raw)
  To: linux-pci, linux-ia64, linux-kernel; +Cc: willy

[-- Attachment #1: Type: text/plain, Size: 580 bytes --]

This patch documents the /proc/bus/pci interface and adds some optional 
architecture specific APIs for accessing legacy I/O port and memory space.  
This is necessary on platforms where legacy I/O port space doesn't 'soft 
fail' like it does on PCs, and is useful for systems that can route legacy 
space to different PCI busses.

I've incorporated all the feedback I've received so far, so I think it's ready 
to send on to Andrew for inclusion, if someone could give the proc-pci.txt 
documentation a last read (and/or comment on other stuff I may have missed).

Thanks,
Jesse

[-- Attachment #2: legacy-ioctl-mem-api-6.patch --]
[-- Type: text/plain, Size: 23134 bytes --]

diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/arch/ia64/pci/pci.c linux-2.5-pciapi/arch/ia64/pci/pci.c
--- linux-2.5-pciapi.new/arch/ia64/pci/pci.c	2004-12-16 08:37:55.000000000 -0800
+++ linux-2.5-pciapi/arch/ia64/pci/pci.c	2004-12-14 14:08:45.000000000 -0800
@@ -514,11 +514,19 @@ pci_mmap_page_range (struct pci_dev *dev
 		 */
 		return -EINVAL;
 
+	if (mmap_state == pci_mmap_legacy_mem) {
+		unsigned long addr;
+		int ret;
+		if ((ret = pci_get_legacy_mem(dev, &addr)))
+			return ret;
+		vma->vm_pgoff += addr >> PAGE_SHIFT;
+	}
+
 	/*
 	 * Leave vm_pgoff as-is, the PCI space address is the physical
 	 * address on this platform.
 	 */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+	vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
 
 	if (write_combine)
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -533,6 +541,101 @@ pci_mmap_page_range (struct pci_dev *dev
 }
 
 /**
+ * ia64_pci_get_legacy_mem - generic legacy mem routine
+ * @dev: device pointer
+ * @addr: caller allocated variable for the base address
+ *
+ * Find the base of legacy memory for @dev.  This is typically the first
+ * megabyte of bus address space for @dev or is simply 0 on platforms whose
+ * chipsets support legacy I/O and memory routing.  Returns 0 on success
+ * or a standard error code on failure.
+ *
+ * This is the ia64 generic version of this routine.  Other platforms
+ * are free to override it with a machine vector.
+ */
+int ia64_pci_get_legacy_mem(struct pci_dev *dev, unsigned long *addr)
+{
+	*addr = 0;
+	return 0;
+}
+
+/**
+ * ia64_pci_legacy_read - read from legacy I/O space
+ * @dev: device to read
+ * @port: legacy port value
+ * @val: caller allocated storage for returned value
+ * @size: number of bytes to read
+ *
+ * Simply reads @size bytes from @port and puts the result in @val.
+ *
+ * Again, this (and the write routine) are generic versions that can be
+ * overridden by the platform.  This is necessary on platforms that don't
+ * support legacy I/O routing or that hard fail on legacy I/O timeouts.
+ */
+int ia64_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val, u8 size)
+{
+	int ret = 0;
+	unsigned long paddr = port;
+	unsigned long *addr;
+
+	switch (size) {
+	case 1:
+		addr = (unsigned long *)paddr;
+		*val = (u8)(*(volatile u8 *)(addr));
+		break;
+	case 2:
+		addr = (unsigned long *)paddr;
+		*val = (u16)(*(volatile u16 *)(addr));
+		break;
+	case 4:
+		addr = (unsigned long *)paddr;
+		*val = (u32)(*(volatile u32 *)(addr));
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * ia64_pci_legacy_write - perform a legacy I/O write
+ * @dev: device pointer
+ * @port: port to write
+ * @val: value to write
+ * @size: number of bytes to write from @val
+ *
+ * Simply writes @size bytes of @val to @port.
+ */
+int ia64_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val, u8 size)
+{
+	int ret = 0;
+	unsigned long paddr = port;
+	unsigned long *addr;
+
+	switch (size) {
+	case 1:
+		addr = (unsigned long *)paddr;
+		*(volatile u8 *)(addr) = (u8)(val);
+		break;
+	case 2:
+		addr = (unsigned long *)paddr;
+		*(volatile u16 *)(addr) = (u16)(val);
+		break;
+	case 4:
+		addr = (unsigned long *)paddr;
+		*(volatile u32 *)(addr) = (u32)(val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
  * pci_cacheline_size - determine cacheline size for PCI devices
  * @dev: void
  *
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/arch/ia64/sn/pci/pci_dma.c linux-2.5-pciapi/arch/ia64/sn/pci/pci_dma.c
--- linux-2.5-pciapi.new/arch/ia64/sn/pci/pci_dma.c	2004-12-16 08:37:55.000000000 -0800
+++ linux-2.5-pciapi/arch/ia64/sn/pci/pci_dma.c	2004-12-14 14:08:45.000000000 -0800
@@ -475,3 +475,77 @@ EXPORT_SYMBOL(sn_pci_alloc_consistent);
 EXPORT_SYMBOL(sn_pci_free_consistent);
 EXPORT_SYMBOL(sn_pci_dma_supported);
 EXPORT_SYMBOL(sn_dma_mapping_error);
+
+int sn_pci_get_legacy_mem(struct pci_dev *dev, unsigned long *addr)
+{
+	if (!SN_PCIDEV_BUSSOFT(dev))
+		return -ENODEV;
+
+	*addr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_mem | __IA64_UNCACHED_OFFSET;
+
+	return 0;
+}
+
+int sn_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val, u8 size)
+{
+	int ret = 0;
+	unsigned long addr;
+
+	if (!SN_PCIDEV_BUSSOFT(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	addr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+	addr += port;
+
+	ret = ia64_sn_probe_mem(addr, (long)size, (void *)val);
+
+	/* Read timed out, return -1 to emulate soft fail */
+	if (ret == 1)
+		*val = -1;
+
+	/* Invalid argument */
+	if (ret == 2)
+		ret = -EINVAL;
+
+ out:
+	return ret;
+}
+
+int sn_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val, u8 size)
+{
+	int ret = 0;
+	unsigned long paddr;
+	unsigned long *addr;
+
+	if (!SN_PCIDEV_BUSSOFT(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Put the phys addr in uncached space */
+	paddr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+	paddr += port;
+	addr = (unsigned long *)paddr;
+
+	switch (size) {
+	case 1:
+		*(volatile u8 *)(addr) = (u8)(val);
+		ret = 1;
+		break;
+	case 2:
+		*(volatile u16 *)(addr) = (u16)(val);
+		ret = 2;
+		break;
+	case 4:
+		*(volatile u32 *)(addr) = (u32)(val);
+		ret = 4;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+ out:
+	return ret;
+}
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/Documentation/filesystems/proc-pci.txt linux-2.5-pciapi/Documentation/filesystems/proc-pci.txt
--- linux-2.5-pciapi.new/Documentation/filesystems/proc-pci.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5-pciapi/Documentation/filesystems/proc-pci.txt	2004-12-15 15:15:01.000000000 -0800
@@ -0,0 +1,126 @@
+Directory layout
+
+/proc/bus/pci contains a list of PCI devices available on the system
+and can be used for driving PCI devices from userspace, getting a list
+of PCI devices, and hotplug support.  Example:
+
+  $ tree /proc/bus/pci
+  /proc/bus/pci/
+  |-- 01		directory for devices on bus 1 
+  |   |-- 01.0		single fn device in slot 1
+  |   |-- 03.0		single fn device in slot 3
+  |   `-- 04.0		single fn device in slot 4
+  |-- 02
+  |   |-- 01.0		single fn device in slot 1
+  |   |-- 02.0		<
+  |   |-- 02.1		< three function device on bus 2
+  |   `-- 02.2		< 
+  |-- 17
+  |   `-- 00.0		busses 17 and 1b have only one device each in
+  |			slot 0
+  |-- 1b
+  |   `-- 00.0
+  `-- devices		see below
+
+  4 directories, 10 files
+
+The devices file contains an entry for each PCI device in the system
+with information about the host addresses corresponding to the device
+BARs and which driver is bound to a device (if present).  This
+information can be used as an offset argument to mmap specific device
+files in the tree above.  Each field in the devices file is seperated
+by tabs with each device on a line by itself.  The fields are
+
+bus id
+?
+?
+host resource 0
+host resource 1
+host resource 2
+host resource 3
+host resource 4
+host resource 5
+host resource 6
+host resource 7
+BAR value 0
+BAR value 1
+BAR value 2
+BAR value 3
+BAR value 4
+BAR value 5
+BAR value 6
+driver name (if present)
+
+For example:
+
+0108	10a9100a	3e	c00000080f200000	0	0	0	0	0	0	100000	0	0	0	0	0	0	SGI-IOC4_IDE
+
+Available interfaces
+
+Each file corresponding to a device in /proc/bus/pci has open, read,
+write, lseek, ioctl, and mmap methods available.
+
+open
+  simply opens the device and returns a handle as expected
+
+read
+  reads from either PCI config space or legacy I/O space, using the
+  current file postion, depending on the current I/O mode setting.
+
+write
+  writes to either PCI config space or legacy I/O space, using the
+  current file postion, depending on the current I/O mode setting.
+
+  Note that reads and writes to legacy I/O space must be 1, 2 or 4
+  bytes in size with the appropriate buffer pointer.  Reads and writes
+  to config space can be arbitrarily sized.  Legacy I/O port space
+  reads and writes must also be to a file position <64k--the kernel will
+  route them to the target device.
+
+lseek
+  Can be used to set the current file position.  Note that the file
+  size is limited to 64k as that's how big legacy I/O space is.
+
+ioctl
+  ioctl is used to set the mode of a subsequent read, write or mmap
+  call.  Available ioctls (in linux/pci.h) include
+    PCIIOC_CONTROLLER - return PCI domain number
+    PCIIOC_MMAP_IS_IO - next mmap maps to I/O space
+    PCIIOC_MMAP_IS_MEM - next mmap maps to memory space
+    PCIIOC_MMAP_IS_LEGACY_MEM - next mmap maps to legacy memory space
+    PCIIOC_WRITE_COMBINE - try to use write gathering for the new
+                           region if the ioctl argument is true,
+                           otherwise disable write gathering
+    PCIIOC_RW_LEGACY_IO - read/writes will go to legacy I/O space
+    PCIIOC_RW_CONFIG - read/writes will go to config space
+  Note that not all architectures support the *_MMAP_* or *_RW_* ioctl
+  commands.  If they're not supported, ioctl will return -EINVAL.
+
+mmap
+  The final argument of mmap(2) must be a host address obtained from
+  /proc/bus/pci/devices or an address between 0 and 1M for legacy
+  memory mappings.  Only supported on some architectures.
+
+Examples
+
+	/* Read from the 3rd BAR of device in slot 1 of bus 1 */
+	int fd = open("/proc/bus/pci/01/01.0", O_RDONLY);
+	ioctl(fd, PCIIOC_RW_CONFIG); /* make sure we're using config space */
+	lseek(fd, 0x20, SEEK_SET);
+	read(fd, buf, 8);
+	close(fd);
+
+	/*
+	 * Do a legacy read of 1 byte (inb) from port 0x3cc from 1:1.0.
+	 * Note that this will just generate a bus cycle on bus 1 for port
+	 * 0x3cc, which the device in question may or may not respond to.
+	 * If there is no response, -1 will be returned.  Also note that
+	 * it may not be possible to generate legacy I/O port requests on
+	 * the bus or device specified, in that case the write will fail
+	 * with an appropriate error code.
+	 */
+	int fd = open("/proc/bus/pci/01/01.0", O_RDONLY);
+	ioctl(fd, PCIIOC_RW_LEGACY_IO); /* enable legacy I/O */
+	lseek(fd, 0x3cc, SEEK_SET);
+	read(fd, &val, 1);
+	close(fd);
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/drivers/pci/proc.c linux-2.5-pciapi/drivers/pci/proc.c
--- linux-2.5-pciapi.new/drivers/pci/proc.c	2004-12-16 08:38:04.000000000 -0800
+++ linux-2.5-pciapi/drivers/pci/proc.c	2004-12-16 08:40:20.000000000 -0800
@@ -44,12 +44,9 @@ proc_bus_pci_lseek(struct file *file, lo
 	return new;
 }
 
-static ssize_t
-proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t proc_bus_pci_config_read(struct pci_dev *dev, char __user *buf,
+					size_t nbytes, loff_t *ppos)
 {
-	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
 	unsigned int pos = *ppos;
 	unsigned int cnt, size;
 
@@ -126,12 +123,10 @@ proc_bus_pci_read(struct file *file, cha
 	return nbytes;
 }
 
-static ssize_t
-proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t proc_bus_pci_config_write(struct pci_dev *dev,
+					 const char __user *buf, size_t nbytes,
+					 loff_t *ppos)
 {
-	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
 	int pos = *ppos;
 	int size = dev->cfg_size;
 	int cnt;
@@ -196,11 +191,77 @@ proc_bus_pci_write(struct file *file, co
 	return nbytes;
 }
 
+#ifdef HAVE_PCI_LEGACY
+static int proc_bus_pci_legacy_read(struct pci_dev *dev, char __user *buf,
+				    size_t size, loff_t *ppos)
+{
+	int ret;
+	u32 v;
+
+	/* Only support 1, 2 or 4 byte accesses */
+	if (size != 1 && size != 2 && size != 4)
+		return -EINVAL;
+
+	if ((ret = pci_legacy_read(dev, *ppos, &v, size)))
+		return ret;
+
+	if (copy_to_user(buf, &v, size))
+		return -EFAULT;
+
+	return size;
+}
+
+static int proc_bus_pci_legacy_write(struct pci_dev *dev,
+				     const char __user *buf, size_t size,
+				     loff_t *ppos)
+{
+	u32 v = 0;
+
+	/* Only support 1, 2 or 4 byte accesses */
+	if (size != 1 && size != 2 && size != 4)
+		return -EINVAL;
+
+	if (copy_from_user(&v, buf, size))
+		return -EFAULT;
+
+	return pci_legacy_write(dev, *ppos, v, size);
+}
+#endif /* HAVE_PCI_LEGACY */
+
 struct pci_filp_private {
 	enum pci_mmap_state mmap_state;
 	int write_combine;
+	enum pci_rw_state rw_state;
 };
 
+static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
+				 size_t nbytes, loff_t *ppos)
+{
+	const struct inode *ino = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = PDE(ino);
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+
+	if (fpriv->rw_state == pci_rw_config)
+		return proc_bus_pci_config_read(dev, buf, nbytes, ppos);
+	else
+		return proc_bus_pci_legacy_read(dev, buf, nbytes, ppos);
+}
+
+static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
+				  size_t nbytes, loff_t *ppos)
+{
+	const struct inode *ino = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = PDE(ino);
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+
+	if (fpriv->rw_state == pci_rw_config)
+		return proc_bus_pci_config_write(dev, buf, nbytes, ppos);
+	else
+		return proc_bus_pci_legacy_write(dev, buf, nbytes, ppos);
+}
+
 static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	const struct proc_dir_entry *dp = PDE(inode);
@@ -224,6 +285,10 @@ static int proc_bus_pci_ioctl(struct ino
 		fpriv->mmap_state = pci_mmap_mem;
 		break;
 
+	case PCIIOC_MMAP_IS_LEGACY_MEM:
+		fpriv->mmap_state = pci_mmap_legacy_mem;
+		break;
+
 	case PCIIOC_WRITE_COMBINE:
 		if (arg)
 			fpriv->write_combine = 1;
@@ -233,6 +298,17 @@ static int proc_bus_pci_ioctl(struct ino
 
 #endif /* HAVE_PCI_MMAP */
 
+#ifdef HAVE_PCI_LEGACY
+	case PCIIOC_RW_LEGACY_IO:
+		fpriv->rw_state = pci_rw_legacy_io;
+		break;
+
+	case PCIIOC_RW_CONFIG:
+		fpriv->rw_state = pci_rw_config;
+		break;
+
+#endif /* HAVE_PCI_LEGACY */
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -271,6 +347,7 @@ static int proc_bus_pci_open(struct inod
 
 	fpriv->mmap_state = pci_mmap_io;
 	fpriv->write_combine = 0;
+	fpriv->rw_state = pci_rw_config;
 
 	file->private_data = fpriv;
 
@@ -403,7 +480,8 @@ int pci_proc_attach_device(struct pci_de
 		return -ENOMEM;
 	e->proc_fops = &proc_bus_pci_operations;
 	e->data = dev;
-	e->size = dev->cfg_size;
+	/* includes config space *and* legacy I/O port space */
+	e->size = 0xffff;
 
 	return 0;
 }
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/asm-ia64/machvec.h linux-2.5-pciapi/include/asm-ia64/machvec.h
--- linux-2.5-pciapi.new/include/asm-ia64/machvec.h	2004-12-16 08:38:11.000000000 -0800
+++ linux-2.5-pciapi/include/asm-ia64/machvec.h	2004-12-14 14:08:49.000000000 -0800
@@ -20,6 +20,7 @@ struct scatterlist;
 struct irq_desc;
 struct page;
 struct mm_struct;
+struct pci_dev;
 
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t (void);
@@ -31,6 +32,11 @@ typedef void ia64_mv_tlb_migrate_finish_
 typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
 typedef u8 ia64_mv_irq_to_vector (unsigned int);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8);
+typedef int ia64_mv_pci_get_legacy_mem_t (struct pci_dev *, unsigned long *);
+typedef int ia64_mv_pci_legacy_read_t (struct pci_dev *, u16 port, u32 *val,
+				       u8 size);
+typedef int ia64_mv_pci_legacy_write_t (struct pci_dev *, u16 port, u32 val,
+					u8 size);
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
@@ -125,6 +131,9 @@ extern void machvec_tlb_migrate_finish (
 #  define platform_irq_desc		ia64_mv.irq_desc
 #  define platform_irq_to_vector	ia64_mv.irq_to_vector
 #  define platform_local_vector_to_irq	ia64_mv.local_vector_to_irq
+#  define platform_pci_get_legacy_mem	ia64_mv.pci_get_legacy_mem
+#  define platform_pci_legacy_read	ia64_mv.pci_legacy_read
+#  define platform_pci_legacy_write	ia64_mv.pci_legacy_write
 #  define platform_inb		ia64_mv.inb
 #  define platform_inw		ia64_mv.inw
 #  define platform_inl		ia64_mv.inl
@@ -172,6 +181,9 @@ struct ia64_machine_vector {
 	ia64_mv_irq_desc *irq_desc;
 	ia64_mv_irq_to_vector *irq_to_vector;
 	ia64_mv_local_vector_to_irq *local_vector_to_irq;
+	ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
+	ia64_mv_pci_legacy_read_t *pci_legacy_read;
+	ia64_mv_pci_legacy_write_t *pci_legacy_write;
 	ia64_mv_inb_t *inb;
 	ia64_mv_inw_t *inw;
 	ia64_mv_inl_t *inl;
@@ -215,6 +227,9 @@ struct ia64_machine_vector {
 	platform_irq_desc,			\
 	platform_irq_to_vector,			\
 	platform_local_vector_to_irq,		\
+	platform_pci_get_legacy_mem,		\
+	platform_pci_legacy_read,		\
+	platform_pci_legacy_write,		\
 	platform_inb,				\
 	platform_inw,				\
 	platform_inl,				\
@@ -330,6 +345,15 @@ extern ia64_mv_dma_supported		swiotlb_dm
 #ifndef platform_local_vector_to_irq
 # define platform_local_vector_to_irq	__ia64_local_vector_to_irq
 #endif
+#ifndef platform_pci_get_legacy_mem
+# define platform_pci_get_legacy_mem	ia64_pci_get_legacy_mem
+#endif
+#ifndef platform_pci_legacy_read
+# define platform_pci_legacy_read	ia64_pci_legacy_read
+#endif
+#ifndef platform_pci_legacy_write
+# define platform_pci_legacy_write	ia64_pci_legacy_write
+#endif
 #ifndef platform_inb
 # define platform_inb		__ia64_inb
 #endif
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/asm-ia64/machvec_init.h linux-2.5-pciapi/include/asm-ia64/machvec_init.h
--- linux-2.5-pciapi.new/include/asm-ia64/machvec_init.h	2004-12-16 08:38:11.000000000 -0800
+++ linux-2.5-pciapi/include/asm-ia64/machvec_init.h	2004-12-14 14:08:49.000000000 -0800
@@ -5,6 +5,9 @@ extern ia64_mv_global_tlb_purge_t ia64_g
 extern ia64_mv_irq_desc __ia64_irq_desc;
 extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
 extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write;
 
 extern ia64_mv_inb_t __ia64_inb;
 extern ia64_mv_inw_t __ia64_inw;
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/asm-ia64/machvec_sn2.h linux-2.5-pciapi/include/asm-ia64/machvec_sn2.h
--- linux-2.5-pciapi.new/include/asm-ia64/machvec_sn2.h	2004-12-16 08:38:11.000000000 -0800
+++ linux-2.5-pciapi/include/asm-ia64/machvec_sn2.h	2004-12-14 14:08:49.000000000 -0800
@@ -43,6 +43,9 @@ extern ia64_mv_tlb_migrate_finish_t	sn_t
 extern ia64_mv_irq_desc sn_irq_desc;
 extern ia64_mv_irq_to_vector sn_irq_to_vector;
 extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write;
 extern ia64_mv_inb_t __sn_inb;
 extern ia64_mv_inw_t __sn_inw;
 extern ia64_mv_inl_t __sn_inl;
@@ -105,6 +108,9 @@ extern ia64_mv_dma_supported		sn_dma_sup
 #define platform_irq_desc		sn_irq_desc
 #define platform_irq_to_vector		sn_irq_to_vector
 #define platform_local_vector_to_irq	sn_local_vector_to_irq
+#define platform_pci_get_legacy_mem	sn_pci_get_legacy_mem
+#define platform_pci_legacy_read	sn_pci_legacy_read
+#define platform_pci_legacy_write	sn_pci_legacy_write
 #define platform_dma_init		machvec_noop
 #define platform_dma_alloc_coherent	sn_dma_alloc_coherent
 #define platform_dma_free_coherent	sn_dma_free_coherent
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/asm-ia64/pci.h linux-2.5-pciapi/include/asm-ia64/pci.h
--- linux-2.5-pciapi.new/include/asm-ia64/pci.h	2004-12-16 08:38:12.000000000 -0800
+++ linux-2.5-pciapi/include/asm-ia64/pci.h	2004-12-14 14:08:49.000000000 -0800
@@ -85,6 +85,10 @@ extern int pcibios_prep_mwi (struct pci_
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 				enum pci_mmap_state mmap_state, int write_combine);
+#define HAVE_PCI_LEGACY
+#define pci_get_legacy_mem platform_pci_get_legacy_mem
+#define pci_legacy_read platform_pci_legacy_read
+#define pci_legacy_write platform_pci_legacy_write
 
 struct pci_window {
 	struct resource resource;
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/asm-ia64/sn/sn_sal.h linux-2.5-pciapi/include/asm-ia64/sn/sn_sal.h
--- linux-2.5-pciapi.new/include/asm-ia64/sn/sn_sal.h	2004-12-16 08:38:12.000000000 -0800
+++ linux-2.5-pciapi/include/asm-ia64/sn/sn_sal.h	2004-12-14 14:08:49.000000000 -0800
@@ -474,6 +474,53 @@ ia64_sn_pod_mode(void)
 	return isrv.v0;
 }
 
+/**
+ * ia64_sn_probe_mem - read from memory safely
+ * @addr: address to probe
+ * @size: number bytes to read (1,2,4,8)
+ * @data_ptr: address to store value read by probe (-1 returned if probe fails)
+ *
+ * Call into the SAL to do a memory read.  If the read generates a machine
+ * check, this routine will recover gracefully and return -1 to the caller.
+ * @addr is usually a kernel virtual address in uncached space (i.e. the
+ * address starts with 0xc), but if called in physical mode, @addr should
+ * be a physical address.
+ *
+ * Return values:
+ *  0 - probe successful
+ *  1 - probe failed (generated MCA)
+ *  2 - Bad arg
+ * <0 - PAL error
+ */
+static inline u64
+ia64_sn_probe_mem(long addr, long size, void *data_ptr)
+{
+	struct ia64_sal_retval isrv;
+
+	SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0);
+
+	if (data_ptr) {
+		switch (size) {
+			case 1:
+				*((u8*)data_ptr) = (u8)isrv.v0;
+				break;
+			case 2:
+				*((u16*)data_ptr) = (u16)isrv.v0;
+				break;
+			case 4:
+				*((u32*)data_ptr) = (u32)isrv.v0;
+				break;
+			case 8:
+				*((u64*)data_ptr) = (u64)isrv.v0;
+				break;
+			default:
+				isrv.status = 2;
+		}
+	}
+
+	return isrv.status;
+}
+
 /*
  * Retrieve the system serial number as an ASCII string.
  */
diff -Napur -X /home/jbarnes/dontdiff linux-2.5-pciapi.new/include/linux/pci.h linux-2.5-pciapi/include/linux/pci.h
--- linux-2.5-pciapi.new/include/linux/pci.h	2004-12-16 08:38:15.000000000 -0800
+++ linux-2.5-pciapi/include/linux/pci.h	2004-12-16 08:40:21.000000000 -0800
@@ -455,6 +455,9 @@
 #define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
 #define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
 #define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+#define PCIIOC_RW_LEGACY_IO	(PCIIOC_BASE | 0x04)	/* Read/write access functions go to legacy space */
+#define PCIIOC_RW_CONFIG	(PCIIOC_BASE | 0x05)	/* Read/write access functions go to config space */
+#define PCIIOC_MMAP_IS_LEGACY_MEM (PCIIOC_BASE | 0x6)	/* Legacy memory */
 
 #ifdef __KERNEL__
 
@@ -468,7 +471,14 @@
 /* File state for mmap()s on /proc/bus/pci/X/Y */
 enum pci_mmap_state {
 	pci_mmap_io,
-	pci_mmap_mem
+	pci_mmap_mem,
+	pci_mmap_legacy_mem
+};
+
+/* Mode state for read/write routines on /proc/bus/pci/X/Y */
+enum pci_rw_state {
+	pci_rw_config, /* r/w config space */
+	pci_rw_legacy_io /* r/w legacy I/O port space */
 };
 
 /* This defines the direction arg to the DMA mapping routines. */

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:50 [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci Jesse Barnes
  2004-12-16 16:39 ` Randy.Dunlap
@ 2004-12-16 16:56 ` Christoph Hellwig
  2004-12-16 17:04   ` Jesse Barnes
  2004-12-16 17:37 ` Bjorn Helgaas
  2004-12-16 18:45 ` David Mosberger
  3 siblings, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2004-12-16 16:56 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, linux-ia64, linux-kernel, willy

On Thu, Dec 16, 2004 at 08:50:19AM -0800, Jesse Barnes wrote:
> This patch documents the /proc/bus/pci interface and adds some optional 
> architecture specific APIs for accessing legacy I/O port and memory space.  
> This is necessary on platforms where legacy I/O port space doesn't 'soft 
> fail' like it does on PCs, and is useful for systems that can route legacy 
> space to different PCI busses.

Please don't add more interfaces to procfs.  And ioctl() on procfs is even
more evil.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:56 ` Christoph Hellwig
@ 2004-12-16 17:04   ` Jesse Barnes
  0 siblings, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 17:04 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-pci, linux-ia64, linux-kernel, willy

On Thursday, December 16, 2004 8:56 am, Christoph Hellwig wrote:
> On Thu, Dec 16, 2004 at 08:50:19AM -0800, Jesse Barnes wrote:
> > This patch documents the /proc/bus/pci interface and adds some optional
> > architecture specific APIs for accessing legacy I/O port and memory
> > space. This is necessary on platforms where legacy I/O port space doesn't
> > 'soft fail' like it does on PCs, and is useful for systems that can route
> > legacy space to different PCI busses.
>
> Please don't add more interfaces to procfs.  And ioctl() on procfs is even
> more evil.

Oh come on, there's already an API there, and now it's documented even!  The 
additions are straightforward and there's no where else to put them...  /sys 
doesn't seem like a good place either, would you prefer a device driver?

I really don't see what the problem is though.  /proc/bus/pci is a commonly 
used API and I don't see it going away.  These extensions just make it a 
little more usable on platforms like sn2 and ppc.

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:39 ` Randy.Dunlap
@ 2004-12-16 17:07   ` Jesse Barnes
  2004-12-16 17:55   ` Doug Maxey
  1 sibling, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 17:07 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: linux-pci, linux-ia64, linux-kernel, willy

On Thursday, December 16, 2004 8:39 am, Randy.Dunlap wrote:
> meta-comment:
> Would you (and not just you :) include a diffstat summary so we
> can see which files are being changed?  something like this:
>
>
>   Documentation/filesystems/proc-pci.txt |  126
> +++++++++++++++++++++++++++++++++
>   arch/ia64/pci/pci.c                    |  105
> +++++++++++++++++++++++++++
>   arch/ia64/sn/pci/pci_dma.c             |   74 +++++++++++++++++++
>   drivers/pci/proc.c                     |  100 +++++++++++++++++++++++---
>   include/asm-ia64/machvec.h             |   24 ++++++
>   include/asm-ia64/machvec_init.h        |    3
>   include/asm-ia64/machvec_sn2.h         |    6 +
>   include/asm-ia64/pci.h                 |    4 +
>   include/asm-ia64/sn/sn_sal.h           |   47 ++++++++++++
>   include/linux/pci.h                    |   12 ++-
>   10 files changed, 488 insertions(+), 13 deletions(-)

Sure, I keep forgetting to do that for the larger patches.  Thanks for 
reminding me.

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:50 [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci Jesse Barnes
  2004-12-16 16:39 ` Randy.Dunlap
  2004-12-16 16:56 ` Christoph Hellwig
@ 2004-12-16 17:37 ` Bjorn Helgaas
  2004-12-16 17:42   ` Jesse Barnes
  2004-12-16 18:45 ` David Mosberger
  3 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2004-12-16 17:37 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, linux-ia64, linux-kernel, willy

On Thursday 16 December 2004 9:50 am, Jesse Barnes wrote:
> This patch documents the /proc/bus/pci interface and adds some optional 
> architecture specific APIs for accessing legacy I/O port and memory space.  
> This is necessary on platforms where legacy I/O port space doesn't 'soft 
> fail' like it does on PCs, and is useful for systems that can route legacy 
> space to different PCI busses.

But we didn't resolve anything with respect to multiple PCI domains,
did we?  As far as I can see, /proc/bus/pci currently doesn't support
multiple domains at all.  I don't like the idea of adding new stuff
that we already know is insufficient for machines in the very near
future.  True, it's just extending an existing interface, but it
seems like if we're going to the trouble of changing X, we might as
well address multiple domains at the same time.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 17:37 ` Bjorn Helgaas
@ 2004-12-16 17:42   ` Jesse Barnes
  0 siblings, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 17:42 UTC (permalink / raw)
  To: linux-pci; +Cc: Bjorn Helgaas, linux-ia64, linux-kernel, willy

On Thursday, December 16, 2004 9:37 am, Bjorn Helgaas wrote:
> On Thursday 16 December 2004 9:50 am, Jesse Barnes wrote:
> > This patch documents the /proc/bus/pci interface and adds some optional
> > architecture specific APIs for accessing legacy I/O port and memory
> > space. This is necessary on platforms where legacy I/O port space doesn't
> > 'soft fail' like it does on PCs, and is useful for systems that can route
> > legacy space to different PCI busses.
>
> But we didn't resolve anything with respect to multiple PCI domains,
> did we?  As far as I can see, /proc/bus/pci currently doesn't support
> multiple domains at all.  I don't like the idea of adding new stuff
> that we already know is insufficient for machines in the very near
> future.  True, it's just extending an existing interface, but it
> seems like if we're going to the trouble of changing X, we might as
> well address multiple domains at the same time.

The problem with adding domain support is that it'll break existing users, 
unless it's added on the side somehow.  One thought I had was to document 
that /proc/bus/pci/ contains only busses from domain 0.  Machines with more 
than 1 domain could create /proc/bus/pci/domain/DDDD directories with busses 
in the DDDD domain underneath.  That wouldn't break existing applications, 
and would let you get at domains other than 0 if you needed to.

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:39 ` Randy.Dunlap
  2004-12-16 17:07   ` Jesse Barnes
@ 2004-12-16 17:55   ` Doug Maxey
  1 sibling, 0 replies; 13+ messages in thread
From: Doug Maxey @ 2004-12-16 17:55 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Jesse Barnes, linux-pci, linux-ia64, linux-kernel, willy

[-- Attachment #1: Type: text/plain, Size: 1825 bytes --]


On Thu, 16 Dec 2004 08:39:20 PST, "Randy.Dunlap" wrote:
>Jesse Barnes wrote:
>> This patch documents the /proc/bus/pci interface and adds some optional 
>> architecture specific APIs for accessing legacy I/O port and memory space.  
>> This is necessary on platforms where legacy I/O port space doesn't 'soft 
>> fail' like it does on PCs, and is useful for systems that can route legacy 
>> space to different PCI busses.
>> 
>> I've incorporated all the feedback I've received so far, so I think it's ready 
>> to send on to Andrew for inclusion, if someone could give the proc-pci.txt 
>> documentation a last read (and/or comment on other stuff I may have missed).
>
>meta-comment:
>Would you (and not just you :) include a diffstat summary so we
>can see which files are being changed?  something like this:
>
>
>  Documentation/filesystems/proc-pci.txt |  126 
>+++++++++++++++++++++++++++++++++
>  arch/ia64/pci/pci.c                    |  105 
>+++++++++++++++++++++++++++
>  arch/ia64/sn/pci/pci_dma.c             |   74 +++++++++++++++++++
>  drivers/pci/proc.c                     |  100 +++++++++++++++++++++++---
>  include/asm-ia64/machvec.h             |   24 ++++++
>  include/asm-ia64/machvec_init.h        |    3
>  include/asm-ia64/machvec_sn2.h         |    6 +
>  include/asm-ia64/pci.h                 |    4 +
>  include/asm-ia64/sn/sn_sal.h           |   47 ++++++++++++
>  include/linux/pci.h                    |   12 ++-
>  10 files changed, 488 insertions(+), 13 deletions(-)
>
>-- 
>~Randy
>-
>To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>Please read the FAQ at  http://www.tux.org/lkml/
>

Here is a little perl diddy that accomplishes same:


[-- Attachment #2: ds --]
[-- Type: text/plain , Size: 3416 bytes --]

#!/usr/bin/env perl
# ds
# Created Fri Oct 22 2004 by dwm@austin.ibm.com
# $Id: ds,v 1.11 2004/11/05 23:24:06 dwm Exp $

require 5.6.1;
use Getopt::Long 2.33;
use Pod::Usage;
use Data::Dumper;
use Config;


### variables and subroutines ##
$opt_debug = 0;
$opt_help = 0;
$opt_man = 0;

$stat_flags = "";
$diff_flags = "-Nwupa";
@dirs = ();
@tops = ();

sub infer_orig ( $ ) {
    my $suf = "$_[0]\$";
    my $x = $ENV{PWD};
    my $basedir;
    ($basedir = $x) =~ s,.*/,,;
    if ($basedir =~ m{$suf}) {
        ($tops[0] = $basedir) =~ s{$suf}{};
	$tops[1] = $basedir;
	return 1;
    }
    return 0;
}

\f
#############  main  ####################
GetOptions (
            'debug'       => \$opt_debug,
            'diffflags=s' => \$diff_flags,
            'dirs=s'      => \@dirs,
            'help|?'      => \$opt_help,
            'man'         => \$opt_man,
            'statflags=s' => \$stat_flags,
            'tops=s'      => \@tops,
            'verbose+'    => \$verbose,
	   )
    or pod2usage(2);

pod2usage (1) if $opt_help;
pod2usage (-verbose => 2) if $opt_man;
( $prog = $0 ) =~  s{.*/}{}o;

## If no arguments were given, then allow STDIN to be used only
## if it's not connected to a terminal (otherwise print usage)
pod2usage ("$prog: No files given.")  if ((@ARGV == 0) && (-t STDIN));

# setbuf on STDERR.
$ofh = select (STDERR); $| = 1; select ($ofh);

@diffout = ();
$kill_errs = ($verbose) ? "" : "2>/dev/null";

#
# if tops is not set, infer the older directory.  Long Term - find out if cvs file.
#
if (not scalar @tops) {
    my @os = ( "\.edit" );

    while ($od = shift @os) {
	last if (infer_orig $od);
    }
}

if (not scalar @tops) {
    pod2usage ("$prog: could not infer, need to define tops.");
}

if (not -d $tops[0]) {
    if (-d "../$tops[0]") {
	chdir '..';
	print STDERR qx{pwd} if $verbose;
    }
    else {
	die "could not find $tops[0]\n";
    }
}

while ($path = shift @ARGV) {
    my $recurse = (-d "$tops[0]/$path") ? 'r' : '';
    $cmd = "diff $diff_flags${recurse} $tops[0]/$path $tops[1]/$path $kill_errs";
    print "tops={@tops}\n$cmd\n" if $opt_debug;
    open DIFFIN, "$cmd |" or die "open {$cmd}\n";
    while (<DIFFIN>) {
	next if (m{^Common});
	push @diffout, $_;
    }
}

open DSI, "|diffstat $stat_flags" or die "open stat pipe\n";
print DSI @diffout;
print while (<DSI>);
close DSI;
print "\n", @diffout;

__END__
\f
=head1 NAME

B<ds> - diffstat + diff from one command

=head1 SYNOPSIS

B<ds> [options] ...

=head1 OPTIONS

=over 4

=item B<--debug>

run without action, printing debug messages.

=item B<--diffflags>

flags to pass to diff.  default -Nwupa.

=item B<--help>

print the synopsis only.  see B<--man>.

=item B<--man>

print the complete manpage.

=item B<--statflags>

flags to pass to diffstat.  default is {$stat_flags}.

=item B<--tops>

Top level directories to diff with the appended paths.  If not specified,
infer from current directory if possible.

=item B<--verbose>

whistle while we work.  multiple calls increase the verbosity level.

=back

=head1 DESCRIPTION

Runs diff over the list of files, collecting the output.  When complete, outputs
the stats followed by the diffs to stdout.

=head1 EXAMPLES

examples

=head1 NOTE

note

=head1 BUGS

Undoubtedly.  Contact the author with the particulars if this is stopping your progress.

=head1 FILES

B<ds> - perl script

=head1 AUTHOR

Doug Maxey <dwm@austin.ibm.com>

=cut

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 16:50 [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci Jesse Barnes
                   ` (2 preceding siblings ...)
  2004-12-16 17:37 ` Bjorn Helgaas
@ 2004-12-16 18:45 ` David Mosberger
  2004-12-16 18:56   ` Jesse Barnes
  3 siblings, 1 reply; 13+ messages in thread
From: David Mosberger @ 2004-12-16 18:45 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, linux-ia64, linux-kernel, willy

>>>>> On Thu, 16 Dec 2004 08:50:19 -0800, Jesse Barnes <jbarnes@engr.sgi.com> said:

  Jesse> +int ia64_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val, u8 size)
  Jesse> +{
  Jesse> +	int ret = 0;
  Jesse>         :
  Jesse> +	case 1:
  Jesse> +		addr = (unsigned long *)paddr;
  Jesse> +		*val = (u8)(*(volatile u8 *)(addr));
  Jesse> +		break;
  Jesse> +	case 2:
  Jesse> +		addr = (unsigned long *)paddr;
  Jesse> +		*val = (u16)(*(volatile u16 *)(addr));
  Jesse> +		break;
  Jesse>          :
  Jesse> +}

  Jesse> +int ia64_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val, u8 size)
  Jesse> +{
  Jesse> +	switch (size) {
  Jesse> +	case 1:
  Jesse> +		addr = (unsigned long *)paddr;
  Jesse> +		*(volatile u8 *)(addr) = (u8)(val);
  Jesse> +		break;
  Jesse> +	case 2:
  Jesse> +		addr = (unsigned long *)paddr;
  Jesse> +		*(volatile u16 *)(addr) = (u16)(val);
  Jesse> +		break;
  Jesse>           :
  Jesse> +	}

No offense, but what's up with this castamania?

	--david

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 18:45 ` David Mosberger
@ 2004-12-16 18:56   ` Jesse Barnes
  2004-12-16 19:07     ` Jesse Barnes
  0 siblings, 1 reply; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 18:56 UTC (permalink / raw)
  To: davidm; +Cc: linux-pci, linux-ia64, linux-kernel, willy

On Thursday, December 16, 2004 10:45 am, David Mosberger wrote:
> >>>>> On Thu, 16 Dec 2004 08:50:19 -0800, Jesse Barnes
> >>>>> <jbarnes@engr.sgi.com> said:
>
>   Jesse> +int ia64_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val,
> u8 size) Jesse> +{
>   Jesse> + int ret = 0;
>   Jesse>         :
>   Jesse> + case 1:
>   Jesse> +  addr = (unsigned long *)paddr;
>   Jesse> +  *val = (u8)(*(volatile u8 *)(addr));
>   Jesse> +  break;
>   Jesse> + case 2:
>   Jesse> +  addr = (unsigned long *)paddr;
>   Jesse> +  *val = (u16)(*(volatile u16 *)(addr));
>   Jesse> +  break;
>   Jesse>          :
>   Jesse> +}
>
>   Jesse> +int ia64_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val,
> u8 size) Jesse> +{
>   Jesse> + switch (size) {
>   Jesse> + case 1:
>   Jesse> +  addr = (unsigned long *)paddr;
>   Jesse> +  *(volatile u8 *)(addr) = (u8)(val);
>   Jesse> +  break;
>   Jesse> + case 2:
>   Jesse> +  addr = (unsigned long *)paddr;
>   Jesse> +  *(volatile u16 *)(addr) = (u16)(val);
>   Jesse> +  break;
>   Jesse>           :
>   Jesse> + }
>
> No offense, but what's up with this castamania?

Leftovers from other code.  I don't actually use this stuff on sn2, someone 
with a DIG test box will have to verify it (willy pointed out that I should 
probably just be using the appropriate inX our outX routine here instead, 
which makes sense).

Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 18:56   ` Jesse Barnes
@ 2004-12-16 19:07     ` Jesse Barnes
  2004-12-16 19:11       ` David Mosberger
  0 siblings, 1 reply; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 19:07 UTC (permalink / raw)
  To: linux-pci; +Cc: davidm, linux-ia64, linux-kernel, willy

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

On Thursday, December 16, 2004 10:56 am, Jesse Barnes wrote:
> > No offense, but what's up with this castamania?

Maybe this is a little better?  I talked with Bjorn and willy on irc about 
this and there are some other approaches we could take.  I still think domain 
support is a separate issue from the additions in this patch, but there are 
definitely other ways to export this stuff to userspace.  One would be adding 
sys_ioport system call to ia64 that would allow reads and writes to arbitrary 
I/O ports (not just legacy ones) coupled with exporting the legacy memory 
base address in /proc/iomem somewhere and letting users map it in /dev/mem.  
Doing things that way wouldn't help platforms like ppc though, and the API 
would be a bit more confusing (more places to poke to find the info you 
need).

Jesse

[-- Attachment #2: legacy-ioctl-mem-api-7.patch --]
[-- Type: text/plain, Size: 20677 bytes --]

===== arch/ia64/pci/pci.c 1.59 vs edited =====
--- 1.59/arch/ia64/pci/pci.c	2004-11-05 11:55:25 -08:00
+++ edited/arch/ia64/pci/pci.c	2004-12-16 11:02:53 -08:00
@@ -514,11 +514,19 @@
 		 */
 		return -EINVAL;
 
+	if (mmap_state == pci_mmap_legacy_mem) {
+		unsigned long addr;
+		int ret;
+		if ((ret = pci_get_legacy_mem(dev, &addr)))
+			return ret;
+		vma->vm_pgoff += addr >> PAGE_SHIFT;
+	}
+
 	/*
 	 * Leave vm_pgoff as-is, the PCI space address is the physical
 	 * address on this platform.
 	 */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+	vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
 
 	if (write_combine)
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -530,6 +538,91 @@
 		return -EAGAIN;
 
 	return 0;
+}
+
+/**
+ * ia64_pci_get_legacy_mem - generic legacy mem routine
+ * @dev: device pointer
+ * @addr: caller allocated variable for the base address
+ *
+ * Find the base of legacy memory for @dev.  This is typically the first
+ * megabyte of bus address space for @dev or is simply 0 on platforms whose
+ * chipsets support legacy I/O and memory routing.  Returns 0 on success
+ * or a standard error code on failure.
+ *
+ * This is the ia64 generic version of this routine.  Other platforms
+ * are free to override it with a machine vector.
+ */
+int ia64_pci_get_legacy_mem(struct pci_dev *dev, unsigned long *addr)
+{
+	*addr = 0;
+	return 0;
+}
+
+/**
+ * ia64_pci_legacy_read - read from legacy I/O space
+ * @dev: device to read
+ * @port: legacy port value
+ * @val: caller allocated storage for returned value
+ * @size: number of bytes to read
+ *
+ * Simply reads @size bytes from @port and puts the result in @val.
+ *
+ * Again, this (and the write routine) are generic versions that can be
+ * overridden by the platform.  This is necessary on platforms that don't
+ * support legacy I/O routing or that hard fail on legacy I/O timeouts.
+ */
+int ia64_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val, u8 size)
+{
+	int ret = 0;
+
+	switch (size) {
+	case 1:
+		*val = inb(port);
+		break;
+	case 2:
+		*val = inw(port);
+		break;
+	case 4:
+		*val = inl(port);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * ia64_pci_legacy_write - perform a legacy I/O write
+ * @dev: device pointer
+ * @port: port to write
+ * @val: value to write
+ * @size: number of bytes to write from @val
+ *
+ * Simply writes @size bytes of @val to @port.
+ */
+int ia64_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val, u8 size)
+{
+	int ret = 0;
+
+	switch (size) {
+	case 1:
+		outb((unsigned char)val, port);
+		break;
+	case 2:
+		outw((unsigned short)val, port);
+		break;
+	case 4:
+		outl((unsigned int)val, port);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
 }
 
 /**
===== arch/ia64/sn/pci/pci_dma.c 1.2 vs edited =====
--- 1.2/arch/ia64/sn/pci/pci_dma.c	2004-10-20 12:00:10 -07:00
+++ edited/arch/ia64/sn/pci/pci_dma.c	2004-12-16 10:56:58 -08:00
@@ -475,3 +475,77 @@
 EXPORT_SYMBOL(sn_pci_free_consistent);
 EXPORT_SYMBOL(sn_pci_dma_supported);
 EXPORT_SYMBOL(sn_dma_mapping_error);
+
+int sn_pci_get_legacy_mem(struct pci_dev *dev, unsigned long *addr)
+{
+	if (!SN_PCIDEV_BUSSOFT(dev))
+		return -ENODEV;
+
+	*addr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_mem | __IA64_UNCACHED_OFFSET;
+
+	return 0;
+}
+
+int sn_pci_legacy_read(struct pci_dev *dev, u16 port, u32 *val, u8 size)
+{
+	int ret = 0;
+	unsigned long addr;
+
+	if (!SN_PCIDEV_BUSSOFT(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	addr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+	addr += port;
+
+	ret = ia64_sn_probe_mem(addr, (long)size, (void *)val);
+
+	/* Read timed out, return -1 to emulate soft fail */
+	if (ret == 1)
+		*val = -1;
+
+	/* Invalid argument */
+	if (ret == 2)
+		ret = -EINVAL;
+
+ out:
+	return ret;
+}
+
+int sn_pci_legacy_write(struct pci_dev *dev, u16 port, u32 val, u8 size)
+{
+	int ret = 0;
+	unsigned long paddr;
+	unsigned long *addr;
+
+	if (!SN_PCIDEV_BUSSOFT(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Put the phys addr in uncached space */
+	paddr = SN_PCIDEV_BUSSOFT(dev)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+	paddr += port;
+	addr = (unsigned long *)paddr;
+
+	switch (size) {
+	case 1:
+		*(volatile u8 *)(addr) = (u8)(val);
+		ret = 1;
+		break;
+	case 2:
+		*(volatile u16 *)(addr) = (u16)(val);
+		ret = 2;
+		break;
+	case 4:
+		*(volatile u32 *)(addr) = (u32)(val);
+		ret = 4;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+ out:
+	return ret;
+}
===== drivers/pci/proc.c 1.41 vs edited =====
--- 1.41/drivers/pci/proc.c	2004-10-06 09:44:51 -07:00
+++ edited/drivers/pci/proc.c	2004-12-16 10:56:58 -08:00
@@ -44,12 +44,9 @@
 	return new;
 }
 
-static ssize_t
-proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t proc_bus_pci_config_read(struct pci_dev *dev, char __user *buf,
+					size_t nbytes, loff_t *ppos)
 {
-	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
 	unsigned int pos = *ppos;
 	unsigned int cnt, size;
 
@@ -126,12 +123,10 @@
 	return nbytes;
 }
 
-static ssize_t
-proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t proc_bus_pci_config_write(struct pci_dev *dev,
+					 const char __user *buf, size_t nbytes,
+					 loff_t *ppos)
 {
-	const struct inode *ino = file->f_dentry->d_inode;
-	const struct proc_dir_entry *dp = PDE(ino);
-	struct pci_dev *dev = dp->data;
 	int pos = *ppos;
 	int size = dev->cfg_size;
 	int cnt;
@@ -196,11 +191,77 @@
 	return nbytes;
 }
 
+#ifdef HAVE_PCI_LEGACY
+static int proc_bus_pci_legacy_read(struct pci_dev *dev, char __user *buf,
+				    size_t size, loff_t *ppos)
+{
+	int ret;
+	u32 v;
+
+	/* Only support 1, 2 or 4 byte accesses */
+	if (size != 1 && size != 2 && size != 4)
+		return -EINVAL;
+
+	if ((ret = pci_legacy_read(dev, *ppos, &v, size)))
+		return ret;
+
+	if (copy_to_user(buf, &v, size))
+		return -EFAULT;
+
+	return size;
+}
+
+static int proc_bus_pci_legacy_write(struct pci_dev *dev,
+				     const char __user *buf, size_t size,
+				     loff_t *ppos)
+{
+	u32 v = 0;
+
+	/* Only support 1, 2 or 4 byte accesses */
+	if (size != 1 && size != 2 && size != 4)
+		return -EINVAL;
+
+	if (copy_from_user(&v, buf, size))
+		return -EFAULT;
+
+	return pci_legacy_write(dev, *ppos, v, size);
+}
+#endif /* HAVE_PCI_LEGACY */
+
 struct pci_filp_private {
 	enum pci_mmap_state mmap_state;
 	int write_combine;
+	enum pci_rw_state rw_state;
 };
 
+static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
+				 size_t nbytes, loff_t *ppos)
+{
+	const struct inode *ino = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = PDE(ino);
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+
+	if (fpriv->rw_state == pci_rw_config)
+		return proc_bus_pci_config_read(dev, buf, nbytes, ppos);
+	else
+		return proc_bus_pci_legacy_read(dev, buf, nbytes, ppos);
+}
+
+static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
+				  size_t nbytes, loff_t *ppos)
+{
+	const struct inode *ino = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = PDE(ino);
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+
+	if (fpriv->rw_state == pci_rw_config)
+		return proc_bus_pci_config_write(dev, buf, nbytes, ppos);
+	else
+		return proc_bus_pci_legacy_write(dev, buf, nbytes, ppos);
+}
+
 static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	const struct proc_dir_entry *dp = PDE(inode);
@@ -224,6 +285,10 @@
 		fpriv->mmap_state = pci_mmap_mem;
 		break;
 
+	case PCIIOC_MMAP_IS_LEGACY_MEM:
+		fpriv->mmap_state = pci_mmap_legacy_mem;
+		break;
+
 	case PCIIOC_WRITE_COMBINE:
 		if (arg)
 			fpriv->write_combine = 1;
@@ -233,6 +298,17 @@
 
 #endif /* HAVE_PCI_MMAP */
 
+#ifdef HAVE_PCI_LEGACY
+	case PCIIOC_RW_LEGACY_IO:
+		fpriv->rw_state = pci_rw_legacy_io;
+		break;
+
+	case PCIIOC_RW_CONFIG:
+		fpriv->rw_state = pci_rw_config;
+		break;
+
+#endif /* HAVE_PCI_LEGACY */
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -271,6 +347,7 @@
 
 	fpriv->mmap_state = pci_mmap_io;
 	fpriv->write_combine = 0;
+	fpriv->rw_state = pci_rw_config;
 
 	file->private_data = fpriv;
 
@@ -403,7 +480,8 @@
 		return -ENOMEM;
 	e->proc_fops = &proc_bus_pci_operations;
 	e->data = dev;
-	e->size = dev->cfg_size;
+	/* includes config space *and* legacy I/O port space */
+	e->size = 0xffff;
 
 	return 0;
 }
===== include/asm-ia64/machvec.h 1.29 vs edited =====
--- 1.29/include/asm-ia64/machvec.h	2004-10-25 13:06:49 -07:00
+++ edited/include/asm-ia64/machvec.h	2004-12-16 10:56:59 -08:00
@@ -20,6 +20,7 @@
 struct irq_desc;
 struct page;
 struct mm_struct;
+struct pci_dev;
 
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t (void);
@@ -31,6 +32,11 @@
 typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
 typedef u8 ia64_mv_irq_to_vector (unsigned int);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8);
+typedef int ia64_mv_pci_get_legacy_mem_t (struct pci_dev *, unsigned long *);
+typedef int ia64_mv_pci_legacy_read_t (struct pci_dev *, u16 port, u32 *val,
+				       u8 size);
+typedef int ia64_mv_pci_legacy_write_t (struct pci_dev *, u16 port, u32 val,
+					u8 size);
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
@@ -125,6 +131,9 @@
 #  define platform_irq_desc		ia64_mv.irq_desc
 #  define platform_irq_to_vector	ia64_mv.irq_to_vector
 #  define platform_local_vector_to_irq	ia64_mv.local_vector_to_irq
+#  define platform_pci_get_legacy_mem	ia64_mv.pci_get_legacy_mem
+#  define platform_pci_legacy_read	ia64_mv.pci_legacy_read
+#  define platform_pci_legacy_write	ia64_mv.pci_legacy_write
 #  define platform_inb		ia64_mv.inb
 #  define platform_inw		ia64_mv.inw
 #  define platform_inl		ia64_mv.inl
@@ -172,6 +181,9 @@
 	ia64_mv_irq_desc *irq_desc;
 	ia64_mv_irq_to_vector *irq_to_vector;
 	ia64_mv_local_vector_to_irq *local_vector_to_irq;
+	ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
+	ia64_mv_pci_legacy_read_t *pci_legacy_read;
+	ia64_mv_pci_legacy_write_t *pci_legacy_write;
 	ia64_mv_inb_t *inb;
 	ia64_mv_inw_t *inw;
 	ia64_mv_inl_t *inl;
@@ -215,6 +227,9 @@
 	platform_irq_desc,			\
 	platform_irq_to_vector,			\
 	platform_local_vector_to_irq,		\
+	platform_pci_get_legacy_mem,		\
+	platform_pci_legacy_read,		\
+	platform_pci_legacy_write,		\
 	platform_inb,				\
 	platform_inw,				\
 	platform_inl,				\
@@ -329,6 +344,15 @@
 #endif
 #ifndef platform_local_vector_to_irq
 # define platform_local_vector_to_irq	__ia64_local_vector_to_irq
+#endif
+#ifndef platform_pci_get_legacy_mem
+# define platform_pci_get_legacy_mem	ia64_pci_get_legacy_mem
+#endif
+#ifndef platform_pci_legacy_read
+# define platform_pci_legacy_read	ia64_pci_legacy_read
+#endif
+#ifndef platform_pci_legacy_write
+# define platform_pci_legacy_write	ia64_pci_legacy_write
 #endif
 #ifndef platform_inb
 # define platform_inb		__ia64_inb
===== include/asm-ia64/machvec_init.h 1.8 vs edited =====
--- 1.8/include/asm-ia64/machvec_init.h	2004-10-25 13:06:49 -07:00
+++ edited/include/asm-ia64/machvec_init.h	2004-12-16 10:56:59 -08:00
@@ -5,6 +5,9 @@
 extern ia64_mv_irq_desc __ia64_irq_desc;
 extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
 extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write;
 
 extern ia64_mv_inb_t __ia64_inb;
 extern ia64_mv_inw_t __ia64_inw;
===== include/asm-ia64/machvec_sn2.h 1.16 vs edited =====
--- 1.16/include/asm-ia64/machvec_sn2.h	2004-10-25 13:06:49 -07:00
+++ edited/include/asm-ia64/machvec_sn2.h	2004-12-16 10:56:59 -08:00
@@ -43,6 +43,9 @@
 extern ia64_mv_irq_desc sn_irq_desc;
 extern ia64_mv_irq_to_vector sn_irq_to_vector;
 extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write;
 extern ia64_mv_inb_t __sn_inb;
 extern ia64_mv_inw_t __sn_inw;
 extern ia64_mv_inl_t __sn_inl;
@@ -105,6 +108,9 @@
 #define platform_irq_desc		sn_irq_desc
 #define platform_irq_to_vector		sn_irq_to_vector
 #define platform_local_vector_to_irq	sn_local_vector_to_irq
+#define platform_pci_get_legacy_mem	sn_pci_get_legacy_mem
+#define platform_pci_legacy_read	sn_pci_legacy_read
+#define platform_pci_legacy_write	sn_pci_legacy_write
 #define platform_dma_init		machvec_noop
 #define platform_dma_alloc_coherent	sn_dma_alloc_coherent
 #define platform_dma_free_coherent	sn_dma_free_coherent
===== include/asm-ia64/pci.h 1.27 vs edited =====
--- 1.27/include/asm-ia64/pci.h	2004-11-03 13:36:55 -08:00
+++ edited/include/asm-ia64/pci.h	2004-12-16 10:56:59 -08:00
@@ -85,6 +85,10 @@
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 				enum pci_mmap_state mmap_state, int write_combine);
+#define HAVE_PCI_LEGACY
+#define pci_get_legacy_mem platform_pci_get_legacy_mem
+#define pci_legacy_read platform_pci_legacy_read
+#define pci_legacy_write platform_pci_legacy_write
 
 struct pci_window {
 	struct resource resource;
===== include/asm-ia64/sn/sn_sal.h 1.17 vs edited =====
--- 1.17/include/asm-ia64/sn/sn_sal.h	2004-11-03 13:41:17 -08:00
+++ edited/include/asm-ia64/sn/sn_sal.h	2004-12-16 10:56:59 -08:00
@@ -474,6 +474,53 @@
 	return isrv.v0;
 }
 
+/**
+ * ia64_sn_probe_mem - read from memory safely
+ * @addr: address to probe
+ * @size: number bytes to read (1,2,4,8)
+ * @data_ptr: address to store value read by probe (-1 returned if probe fails)
+ *
+ * Call into the SAL to do a memory read.  If the read generates a machine
+ * check, this routine will recover gracefully and return -1 to the caller.
+ * @addr is usually a kernel virtual address in uncached space (i.e. the
+ * address starts with 0xc), but if called in physical mode, @addr should
+ * be a physical address.
+ *
+ * Return values:
+ *  0 - probe successful
+ *  1 - probe failed (generated MCA)
+ *  2 - Bad arg
+ * <0 - PAL error
+ */
+static inline u64
+ia64_sn_probe_mem(long addr, long size, void *data_ptr)
+{
+	struct ia64_sal_retval isrv;
+
+	SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0);
+
+	if (data_ptr) {
+		switch (size) {
+			case 1:
+				*((u8*)data_ptr) = (u8)isrv.v0;
+				break;
+			case 2:
+				*((u16*)data_ptr) = (u16)isrv.v0;
+				break;
+			case 4:
+				*((u32*)data_ptr) = (u32)isrv.v0;
+				break;
+			case 8:
+				*((u64*)data_ptr) = (u64)isrv.v0;
+				break;
+			default:
+				isrv.status = 2;
+		}
+	}
+
+	return isrv.status;
+}
+
 /*
  * Retrieve the system serial number as an ASCII string.
  */
===== include/linux/pci.h 1.142 vs edited =====
--- 1.142/include/linux/pci.h	2004-10-31 14:10:04 -08:00
+++ edited/include/linux/pci.h	2004-12-16 10:57:00 -08:00
@@ -455,6 +455,9 @@
 #define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
 #define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
 #define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+#define PCIIOC_RW_LEGACY_IO	(PCIIOC_BASE | 0x04)	/* Read/write access functions go to legacy space */
+#define PCIIOC_RW_CONFIG	(PCIIOC_BASE | 0x05)	/* Read/write access functions go to config space */
+#define PCIIOC_MMAP_IS_LEGACY_MEM (PCIIOC_BASE | 0x6)	/* Legacy memory */
 
 #ifdef __KERNEL__
 
@@ -468,7 +471,14 @@
 /* File state for mmap()s on /proc/bus/pci/X/Y */
 enum pci_mmap_state {
 	pci_mmap_io,
-	pci_mmap_mem
+	pci_mmap_mem,
+	pci_mmap_legacy_mem
+};
+
+/* Mode state for read/write routines on /proc/bus/pci/X/Y */
+enum pci_rw_state {
+	pci_rw_config, /* r/w config space */
+	pci_rw_legacy_io /* r/w legacy I/O port space */
 };
 
 /* This defines the direction arg to the DMA mapping routines. */
--- /dev/null	1969-12-31 16:00:00.000000000 -0800
+++ Documentation/filesystems/proc-pci.txt	2004-12-16 11:03:47.000000000 -0800
@@ -0,0 +1,127 @@
+Directory layout
+
+/proc/bus/pci contains a list of PCI devices available on the system
+and can be used for driving PCI devices from userspace, getting a list
+of PCI devices, and hotplug support.  Example:
+
+  $ tree /proc/bus/pci
+  /proc/bus/pci/
+  |-- 01		directory for devices on bus 1 
+  |   |-- 01.0		single fn device in slot 1
+  |   |-- 03.0		single fn device in slot 3
+  |   `-- 04.0		single fn device in slot 4
+  |-- 02
+  |   |-- 01.0		single fn device in slot 1
+  |   |-- 02.0		<
+  |   |-- 02.1		< three function device on bus 2
+  |   `-- 02.2		< 
+  |-- 17
+  |   `-- 00.0		busses 17 and 1b have only one device each in
+  |			slot 0
+  |-- 1b
+  |   `-- 00.0
+  `-- devices		see below
+
+  4 directories, 10 files
+
+The devices file contains an entry for each PCI device in the system
+with information about the host addresses corresponding to the device
+BARs and which driver is bound to a device (if present).  This
+information can be used as an offset argument to mmap specific device
+files in the tree above.  Each field in the devices file is seperated
+by tabs with each device on a line by itself.  The fields are
+
+bus id
+?
+?
+host resource 0
+host resource 1
+host resource 2
+host resource 3
+host resource 4
+host resource 5
+host resource 6
+host resource 7
+BAR value 0
+BAR value 1
+BAR value 2
+BAR value 3
+BAR value 4
+BAR value 5
+BAR value 6
+driver name (if present)
+
+For example:
+
+0108	10a9100a	3e	c00000080f200000	0	0	0	0	0	0	100000	0	0	0	0	0	0	SGI-IOC4_IDE
+
+Available interfaces
+
+Each file corresponding to a device in /proc/bus/pci has open, read,
+write, lseek, ioctl, and mmap methods available.
+
+open
+  simply opens the device and returns a handle as expected
+
+read
+  reads from either PCI config space or legacy I/O space, using the
+  current file postion, depending on the current I/O mode setting.
+
+write
+  writes to either PCI config space or legacy I/O space, using the
+  current file postion, depending on the current I/O mode setting.
+
+  Note that reads and writes to legacy I/O space must be 1, 2 or 4
+  bytes in size with the appropriate buffer pointer.  Reads and writes
+  to config space can be arbitrarily sized.  Legacy I/O port space
+  reads and writes must also be to a file position <64k--the kernel will
+  route them to the target device.
+
+lseek
+  Can be used to set the current file position.  Note that the file
+  size is limited to 64k as that's how big legacy I/O space is.
+
+ioctl
+  ioctl is used to set the mode of a subsequent read, write or mmap
+  call.  Available ioctls (in linux/pci.h) include
+    PCIIOC_CONTROLLER - return PCI domain number
+    PCIIOC_MMAP_IS_IO - next mmap maps to I/O space
+    PCIIOC_MMAP_IS_MEM - next mmap maps to memory space
+    PCIIOC_MMAP_IS_LEGACY_MEM - next mmap maps to legacy memory space
+    PCIIOC_WRITE_COMBINE - try to use write gathering for the new
+                           region if the ioctl argument is true,
+                           otherwise disable write gathering
+    PCIIOC_RW_LEGACY_IO - read/writes will go to legacy I/O space
+    PCIIOC_RW_CONFIG - read/writes will go to config space, this is the
+                       default for newly opened files
+  Note that not all architectures support the *_MMAP_* or *_RW_* ioctl
+  commands.  If they're not supported, ioctl will return -EINVAL.
+
+mmap
+  The final argument of mmap(2) must be a host address obtained from
+  /proc/bus/pci/devices or an address between 0 and 1M for legacy
+  memory mappings.  Only supported on some architectures.
+
+Examples
+
+	/* Read from the 3rd BAR of device in slot 1 of bus 1 */
+	int fd = open("/proc/bus/pci/01/01.0", O_RDONLY);
+	ioctl(fd, PCIIOC_RW_CONFIG); /* make sure we're using config space */
+	lseek(fd, 0x20, SEEK_SET);
+	read(fd, buf, 8);
+	close(fd);
+
+	/*
+	 * Do a legacy read of 1 byte (inb) from port 0x3cc from 1:1.0.
+	 * Note that this will just generate a bus cycle on bus 1 for port
+	 * 0x3cc, which the device in question may or may not respond to.
+	 * If there is no response, -1 will be returned.  Also note that
+	 * it may not be possible to generate legacy I/O port requests on
+	 * the bus or device specified, in that case the write will fail
+	 * with an appropriate error code.
+	 */
+	int fd = open("/proc/bus/pci/01/01.0", O_RDONLY);
+	ioctl(fd, PCIIOC_RW_LEGACY_IO); /* enable legacy I/O */
+	lseek(fd, 0x3cc, SEEK_SET);
+	read(fd, &val, 1);
+	close(fd);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 19:07     ` Jesse Barnes
@ 2004-12-16 19:11       ` David Mosberger
  2004-12-16 19:13         ` Jesse Barnes
  0 siblings, 1 reply; 13+ messages in thread
From: David Mosberger @ 2004-12-16 19:11 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, davidm, linux-ia64, linux-kernel, willy

>>>>> On Thu, 16 Dec 2004 11:07:56 -0800, Jesse Barnes <jbarnes@engr.sgi.com> said:

  Jesse> On Thursday, December 16, 2004 10:56 am, Jesse Barnes wrote:

  Jesse> Maybe this is a little better?

The ia64_pci_legacy_{read,write}() functions definitely look much
better, except I don't think you need any casts in the outX() calls.

	--david

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci
  2004-12-16 19:11       ` David Mosberger
@ 2004-12-16 19:13         ` Jesse Barnes
  0 siblings, 0 replies; 13+ messages in thread
From: Jesse Barnes @ 2004-12-16 19:13 UTC (permalink / raw)
  To: linux-pci, davidm; +Cc: linux-ia64, linux-kernel, willy

On Thursday, December 16, 2004 11:11 am, David Mosberger wrote:
> >>>>> On Thu, 16 Dec 2004 11:07:56 -0800, Jesse Barnes
> >>>>> <jbarnes@engr.sgi.com> said:
>
>   Jesse> On Thursday, December 16, 2004 10:56 am, Jesse Barnes wrote:
>
>   Jesse> Maybe this is a little better?
>
> The ia64_pci_legacy_{read,write}() functions definitely look much
> better, except I don't think you need any casts in the outX() calls.

You're right, I've removed them.

Thanks,
Jesse

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2004-12-16 19:18 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-16 16:50 [PATCH] add legacy I/O port & memory APIs to /proc/bus/pci Jesse Barnes
2004-12-16 16:39 ` Randy.Dunlap
2004-12-16 17:07   ` Jesse Barnes
2004-12-16 17:55   ` Doug Maxey
2004-12-16 16:56 ` Christoph Hellwig
2004-12-16 17:04   ` Jesse Barnes
2004-12-16 17:37 ` Bjorn Helgaas
2004-12-16 17:42   ` Jesse Barnes
2004-12-16 18:45 ` David Mosberger
2004-12-16 18:56   ` Jesse Barnes
2004-12-16 19:07     ` Jesse Barnes
2004-12-16 19:11       ` David Mosberger
2004-12-16 19:13         ` Jesse Barnes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox