0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include "priv.h"
0024
0025 #include <core/pci.h>
0026
0027 struct priv {
0028 struct pci_dev *pdev;
0029 void __iomem *rom;
0030 size_t size;
0031 };
0032
0033 static u32
0034 pcirom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
0035 {
0036 struct priv *priv = data;
0037 if (offset + length <= priv->size) {
0038 memcpy_fromio(bios->data + offset, priv->rom + offset, length);
0039 return length;
0040 }
0041 return 0;
0042 }
0043
0044 static void
0045 pcirom_fini(void *data)
0046 {
0047 struct priv *priv = data;
0048 pci_unmap_rom(priv->pdev, priv->rom);
0049 pci_disable_rom(priv->pdev);
0050 kfree(priv);
0051 }
0052
0053 static void *
0054 pcirom_init(struct nvkm_bios *bios, const char *name)
0055 {
0056 struct nvkm_device *device = bios->subdev.device;
0057 struct priv *priv = NULL;
0058 struct pci_dev *pdev;
0059 int ret;
0060
0061 if (device->func->pci)
0062 pdev = device->func->pci(device)->pdev;
0063 else
0064 return ERR_PTR(-ENODEV);
0065
0066 if (!(ret = pci_enable_rom(pdev))) {
0067 if (ret = -ENOMEM,
0068 (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
0069 if (ret = -EFAULT,
0070 (priv->rom = pci_map_rom(pdev, &priv->size))) {
0071 priv->pdev = pdev;
0072 return priv;
0073 }
0074 kfree(priv);
0075 }
0076 pci_disable_rom(pdev);
0077 }
0078
0079 return ERR_PTR(ret);
0080 }
0081
0082 const struct nvbios_source
0083 nvbios_pcirom = {
0084 .name = "PCIROM",
0085 .init = pcirom_init,
0086 .fini = pcirom_fini,
0087 .read = pcirom_read,
0088 .rw = true,
0089 };
0090
0091 static void *
0092 platform_init(struct nvkm_bios *bios, const char *name)
0093 {
0094 struct nvkm_device *device = bios->subdev.device;
0095 struct pci_dev *pdev;
0096 struct priv *priv;
0097 int ret = -ENOMEM;
0098
0099 if (device->func->pci)
0100 pdev = device->func->pci(device)->pdev;
0101 else
0102 return ERR_PTR(-ENODEV);
0103
0104 if (!pdev->rom || pdev->romlen == 0)
0105 return ERR_PTR(-ENODEV);
0106
0107 if ((priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
0108 priv->size = pdev->romlen;
0109 if (ret = -ENODEV,
0110 (priv->rom = ioremap(pdev->rom, pdev->romlen)))
0111 return priv;
0112 kfree(priv);
0113 }
0114
0115 return ERR_PTR(ret);
0116 }
0117
0118 static void
0119 platform_fini(void *data)
0120 {
0121 struct priv *priv = data;
0122
0123 iounmap(priv->rom);
0124 kfree(priv);
0125 }
0126
0127 const struct nvbios_source
0128 nvbios_platform = {
0129 .name = "PLATFORM",
0130 .init = platform_init,
0131 .fini = platform_fini,
0132 .read = pcirom_read,
0133 .rw = true,
0134 };