Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
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 };