1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
210a0ef39SIvan Kokshaysky /*
310a0ef39SIvan Kokshaysky * arch/alpha/kernel/pci-sysfs.c
410a0ef39SIvan Kokshaysky *
510a0ef39SIvan Kokshaysky * Copyright (C) 2009 Ivan Kokshaysky
610a0ef39SIvan Kokshaysky *
710a0ef39SIvan Kokshaysky * Alpha PCI resource files.
810a0ef39SIvan Kokshaysky *
910a0ef39SIvan Kokshaysky * Loosely based on generic HAVE_PCI_MMAP implementation in
1010a0ef39SIvan Kokshaysky * drivers/pci/pci-sysfs.c
1110a0ef39SIvan Kokshaysky */
1210a0ef39SIvan Kokshaysky
1310a0ef39SIvan Kokshaysky #include <linux/sched.h>
14ce7cf073SPaul Gortmaker #include <linux/stat.h>
155a0e3ad6STejun Heo #include <linux/slab.h>
1610a0ef39SIvan Kokshaysky #include <linux/pci.h>
1710a0ef39SIvan Kokshaysky
hose_mmap_page_range(struct pci_controller * hose,struct vm_area_struct * vma,enum pci_mmap_state mmap_type,int sparse)1810a0ef39SIvan Kokshaysky static int hose_mmap_page_range(struct pci_controller *hose,
1910a0ef39SIvan Kokshaysky struct vm_area_struct *vma,
2010a0ef39SIvan Kokshaysky enum pci_mmap_state mmap_type, int sparse)
2110a0ef39SIvan Kokshaysky {
2210a0ef39SIvan Kokshaysky unsigned long base;
2310a0ef39SIvan Kokshaysky
2410a0ef39SIvan Kokshaysky if (mmap_type == pci_mmap_mem)
2510a0ef39SIvan Kokshaysky base = sparse ? hose->sparse_mem_base : hose->dense_mem_base;
2610a0ef39SIvan Kokshaysky else
2710a0ef39SIvan Kokshaysky base = sparse ? hose->sparse_io_base : hose->dense_io_base;
2810a0ef39SIvan Kokshaysky
2910a0ef39SIvan Kokshaysky vma->vm_pgoff += base >> PAGE_SHIFT;
3010a0ef39SIvan Kokshaysky
3110a0ef39SIvan Kokshaysky return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
3210a0ef39SIvan Kokshaysky vma->vm_end - vma->vm_start,
3310a0ef39SIvan Kokshaysky vma->vm_page_prot);
3410a0ef39SIvan Kokshaysky }
3510a0ef39SIvan Kokshaysky
__pci_mmap_fits(struct pci_dev * pdev,int num,struct vm_area_struct * vma,int sparse)3610a0ef39SIvan Kokshaysky static int __pci_mmap_fits(struct pci_dev *pdev, int num,
3710a0ef39SIvan Kokshaysky struct vm_area_struct *vma, int sparse)
3810a0ef39SIvan Kokshaysky {
3910a0ef39SIvan Kokshaysky unsigned long nr, start, size;
4010a0ef39SIvan Kokshaysky int shift = sparse ? 5 : 0;
4110a0ef39SIvan Kokshaysky
42236d62b0SShyam Saini nr = vma_pages(vma);
4310a0ef39SIvan Kokshaysky start = vma->vm_pgoff;
4410a0ef39SIvan Kokshaysky size = ((pci_resource_len(pdev, num) - 1) >> (PAGE_SHIFT - shift)) + 1;
4510a0ef39SIvan Kokshaysky
4610a0ef39SIvan Kokshaysky if (start < size && size - start >= nr)
4710a0ef39SIvan Kokshaysky return 1;
4810a0ef39SIvan Kokshaysky WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on %s BAR %d "
4910a0ef39SIvan Kokshaysky "(size 0x%08lx)\n",
5010a0ef39SIvan Kokshaysky current->comm, sparse ? " sparse" : "", start, start + nr,
5110a0ef39SIvan Kokshaysky pci_name(pdev), num, size);
5210a0ef39SIvan Kokshaysky return 0;
5310a0ef39SIvan Kokshaysky }
5410a0ef39SIvan Kokshaysky
5510a0ef39SIvan Kokshaysky /**
5610a0ef39SIvan Kokshaysky * pci_mmap_resource - map a PCI resource into user memory space
5710a0ef39SIvan Kokshaysky * @kobj: kobject for mapping
5810a0ef39SIvan Kokshaysky * @attr: struct bin_attribute for the file being mapped
5910a0ef39SIvan Kokshaysky * @vma: struct vm_area_struct passed into the mmap
6010a0ef39SIvan Kokshaysky * @sparse: address space type
6110a0ef39SIvan Kokshaysky *
6210a0ef39SIvan Kokshaysky * Use the bus mapping routines to map a PCI resource into userspace.
63*0a9d991cSRandy Dunlap *
64*0a9d991cSRandy Dunlap * Return: %0 on success, negative error code otherwise
6510a0ef39SIvan Kokshaysky */
pci_mmap_resource(struct kobject * kobj,struct bin_attribute * attr,struct vm_area_struct * vma,int sparse)665efa16ffSMatt Turner static int pci_mmap_resource(struct kobject *kobj,
672c3c8beaSChris Wright struct bin_attribute *attr,
6810a0ef39SIvan Kokshaysky struct vm_area_struct *vma, int sparse)
6910a0ef39SIvan Kokshaysky {
708c9b839cSGeliang Tang struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
71af96f8a3Smatt mooney struct resource *res = attr->private;
7210a0ef39SIvan Kokshaysky enum pci_mmap_state mmap_type;
7310a0ef39SIvan Kokshaysky struct pci_bus_region bar;
7410a0ef39SIvan Kokshaysky int i;
7510a0ef39SIvan Kokshaysky
76c9c13ba4SDenis Efremov for (i = 0; i < PCI_STD_NUM_BARS; i++)
7710a0ef39SIvan Kokshaysky if (res == &pdev->resource[i])
7810a0ef39SIvan Kokshaysky break;
79c9c13ba4SDenis Efremov if (i >= PCI_STD_NUM_BARS)
8010a0ef39SIvan Kokshaysky return -ENODEV;
8110a0ef39SIvan Kokshaysky
82c20e1280SBjorn Helgaas if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
8310a0ef39SIvan Kokshaysky return -EINVAL;
8410a0ef39SIvan Kokshaysky
85c20e1280SBjorn Helgaas if (!__pci_mmap_fits(pdev, i, vma, sparse))
8610a0ef39SIvan Kokshaysky return -EINVAL;
8710a0ef39SIvan Kokshaysky
88fc279850SYinghai Lu pcibios_resource_to_bus(pdev->bus, &bar, res);
8910a0ef39SIvan Kokshaysky vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0));
9010a0ef39SIvan Kokshaysky mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
9110a0ef39SIvan Kokshaysky
9210a0ef39SIvan Kokshaysky return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse);
9310a0ef39SIvan Kokshaysky }
9410a0ef39SIvan Kokshaysky
pci_mmap_resource_sparse(struct file * filp,struct kobject * kobj,struct bin_attribute * attr,struct vm_area_struct * vma)952c3c8beaSChris Wright static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj,
9610a0ef39SIvan Kokshaysky struct bin_attribute *attr,
9710a0ef39SIvan Kokshaysky struct vm_area_struct *vma)
9810a0ef39SIvan Kokshaysky {
9910a0ef39SIvan Kokshaysky return pci_mmap_resource(kobj, attr, vma, 1);
10010a0ef39SIvan Kokshaysky }
10110a0ef39SIvan Kokshaysky
pci_mmap_resource_dense(struct file * filp,struct kobject * kobj,struct bin_attribute * attr,struct vm_area_struct * vma)1022c3c8beaSChris Wright static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj,
10310a0ef39SIvan Kokshaysky struct bin_attribute *attr,
10410a0ef39SIvan Kokshaysky struct vm_area_struct *vma)
10510a0ef39SIvan Kokshaysky {
10610a0ef39SIvan Kokshaysky return pci_mmap_resource(kobj, attr, vma, 0);
10710a0ef39SIvan Kokshaysky }
10810a0ef39SIvan Kokshaysky
10910a0ef39SIvan Kokshaysky /**
11010a0ef39SIvan Kokshaysky * pci_remove_resource_files - cleanup resource files
111*0a9d991cSRandy Dunlap * @pdev: pci_dev to cleanup
11210a0ef39SIvan Kokshaysky *
11310a0ef39SIvan Kokshaysky * If we created resource files for @dev, remove them from sysfs and
11410a0ef39SIvan Kokshaysky * free their resources.
11510a0ef39SIvan Kokshaysky */
pci_remove_resource_files(struct pci_dev * pdev)11610a0ef39SIvan Kokshaysky void pci_remove_resource_files(struct pci_dev *pdev)
11710a0ef39SIvan Kokshaysky {
11810a0ef39SIvan Kokshaysky int i;
11910a0ef39SIvan Kokshaysky
120c9c13ba4SDenis Efremov for (i = 0; i < PCI_STD_NUM_BARS; i++) {
12110a0ef39SIvan Kokshaysky struct bin_attribute *res_attr;
12210a0ef39SIvan Kokshaysky
12310a0ef39SIvan Kokshaysky res_attr = pdev->res_attr[i];
12410a0ef39SIvan Kokshaysky if (res_attr) {
12510a0ef39SIvan Kokshaysky sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
12610a0ef39SIvan Kokshaysky kfree(res_attr);
12710a0ef39SIvan Kokshaysky }
12810a0ef39SIvan Kokshaysky
12910a0ef39SIvan Kokshaysky res_attr = pdev->res_attr_wc[i];
13010a0ef39SIvan Kokshaysky if (res_attr) {
13110a0ef39SIvan Kokshaysky sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
13210a0ef39SIvan Kokshaysky kfree(res_attr);
13310a0ef39SIvan Kokshaysky }
13410a0ef39SIvan Kokshaysky }
13510a0ef39SIvan Kokshaysky }
13610a0ef39SIvan Kokshaysky
sparse_mem_mmap_fits(struct pci_dev * pdev,int num)13710a0ef39SIvan Kokshaysky static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
13810a0ef39SIvan Kokshaysky {
13910a0ef39SIvan Kokshaysky struct pci_bus_region bar;
14010a0ef39SIvan Kokshaysky struct pci_controller *hose = pdev->sysdata;
14110a0ef39SIvan Kokshaysky long dense_offset;
14210a0ef39SIvan Kokshaysky unsigned long sparse_size;
14310a0ef39SIvan Kokshaysky
144fc279850SYinghai Lu pcibios_resource_to_bus(pdev->bus, &bar, &pdev->resource[num]);
14510a0ef39SIvan Kokshaysky
14610a0ef39SIvan Kokshaysky /* All core logic chips have 4G sparse address space, except
14710a0ef39SIvan Kokshaysky CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM
14810a0ef39SIvan Kokshaysky definitions in asm/core_xxx.h files). This corresponds
14910a0ef39SIvan Kokshaysky to 128M or 512M of the bus space. */
15010a0ef39SIvan Kokshaysky dense_offset = (long)(hose->dense_mem_base - hose->sparse_mem_base);
15110a0ef39SIvan Kokshaysky sparse_size = dense_offset >= 0x400000000UL ? 0x20000000 : 0x8000000;
15210a0ef39SIvan Kokshaysky
15310a0ef39SIvan Kokshaysky return bar.end < sparse_size;
15410a0ef39SIvan Kokshaysky }
15510a0ef39SIvan Kokshaysky
pci_create_one_attr(struct pci_dev * pdev,int num,char * name,char * suffix,struct bin_attribute * res_attr,unsigned long sparse)15610a0ef39SIvan Kokshaysky static int pci_create_one_attr(struct pci_dev *pdev, int num, char *name,
15710a0ef39SIvan Kokshaysky char *suffix, struct bin_attribute *res_attr,
15810a0ef39SIvan Kokshaysky unsigned long sparse)
15910a0ef39SIvan Kokshaysky {
16010a0ef39SIvan Kokshaysky size_t size = pci_resource_len(pdev, num);
16110a0ef39SIvan Kokshaysky
16210a0ef39SIvan Kokshaysky sprintf(name, "resource%d%s", num, suffix);
16310a0ef39SIvan Kokshaysky res_attr->mmap = sparse ? pci_mmap_resource_sparse :
16410a0ef39SIvan Kokshaysky pci_mmap_resource_dense;
16510a0ef39SIvan Kokshaysky res_attr->attr.name = name;
16610a0ef39SIvan Kokshaysky res_attr->attr.mode = S_IRUSR | S_IWUSR;
16710a0ef39SIvan Kokshaysky res_attr->size = sparse ? size << 5 : size;
16810a0ef39SIvan Kokshaysky res_attr->private = &pdev->resource[num];
16910a0ef39SIvan Kokshaysky return sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
17010a0ef39SIvan Kokshaysky }
17110a0ef39SIvan Kokshaysky
pci_create_attr(struct pci_dev * pdev,int num)17210a0ef39SIvan Kokshaysky static int pci_create_attr(struct pci_dev *pdev, int num)
17310a0ef39SIvan Kokshaysky {
17410a0ef39SIvan Kokshaysky /* allocate attribute structure, piggyback attribute name */
17510a0ef39SIvan Kokshaysky int retval, nlen1, nlen2 = 0, res_count = 1;
17610a0ef39SIvan Kokshaysky unsigned long sparse_base, dense_base;
17710a0ef39SIvan Kokshaysky struct bin_attribute *attr;
17810a0ef39SIvan Kokshaysky struct pci_controller *hose = pdev->sysdata;
17910a0ef39SIvan Kokshaysky char *suffix, *attr_name;
18010a0ef39SIvan Kokshaysky
18110a0ef39SIvan Kokshaysky suffix = ""; /* Assume bwx machine, normal resourceN files. */
18210a0ef39SIvan Kokshaysky nlen1 = 10;
18310a0ef39SIvan Kokshaysky
18410a0ef39SIvan Kokshaysky if (pdev->resource[num].flags & IORESOURCE_MEM) {
18510a0ef39SIvan Kokshaysky sparse_base = hose->sparse_mem_base;
18610a0ef39SIvan Kokshaysky dense_base = hose->dense_mem_base;
18710a0ef39SIvan Kokshaysky if (sparse_base && !sparse_mem_mmap_fits(pdev, num)) {
18810a0ef39SIvan Kokshaysky sparse_base = 0;
18910a0ef39SIvan Kokshaysky suffix = "_dense";
19010a0ef39SIvan Kokshaysky nlen1 = 16; /* resourceN_dense */
19110a0ef39SIvan Kokshaysky }
19210a0ef39SIvan Kokshaysky } else {
19310a0ef39SIvan Kokshaysky sparse_base = hose->sparse_io_base;
19410a0ef39SIvan Kokshaysky dense_base = hose->dense_io_base;
19510a0ef39SIvan Kokshaysky }
19610a0ef39SIvan Kokshaysky
19710a0ef39SIvan Kokshaysky if (sparse_base) {
19810a0ef39SIvan Kokshaysky suffix = "_sparse";
19910a0ef39SIvan Kokshaysky nlen1 = 17;
20010a0ef39SIvan Kokshaysky if (dense_base) {
20110a0ef39SIvan Kokshaysky nlen2 = 16; /* resourceN_dense */
20210a0ef39SIvan Kokshaysky res_count = 2;
20310a0ef39SIvan Kokshaysky }
20410a0ef39SIvan Kokshaysky }
20510a0ef39SIvan Kokshaysky
20610a0ef39SIvan Kokshaysky attr = kzalloc(sizeof(*attr) * res_count + nlen1 + nlen2, GFP_ATOMIC);
20710a0ef39SIvan Kokshaysky if (!attr)
20810a0ef39SIvan Kokshaysky return -ENOMEM;
20910a0ef39SIvan Kokshaysky
21010a0ef39SIvan Kokshaysky /* Create bwx, sparse or single dense file */
21110a0ef39SIvan Kokshaysky attr_name = (char *)(attr + res_count);
21210a0ef39SIvan Kokshaysky pdev->res_attr[num] = attr;
21310a0ef39SIvan Kokshaysky retval = pci_create_one_attr(pdev, num, attr_name, suffix, attr,
21410a0ef39SIvan Kokshaysky sparse_base);
21510a0ef39SIvan Kokshaysky if (retval || res_count == 1)
21610a0ef39SIvan Kokshaysky return retval;
21710a0ef39SIvan Kokshaysky
21810a0ef39SIvan Kokshaysky /* Create dense file */
21910a0ef39SIvan Kokshaysky attr_name += nlen1;
22010a0ef39SIvan Kokshaysky attr++;
22110a0ef39SIvan Kokshaysky pdev->res_attr_wc[num] = attr;
22210a0ef39SIvan Kokshaysky return pci_create_one_attr(pdev, num, attr_name, "_dense", attr, 0);
22310a0ef39SIvan Kokshaysky }
22410a0ef39SIvan Kokshaysky
22510a0ef39SIvan Kokshaysky /**
226*0a9d991cSRandy Dunlap * pci_create_resource_files - create resource files in sysfs for @pdev
227*0a9d991cSRandy Dunlap * @pdev: pci_dev in question
22810a0ef39SIvan Kokshaysky *
22910a0ef39SIvan Kokshaysky * Walk the resources in @dev creating files for each resource available.
230*0a9d991cSRandy Dunlap *
231*0a9d991cSRandy Dunlap * Return: %0 on success, or negative error code
23210a0ef39SIvan Kokshaysky */
pci_create_resource_files(struct pci_dev * pdev)23310a0ef39SIvan Kokshaysky int pci_create_resource_files(struct pci_dev *pdev)
23410a0ef39SIvan Kokshaysky {
23510a0ef39SIvan Kokshaysky int i;
23610a0ef39SIvan Kokshaysky int retval;
23710a0ef39SIvan Kokshaysky
23810a0ef39SIvan Kokshaysky /* Expose the PCI resources from this device as files */
239c9c13ba4SDenis Efremov for (i = 0; i < PCI_STD_NUM_BARS; i++) {
24010a0ef39SIvan Kokshaysky
24110a0ef39SIvan Kokshaysky /* skip empty resources */
24210a0ef39SIvan Kokshaysky if (!pci_resource_len(pdev, i))
24310a0ef39SIvan Kokshaysky continue;
24410a0ef39SIvan Kokshaysky
24510a0ef39SIvan Kokshaysky retval = pci_create_attr(pdev, i);
24610a0ef39SIvan Kokshaysky if (retval) {
24710a0ef39SIvan Kokshaysky pci_remove_resource_files(pdev);
24810a0ef39SIvan Kokshaysky return retval;
24910a0ef39SIvan Kokshaysky }
25010a0ef39SIvan Kokshaysky }
25110a0ef39SIvan Kokshaysky return 0;
25210a0ef39SIvan Kokshaysky }
25310a0ef39SIvan Kokshaysky
25410a0ef39SIvan Kokshaysky /* Legacy I/O bus mapping stuff. */
25510a0ef39SIvan Kokshaysky
__legacy_mmap_fits(struct pci_controller * hose,struct vm_area_struct * vma,unsigned long res_size,int sparse)25610a0ef39SIvan Kokshaysky static int __legacy_mmap_fits(struct pci_controller *hose,
25710a0ef39SIvan Kokshaysky struct vm_area_struct *vma,
25810a0ef39SIvan Kokshaysky unsigned long res_size, int sparse)
25910a0ef39SIvan Kokshaysky {
26010a0ef39SIvan Kokshaysky unsigned long nr, start, size;
26110a0ef39SIvan Kokshaysky
262236d62b0SShyam Saini nr = vma_pages(vma);
26310a0ef39SIvan Kokshaysky start = vma->vm_pgoff;
26410a0ef39SIvan Kokshaysky size = ((res_size - 1) >> PAGE_SHIFT) + 1;
26510a0ef39SIvan Kokshaysky
26610a0ef39SIvan Kokshaysky if (start < size && size - start >= nr)
26710a0ef39SIvan Kokshaysky return 1;
26810a0ef39SIvan Kokshaysky WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on hose %d "
26910a0ef39SIvan Kokshaysky "(size 0x%08lx)\n",
27010a0ef39SIvan Kokshaysky current->comm, sparse ? " sparse" : "", start, start + nr,
27110a0ef39SIvan Kokshaysky hose->index, size);
27210a0ef39SIvan Kokshaysky return 0;
27310a0ef39SIvan Kokshaysky }
27410a0ef39SIvan Kokshaysky
has_sparse(struct pci_controller * hose,enum pci_mmap_state mmap_type)27510a0ef39SIvan Kokshaysky static inline int has_sparse(struct pci_controller *hose,
27610a0ef39SIvan Kokshaysky enum pci_mmap_state mmap_type)
27710a0ef39SIvan Kokshaysky {
27810a0ef39SIvan Kokshaysky unsigned long base;
27910a0ef39SIvan Kokshaysky
28010a0ef39SIvan Kokshaysky base = (mmap_type == pci_mmap_mem) ? hose->sparse_mem_base :
28110a0ef39SIvan Kokshaysky hose->sparse_io_base;
28210a0ef39SIvan Kokshaysky
28310a0ef39SIvan Kokshaysky return base != 0;
28410a0ef39SIvan Kokshaysky }
28510a0ef39SIvan Kokshaysky
pci_mmap_legacy_page_range(struct pci_bus * bus,struct vm_area_struct * vma,enum pci_mmap_state mmap_type)28610a0ef39SIvan Kokshaysky int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
28710a0ef39SIvan Kokshaysky enum pci_mmap_state mmap_type)
28810a0ef39SIvan Kokshaysky {
28910a0ef39SIvan Kokshaysky struct pci_controller *hose = bus->sysdata;
29010a0ef39SIvan Kokshaysky int sparse = has_sparse(hose, mmap_type);
29110a0ef39SIvan Kokshaysky unsigned long res_size;
29210a0ef39SIvan Kokshaysky
29310a0ef39SIvan Kokshaysky res_size = (mmap_type == pci_mmap_mem) ? bus->legacy_mem->size :
29410a0ef39SIvan Kokshaysky bus->legacy_io->size;
29510a0ef39SIvan Kokshaysky if (!__legacy_mmap_fits(hose, vma, res_size, sparse))
29610a0ef39SIvan Kokshaysky return -EINVAL;
29710a0ef39SIvan Kokshaysky
29810a0ef39SIvan Kokshaysky return hose_mmap_page_range(hose, vma, mmap_type, sparse);
29910a0ef39SIvan Kokshaysky }
30010a0ef39SIvan Kokshaysky
30110a0ef39SIvan Kokshaysky /**
30210a0ef39SIvan Kokshaysky * pci_adjust_legacy_attr - adjustment of legacy file attributes
303*0a9d991cSRandy Dunlap * @bus: bus to create files under
30410a0ef39SIvan Kokshaysky * @mmap_type: I/O port or memory
30510a0ef39SIvan Kokshaysky *
30610a0ef39SIvan Kokshaysky * Adjust file name and size for sparse mappings.
30710a0ef39SIvan Kokshaysky */
pci_adjust_legacy_attr(struct pci_bus * bus,enum pci_mmap_state mmap_type)30810a0ef39SIvan Kokshaysky void pci_adjust_legacy_attr(struct pci_bus *bus, enum pci_mmap_state mmap_type)
30910a0ef39SIvan Kokshaysky {
31010a0ef39SIvan Kokshaysky struct pci_controller *hose = bus->sysdata;
31110a0ef39SIvan Kokshaysky
31210a0ef39SIvan Kokshaysky if (!has_sparse(hose, mmap_type))
31310a0ef39SIvan Kokshaysky return;
31410a0ef39SIvan Kokshaysky
31510a0ef39SIvan Kokshaysky if (mmap_type == pci_mmap_mem) {
31610a0ef39SIvan Kokshaysky bus->legacy_mem->attr.name = "legacy_mem_sparse";
31710a0ef39SIvan Kokshaysky bus->legacy_mem->size <<= 5;
31810a0ef39SIvan Kokshaysky } else {
31910a0ef39SIvan Kokshaysky bus->legacy_io->attr.name = "legacy_io_sparse";
32010a0ef39SIvan Kokshaysky bus->legacy_io->size <<= 5;
32110a0ef39SIvan Kokshaysky }
32210a0ef39SIvan Kokshaysky return;
32310a0ef39SIvan Kokshaysky }
32410a0ef39SIvan Kokshaysky
32510a0ef39SIvan Kokshaysky /* Legacy I/O bus read/write functions */
pci_legacy_read(struct pci_bus * bus,loff_t port,u32 * val,size_t size)32610a0ef39SIvan Kokshaysky int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size)
32710a0ef39SIvan Kokshaysky {
32810a0ef39SIvan Kokshaysky struct pci_controller *hose = bus->sysdata;
32910a0ef39SIvan Kokshaysky
33010a0ef39SIvan Kokshaysky port += hose->io_space->start;
33110a0ef39SIvan Kokshaysky
33210a0ef39SIvan Kokshaysky switch(size) {
33310a0ef39SIvan Kokshaysky case 1:
33410a0ef39SIvan Kokshaysky *((u8 *)val) = inb(port);
33510a0ef39SIvan Kokshaysky return 1;
33610a0ef39SIvan Kokshaysky case 2:
33710a0ef39SIvan Kokshaysky if (port & 1)
33810a0ef39SIvan Kokshaysky return -EINVAL;
33910a0ef39SIvan Kokshaysky *((u16 *)val) = inw(port);
34010a0ef39SIvan Kokshaysky return 2;
34110a0ef39SIvan Kokshaysky case 4:
34210a0ef39SIvan Kokshaysky if (port & 3)
34310a0ef39SIvan Kokshaysky return -EINVAL;
34410a0ef39SIvan Kokshaysky *((u32 *)val) = inl(port);
34510a0ef39SIvan Kokshaysky return 4;
34610a0ef39SIvan Kokshaysky }
34710a0ef39SIvan Kokshaysky return -EINVAL;
34810a0ef39SIvan Kokshaysky }
34910a0ef39SIvan Kokshaysky
pci_legacy_write(struct pci_bus * bus,loff_t port,u32 val,size_t size)35010a0ef39SIvan Kokshaysky int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
35110a0ef39SIvan Kokshaysky {
35210a0ef39SIvan Kokshaysky struct pci_controller *hose = bus->sysdata;
35310a0ef39SIvan Kokshaysky
35410a0ef39SIvan Kokshaysky port += hose->io_space->start;
35510a0ef39SIvan Kokshaysky
35610a0ef39SIvan Kokshaysky switch(size) {
35710a0ef39SIvan Kokshaysky case 1:
35810a0ef39SIvan Kokshaysky outb(port, val);
35910a0ef39SIvan Kokshaysky return 1;
36010a0ef39SIvan Kokshaysky case 2:
36110a0ef39SIvan Kokshaysky if (port & 1)
36210a0ef39SIvan Kokshaysky return -EINVAL;
36310a0ef39SIvan Kokshaysky outw(port, val);
36410a0ef39SIvan Kokshaysky return 2;
36510a0ef39SIvan Kokshaysky case 4:
36610a0ef39SIvan Kokshaysky if (port & 3)
36710a0ef39SIvan Kokshaysky return -EINVAL;
36810a0ef39SIvan Kokshaysky outl(port, val);
36910a0ef39SIvan Kokshaysky return 4;
37010a0ef39SIvan Kokshaysky }
37110a0ef39SIvan Kokshaysky return -EINVAL;
37210a0ef39SIvan Kokshaysky }
373