linux/drivers/char/agp/alpha-agp.c
<<
>>
Prefs
   1#include <linux/module.h>
   2#include <linux/pci.h>
   3#include <linux/init.h>
   4#include <linux/agp_backend.h>
   5#include <linux/mm.h>
   6#include <linux/slab.h>
   7
   8#include <asm/machvec.h>
   9#include <asm/agp_backend.h>
  10#include "../../../arch/alpha/kernel/pci_impl.h"
  11
  12#include "agp.h"
  13
  14static vm_fault_t alpha_core_agp_vm_fault(struct vm_fault *vmf)
  15{
  16        alpha_agp_info *agp = agp_bridge->dev_private_data;
  17        dma_addr_t dma_addr;
  18        unsigned long pa;
  19        struct page *page;
  20
  21        dma_addr = vmf->address - vmf->vma->vm_start + agp->aperture.bus_base;
  22        pa = agp->ops->translate(agp, dma_addr);
  23
  24        if (pa == (unsigned long)-EINVAL)
  25                return VM_FAULT_SIGBUS; /* no translation */
  26
  27        /*
  28         * Get the page, inc the use count, and return it
  29         */
  30        page = virt_to_page(__va(pa));
  31        get_page(page);
  32        vmf->page = page;
  33        return 0;
  34}
  35
  36static struct aper_size_info_fixed alpha_core_agp_sizes[] =
  37{
  38        { 0, 0, 0 }, /* filled in by alpha_core_agp_setup */
  39};
  40
  41static const struct vm_operations_struct alpha_core_agp_vm_ops = {
  42        .fault = alpha_core_agp_vm_fault,
  43};
  44
  45
  46static int alpha_core_agp_fetch_size(void)
  47{
  48        return alpha_core_agp_sizes[0].size;
  49}
  50
  51static int alpha_core_agp_configure(void)
  52{
  53        alpha_agp_info *agp = agp_bridge->dev_private_data;
  54        agp_bridge->gart_bus_addr = agp->aperture.bus_base;
  55        return 0;
  56}
  57
  58static void alpha_core_agp_cleanup(void)
  59{
  60        alpha_agp_info *agp = agp_bridge->dev_private_data;
  61
  62        agp->ops->cleanup(agp);
  63}
  64
  65static void alpha_core_agp_tlbflush(struct agp_memory *mem)
  66{
  67        alpha_agp_info *agp = agp_bridge->dev_private_data;
  68        alpha_mv.mv_pci_tbi(agp->hose, 0, -1);
  69}
  70
  71static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
  72{
  73        alpha_agp_info *agp = bridge->dev_private_data;
  74
  75        agp->mode.lw = agp_collect_device_status(bridge, mode,
  76                                        agp->capability.lw);
  77
  78        agp->mode.bits.enable = 1;
  79        agp->ops->configure(agp);
  80
  81        agp_device_command(agp->mode.lw, false);
  82}
  83
  84static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
  85                                        int type)
  86{
  87        alpha_agp_info *agp = agp_bridge->dev_private_data;
  88        int num_entries, status;
  89        void *temp;
  90
  91        if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
  92                return -EINVAL;
  93
  94        temp = agp_bridge->current_size;
  95        num_entries = A_SIZE_FIX(temp)->num_entries;
  96        if ((pg_start + mem->page_count) > num_entries)
  97                return -EINVAL;
  98
  99        status = agp->ops->bind(agp, pg_start, mem);
 100        mb();
 101        alpha_core_agp_tlbflush(mem);
 102
 103        return status;
 104}
 105
 106static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
 107                                        int type)
 108{
 109        alpha_agp_info *agp = agp_bridge->dev_private_data;
 110        int status;
 111
 112        status = agp->ops->unbind(agp, pg_start, mem);
 113        alpha_core_agp_tlbflush(mem);
 114        return status;
 115}
 116
 117static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a)
 118{
 119        return 0;
 120}
 121
 122struct agp_bridge_driver alpha_core_agp_driver = {
 123        .owner                  = THIS_MODULE,
 124        .aperture_sizes         = alpha_core_agp_sizes,
 125        .num_aperture_sizes     = 1,
 126        .size_type              = FIXED_APER_SIZE,
 127        .cant_use_aperture      = true,
 128        .masks                  = NULL,
 129
 130        .fetch_size             = alpha_core_agp_fetch_size,
 131        .configure              = alpha_core_agp_configure,
 132        .agp_enable             = alpha_core_agp_enable,
 133        .cleanup                = alpha_core_agp_cleanup,
 134        .tlb_flush              = alpha_core_agp_tlbflush,
 135        .mask_memory            = agp_generic_mask_memory,
 136        .cache_flush            = global_cache_flush,
 137        .create_gatt_table      = alpha_core_agp_create_free_gatt_table,
 138        .free_gatt_table        = alpha_core_agp_create_free_gatt_table,
 139        .insert_memory          = alpha_core_agp_insert_memory,
 140        .remove_memory          = alpha_core_agp_remove_memory,
 141        .alloc_by_type          = agp_generic_alloc_by_type,
 142        .free_by_type           = agp_generic_free_by_type,
 143        .agp_alloc_page         = agp_generic_alloc_page,
 144        .agp_alloc_pages        = agp_generic_alloc_pages,
 145        .agp_destroy_page       = agp_generic_destroy_page,
 146        .agp_destroy_pages      = agp_generic_destroy_pages,
 147        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 148};
 149
 150struct agp_bridge_data *alpha_bridge;
 151
 152int __init
 153alpha_core_agp_setup(void)
 154{
 155        alpha_agp_info *agp = alpha_mv.agp_info();
 156        struct pci_dev *pdev;   /* faked */
 157        struct aper_size_info_fixed *aper_size;
 158
 159        if (!agp)
 160                return -ENODEV;
 161        if (agp->ops->setup(agp))
 162                return -ENODEV;
 163
 164        /*
 165         * Build the aperture size descriptor
 166         */
 167        aper_size = alpha_core_agp_sizes;
 168        aper_size->size = agp->aperture.size / (1024 * 1024);
 169        aper_size->num_entries = agp->aperture.size / PAGE_SIZE;
 170        aper_size->page_order = __ffs(aper_size->num_entries / 1024);
 171
 172        /*
 173         * Build a fake pci_dev struct
 174         */
 175        pdev = pci_alloc_dev(NULL);
 176        if (!pdev)
 177                return -ENOMEM;
 178        pdev->vendor = 0xffff;
 179        pdev->device = 0xffff;
 180        pdev->sysdata = agp->hose;
 181
 182        alpha_bridge = agp_alloc_bridge();
 183        if (!alpha_bridge)
 184                goto fail;
 185
 186        alpha_bridge->driver = &alpha_core_agp_driver;
 187        alpha_bridge->vm_ops = &alpha_core_agp_vm_ops;
 188        alpha_bridge->current_size = aper_size; /* only 1 size */
 189        alpha_bridge->dev_private_data = agp;
 190        alpha_bridge->dev = pdev;
 191        alpha_bridge->mode = agp->capability.lw;
 192
 193        printk(KERN_INFO PFX "Detected AGP on hose %d\n", agp->hose->index);
 194        return agp_add_bridge(alpha_bridge);
 195
 196 fail:
 197        kfree(pdev);
 198        return -ENOMEM;
 199}
 200
 201static int __init agp_alpha_core_init(void)
 202{
 203        if (agp_off)
 204                return -EINVAL;
 205        if (alpha_mv.agp_info)
 206                return alpha_core_agp_setup();
 207        return -ENODEV;
 208}
 209
 210static void __exit agp_alpha_core_cleanup(void)
 211{
 212        agp_remove_bridge(alpha_bridge);
 213        agp_put_bridge(alpha_bridge);
 214}
 215
 216module_init(agp_alpha_core_init);
 217module_exit(agp_alpha_core_cleanup);
 218
 219MODULE_AUTHOR("Jeff Wiedemeier <Jeff.Wiedemeier@hp.com>");
 220MODULE_LICENSE("GPL and additional rights");
 221