patch-2.4.6 linux/arch/sparc64/kernel/pci.c
Next file: linux/arch/sparc64/kernel/pci_common.c
Previous file: linux/arch/sparc64/kernel/irq.c
Back to the patch index
Back to the overall index
- Lines: 186
- Date:
Wed Jun 20 21:00:55 2001
- Orig file:
v2.4.5/linux/arch/sparc64/kernel/pci.c
- Orig date:
Wed May 16 10:31:27 2001
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.29 2001/05/15 08:54:30 davem Exp $
+/* $Id: pci.c,v 1.35 2001/06/13 06:34:30 davem Exp $
* pci.c: UltraSparc PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -177,6 +177,10 @@
}
}
+extern void rs_init(void);
+extern void clock_probe(void);
+extern void power_init(void);
+
void __init pcibios_init(void)
{
pci_controller_probe();
@@ -190,6 +194,9 @@
isa_init();
ebus_init();
+ rs_init();
+ clock_probe();
+ power_init();
}
struct pci_fixup pcibios_fixups[] = {
@@ -198,6 +205,66 @@
void pcibios_fixup_bus(struct pci_bus *pbus)
{
+ struct pci_pbm_info *pbm = pbus->sysdata;
+
+ /* Generic PCI bus probing sets these to point at
+ * &io{port,mem}_resouce which is wrong for us.
+ */
+ pbus->resource[0] = &pbm->io_space;
+ pbus->resource[1] = &pbm->mem_space;
+}
+
+/* NOTE: This can get called before we've fixed up pdev->sysdata. */
+int pci_claim_resource(struct pci_dev *pdev, int resource)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];
+ struct resource *res = &pdev->resource[resource];
+ struct resource *root;
+
+ if (!pbm)
+ return -EINVAL;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &pbm->io_space;
+ else
+ root = &pbm->mem_space;
+
+ pbm->parent->resource_adjust(pdev, res, root);
+
+ return request_resource(root, res);
+}
+
+int pci_assign_resource(struct pci_dev *pdev, int resource)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct resource *res = &pdev->resource[resource];
+ struct resource *root;
+ unsigned long min, max, size, align;
+ int err;
+
+ if (res->flags & IORESOURCE_IO) {
+ root = &pbm->io_space;
+ min = root->start + 0x400UL;
+ max = root->end;
+ } else {
+ root = &pbm->mem_space;
+ min = root->start;
+ max = min + 0x80000000UL;
+ }
+
+ size = res->end - res->start;
+ align = size + 1;
+
+ err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL);
+ if (err < 0) {
+ printk("PCI: Failed to allocate resource %d for %s\n",
+ resource, pdev->name);
+ } else {
+ pbm->parent->base_address_update(pdev, resource);
+ }
+
+ return err;
}
void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
@@ -238,6 +305,53 @@
/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+/* If the user uses a host-bridge as the PCI device, he may use
+ * this to perform a raw mmap() of the I/O or MEM space behind
+ * that controller.
+ *
+ * This can be useful for execution of x86 PCI bios initialization code
+ * on a PCI card, like the xfree86 int10 stuff does.
+ */
+static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm;
+ unsigned long space_size, user_offset, user_size;
+
+ if (!pcp)
+ return -ENXIO;
+ pbm = pcp->pbm;
+ if (!pbm)
+ return -ENXIO;
+
+ if (mmap_state == pci_mmap_io) {
+ space_size = (pbm->io_space.end -
+ pbm->io_space.start) + 1;
+ } else {
+ space_size = (pbm->mem_space.end -
+ pbm->mem_space.start) + 1;
+ }
+
+ /* Make sure the request is in range. */
+ user_offset = vma->vm_pgoff << PAGE_SHIFT;
+ user_size = vma->vm_end - vma->vm_start;
+
+ if (user_offset >= space_size ||
+ (user_offset + user_size) > space_size)
+ return -EINVAL;
+
+ if (mmap_state == pci_mmap_io) {
+ vma->vm_pgoff = (pbm->io_space.start +
+ user_offset) >> PAGE_SHIFT;
+ } else {
+ vma->vm_pgoff = (pbm->mem_space.start +
+ user_offset) >> PAGE_SHIFT;
+ }
+
+ return 0;
+}
+
/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding
* to the 32-bit pci bus offset for DEV requested by the user.
*
@@ -248,14 +362,17 @@
*
* Returns negative error code on failure, zero on success.
*/
-static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
+static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state)
{
unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long user32 = user_offset & 0xffffffffUL;
unsigned long largest_base, this_base, addr32;
int i;
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+ return __pci_mmap_make_offset_bus(dev, vma, mmap_state);
+
/* Figure out which base address this is for. */
largest_base = 0UL;
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
@@ -303,7 +420,7 @@
/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
* mapping.
*/
-static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
vma->vm_flags |= (VM_SHM | VM_LOCKED);
@@ -312,7 +429,7 @@
/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
-static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
/* Our io_remap_page_range takes care of this, do nothing. */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)