aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c
new file mode 100644
index 000000000000..1d0389c0abef
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c
@@ -0,0 +1,108 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24#include "priv.h"
25
26struct priv {
27 struct pci_dev *pdev;
28 void __iomem *rom;
29 size_t size;
30};
31
32static u32
33pcirom_read(void *data, u32 offset, u32 length, struct nouveau_bios *bios)
34{
35 struct priv *priv = data;
36 if (offset + length <= priv->size) {
37 memcpy_fromio(bios->data + offset, priv->rom + offset, length);
38 return length;
39 }
40 return 0;
41}
42
43static void
44pcirom_fini(void *data)
45{
46 struct priv *priv = data;
47 pci_unmap_rom(priv->pdev, priv->rom);
48 pci_disable_rom(priv->pdev);
49 kfree(priv);
50}
51
52static void *
53pcirom_init(struct nouveau_bios *bios, const char *name)
54{
55 struct pci_dev *pdev = nv_device(bios)->pdev;
56 struct priv *priv = NULL;
57 int ret;
58
59 if (!(ret = pci_enable_rom(pdev))) {
60 if (ret = -ENOMEM,
61 (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
62 if (ret = -EFAULT,
63 (priv->rom = pci_map_rom(pdev, &priv->size))) {
64 priv->pdev = pdev;
65 return priv;
66 }
67 kfree(priv);
68 }
69 pci_disable_rom(pdev);
70 }
71
72 return ERR_PTR(ret);
73}
74
75const struct nvbios_source
76nvbios_pcirom = {
77 .name = "PCIROM",
78 .init = pcirom_init,
79 .fini = pcirom_fini,
80 .read = pcirom_read,
81 .rw = true,
82};
83
84static void *
85platform_init(struct nouveau_bios *bios, const char *name)
86{
87 struct pci_dev *pdev = nv_device(bios)->pdev;
88 struct priv *priv;
89 int ret = -ENOMEM;
90
91 if ((priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
92 if (ret = -ENODEV,
93 (priv->rom = pci_platform_rom(pdev, &priv->size)))
94 return priv;
95 kfree(priv);
96 }
97
98 return ERR_PTR(ret);
99}
100
101const struct nvbios_source
102nvbios_platform = {
103 .name = "PLATFORM",
104 .init = platform_init,
105 .fini = (void(*)(void *))kfree,
106 .read = pcirom_read,
107 .rw = true,
108};