diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/agp/alpha-agp.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/agp/alpha-agp.c')
-rw-r--r-- | drivers/char/agp/alpha-agp.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c new file mode 100644 index 00000000000..a072d32005a --- /dev/null +++ b/drivers/char/agp/alpha-agp.c | |||
@@ -0,0 +1,216 @@ | |||
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 | |||
14 | static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma, | ||
15 | unsigned long address, | ||
16 | int *type) | ||
17 | { | ||
18 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
19 | dma_addr_t dma_addr; | ||
20 | unsigned long pa; | ||
21 | struct page *page; | ||
22 | |||
23 | dma_addr = address - vma->vm_start + agp->aperture.bus_base; | ||
24 | pa = agp->ops->translate(agp, dma_addr); | ||
25 | |||
26 | if (pa == (unsigned long)-EINVAL) return NULL; /* no translation */ | ||
27 | |||
28 | /* | ||
29 | * Get the page, inc the use count, and return it | ||
30 | */ | ||
31 | page = virt_to_page(__va(pa)); | ||
32 | get_page(page); | ||
33 | if (type) | ||
34 | *type = VM_FAULT_MINOR; | ||
35 | return page; | ||
36 | } | ||
37 | |||
38 | static struct aper_size_info_fixed alpha_core_agp_sizes[] = | ||
39 | { | ||
40 | { 0, 0, 0 }, /* filled in by alpha_core_agp_setup */ | ||
41 | }; | ||
42 | |||
43 | struct vm_operations_struct alpha_core_agp_vm_ops = { | ||
44 | .nopage = alpha_core_agp_vm_nopage, | ||
45 | }; | ||
46 | |||
47 | |||
48 | static int alpha_core_agp_nop(void) | ||
49 | { | ||
50 | /* just return success */ | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static int alpha_core_agp_fetch_size(void) | ||
55 | { | ||
56 | return alpha_core_agp_sizes[0].size; | ||
57 | } | ||
58 | |||
59 | static int alpha_core_agp_configure(void) | ||
60 | { | ||
61 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
62 | agp_bridge->gart_bus_addr = agp->aperture.bus_base; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void alpha_core_agp_cleanup(void) | ||
67 | { | ||
68 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
69 | |||
70 | agp->ops->cleanup(agp); | ||
71 | } | ||
72 | |||
73 | static void alpha_core_agp_tlbflush(struct agp_memory *mem) | ||
74 | { | ||
75 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
76 | alpha_mv.mv_pci_tbi(agp->hose, 0, -1); | ||
77 | } | ||
78 | |||
79 | static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode) | ||
80 | { | ||
81 | alpha_agp_info *agp = bridge->dev_private_data; | ||
82 | |||
83 | agp->mode.lw = agp_collect_device_status(bridge, mode, | ||
84 | agp->capability.lw); | ||
85 | |||
86 | agp->mode.bits.enable = 1; | ||
87 | agp->ops->configure(agp); | ||
88 | |||
89 | agp_device_command(agp->mode.lw, 0); | ||
90 | } | ||
91 | |||
92 | static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, | ||
93 | int type) | ||
94 | { | ||
95 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
96 | int num_entries, status; | ||
97 | void *temp; | ||
98 | |||
99 | temp = agp_bridge->current_size; | ||
100 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
101 | if ((pg_start + mem->page_count) > num_entries) return -EINVAL; | ||
102 | |||
103 | status = agp->ops->bind(agp, pg_start, mem); | ||
104 | mb(); | ||
105 | alpha_core_agp_tlbflush(mem); | ||
106 | |||
107 | return status; | ||
108 | } | ||
109 | |||
110 | static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start, | ||
111 | int type) | ||
112 | { | ||
113 | alpha_agp_info *agp = agp_bridge->dev_private_data; | ||
114 | int status; | ||
115 | |||
116 | status = agp->ops->unbind(agp, pg_start, mem); | ||
117 | alpha_core_agp_tlbflush(mem); | ||
118 | return status; | ||
119 | } | ||
120 | |||
121 | struct agp_bridge_driver alpha_core_agp_driver = { | ||
122 | .owner = THIS_MODULE, | ||
123 | .aperture_sizes = alpha_core_agp_sizes, | ||
124 | .num_aperture_sizes = 1, | ||
125 | .size_type = FIXED_APER_SIZE, | ||
126 | .cant_use_aperture = 1, | ||
127 | .masks = NULL, | ||
128 | |||
129 | .fetch_size = alpha_core_agp_fetch_size, | ||
130 | .configure = alpha_core_agp_configure, | ||
131 | .agp_enable = alpha_core_agp_enable, | ||
132 | .cleanup = alpha_core_agp_cleanup, | ||
133 | .tlb_flush = alpha_core_agp_tlbflush, | ||
134 | .mask_memory = agp_generic_mask_memory, | ||
135 | .cache_flush = global_cache_flush, | ||
136 | .create_gatt_table = alpha_core_agp_nop, | ||
137 | .free_gatt_table = alpha_core_agp_nop, | ||
138 | .insert_memory = alpha_core_agp_insert_memory, | ||
139 | .remove_memory = alpha_core_agp_remove_memory, | ||
140 | .alloc_by_type = agp_generic_alloc_by_type, | ||
141 | .free_by_type = agp_generic_free_by_type, | ||
142 | .agp_alloc_page = agp_generic_alloc_page, | ||
143 | .agp_destroy_page = agp_generic_destroy_page, | ||
144 | }; | ||
145 | |||
146 | struct agp_bridge_data *alpha_bridge; | ||
147 | |||
148 | int __init | ||
149 | alpha_core_agp_setup(void) | ||
150 | { | ||
151 | alpha_agp_info *agp = alpha_mv.agp_info(); | ||
152 | struct pci_dev *pdev; /* faked */ | ||
153 | struct aper_size_info_fixed *aper_size; | ||
154 | |||
155 | if (!agp) | ||
156 | return -ENODEV; | ||
157 | if (agp->ops->setup(agp)) | ||
158 | return -ENODEV; | ||
159 | |||
160 | /* | ||
161 | * Build the aperture size descriptor | ||
162 | */ | ||
163 | aper_size = alpha_core_agp_sizes; | ||
164 | aper_size->size = agp->aperture.size / (1024 * 1024); | ||
165 | aper_size->num_entries = agp->aperture.size / PAGE_SIZE; | ||
166 | aper_size->page_order = __ffs(aper_size->num_entries / 1024); | ||
167 | |||
168 | /* | ||
169 | * Build a fake pci_dev struct | ||
170 | */ | ||
171 | pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | ||
172 | if (!pdev) | ||
173 | return -ENOMEM; | ||
174 | pdev->vendor = 0xffff; | ||
175 | pdev->device = 0xffff; | ||
176 | pdev->sysdata = agp->hose; | ||
177 | |||
178 | alpha_bridge = agp_alloc_bridge(); | ||
179 | if (!alpha_bridge) | ||
180 | goto fail; | ||
181 | |||
182 | alpha_bridge->driver = &alpha_core_agp_driver; | ||
183 | alpha_bridge->vm_ops = &alpha_core_agp_vm_ops; | ||
184 | alpha_bridge->current_size = aper_size; /* only 1 size */ | ||
185 | alpha_bridge->dev_private_data = agp; | ||
186 | alpha_bridge->dev = pdev; | ||
187 | alpha_bridge->mode = agp->capability.lw; | ||
188 | |||
189 | printk(KERN_INFO PFX "Detected AGP on hose %d\n", agp->hose->index); | ||
190 | return agp_add_bridge(alpha_bridge); | ||
191 | |||
192 | fail: | ||
193 | kfree(pdev); | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | |||
197 | static int __init agp_alpha_core_init(void) | ||
198 | { | ||
199 | if (agp_off) | ||
200 | return -EINVAL; | ||
201 | if (alpha_mv.agp_info) | ||
202 | return alpha_core_agp_setup(); | ||
203 | return -ENODEV; | ||
204 | } | ||
205 | |||
206 | static void __exit agp_alpha_core_cleanup(void) | ||
207 | { | ||
208 | agp_remove_bridge(alpha_bridge); | ||
209 | agp_put_bridge(alpha_bridge); | ||
210 | } | ||
211 | |||
212 | module_init(agp_alpha_core_init); | ||
213 | module_exit(agp_alpha_core_cleanup); | ||
214 | |||
215 | MODULE_AUTHOR("Jeff Wiedemeier <Jeff.Wiedemeier@hp.com>"); | ||
216 | MODULE_LICENSE("GPL and additional rights"); | ||