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/video/sbuslib.c |
Linux-2.6.12-rc2v2.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/video/sbuslib.c')
-rw-r--r-- | drivers/video/sbuslib.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c new file mode 100644 index 000000000000..34f72edba820 --- /dev/null +++ b/drivers/video/sbuslib.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* sbuslib.c: Helper library for SBUS framebuffer drivers. | ||
2 | * | ||
3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/string.h> | ||
9 | #include <linux/fb.h> | ||
10 | #include <linux/mm.h> | ||
11 | |||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/fbio.h> | ||
14 | |||
15 | #include "sbuslib.h" | ||
16 | |||
17 | void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp) | ||
18 | { | ||
19 | memset(var, 0, sizeof(*var)); | ||
20 | |||
21 | var->xres = prom_getintdefault(prom_node, "width", 1152); | ||
22 | var->yres = prom_getintdefault(prom_node, "height", 900); | ||
23 | var->xres_virtual = var->xres; | ||
24 | var->yres_virtual = var->yres; | ||
25 | var->bits_per_pixel = bpp; | ||
26 | } | ||
27 | |||
28 | EXPORT_SYMBOL(sbusfb_fill_var); | ||
29 | |||
30 | static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize) | ||
31 | { | ||
32 | if (size == SBUS_MMAP_EMPTY) return 0; | ||
33 | if (size >= 0) return size; | ||
34 | return fbsize * (-size); | ||
35 | } | ||
36 | |||
37 | int sbusfb_mmap_helper(struct sbus_mmap_map *map, | ||
38 | unsigned long physbase, | ||
39 | unsigned long fbsize, | ||
40 | unsigned long iospace, | ||
41 | struct vm_area_struct *vma) | ||
42 | { | ||
43 | unsigned int size, page, r, map_size; | ||
44 | unsigned long map_offset = 0; | ||
45 | unsigned long off; | ||
46 | int i; | ||
47 | |||
48 | size = vma->vm_end - vma->vm_start; | ||
49 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) | ||
50 | return -EINVAL; | ||
51 | |||
52 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
53 | |||
54 | /* To stop the swapper from even considering these pages */ | ||
55 | vma->vm_flags |= (VM_IO | VM_RESERVED); | ||
56 | |||
57 | /* Each page, see which map applies */ | ||
58 | for (page = 0; page < size; ){ | ||
59 | map_size = 0; | ||
60 | for (i = 0; map[i].size; i++) | ||
61 | if (map[i].voff == off+page) { | ||
62 | map_size = sbusfb_mmapsize(map[i].size, fbsize); | ||
63 | #ifdef __sparc_v9__ | ||
64 | #define POFF_MASK (PAGE_MASK|0x1UL) | ||
65 | #else | ||
66 | #define POFF_MASK (PAGE_MASK) | ||
67 | #endif | ||
68 | map_offset = (physbase + map[i].poff) & POFF_MASK; | ||
69 | break; | ||
70 | } | ||
71 | if (!map_size){ | ||
72 | page += PAGE_SIZE; | ||
73 | continue; | ||
74 | } | ||
75 | if (page + map_size > size) | ||
76 | map_size = size - page; | ||
77 | r = io_remap_pfn_range(vma, | ||
78 | vma->vm_start + page, | ||
79 | MK_IOSPACE_PFN(iospace, | ||
80 | map_offset >> PAGE_SHIFT), | ||
81 | map_size, | ||
82 | vma->vm_page_prot); | ||
83 | if (r) | ||
84 | return -EAGAIN; | ||
85 | page += map_size; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | EXPORT_SYMBOL(sbusfb_mmap_helper); | ||
91 | |||
92 | int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, | ||
93 | struct fb_info *info, | ||
94 | int type, int fb_depth, unsigned long fb_size) | ||
95 | { | ||
96 | switch(cmd) { | ||
97 | case FBIOGTYPE: { | ||
98 | struct fbtype __user *f = (struct fbtype __user *) arg; | ||
99 | |||
100 | if (put_user(type, &f->fb_type) || | ||
101 | __put_user(info->var.yres, &f->fb_height) || | ||
102 | __put_user(info->var.xres, &f->fb_width) || | ||
103 | __put_user(fb_depth, &f->fb_depth) || | ||
104 | __put_user(0, &f->fb_cmsize) || | ||
105 | __put_user(fb_size, &f->fb_cmsize)) | ||
106 | return -EFAULT; | ||
107 | return 0; | ||
108 | } | ||
109 | case FBIOPUTCMAP_SPARC: { | ||
110 | struct fbcmap __user *c = (struct fbcmap __user *) arg; | ||
111 | struct fb_cmap cmap; | ||
112 | u16 red, green, blue; | ||
113 | u8 red8, green8, blue8; | ||
114 | unsigned char __user *ured; | ||
115 | unsigned char __user *ugreen; | ||
116 | unsigned char __user *ublue; | ||
117 | int index, count, i; | ||
118 | |||
119 | if (get_user(index, &c->index) || | ||
120 | __get_user(count, &c->count) || | ||
121 | __get_user(ured, &c->red) || | ||
122 | __get_user(ugreen, &c->green) || | ||
123 | __get_user(ublue, &c->blue)) | ||
124 | return -EFAULT; | ||
125 | |||
126 | cmap.len = 1; | ||
127 | cmap.red = &red; | ||
128 | cmap.green = &green; | ||
129 | cmap.blue = &blue; | ||
130 | cmap.transp = NULL; | ||
131 | for (i = 0; i < count; i++) { | ||
132 | int err; | ||
133 | |||
134 | if (get_user(red8, &ured[i]) || | ||
135 | get_user(green8, &ugreen[i]) || | ||
136 | get_user(blue8, &ublue[i])) | ||
137 | return -EFAULT; | ||
138 | |||
139 | red = red8 << 8; | ||
140 | green = green8 << 8; | ||
141 | blue = blue8 << 8; | ||
142 | |||
143 | cmap.start = index + i; | ||
144 | err = fb_set_cmap(&cmap, info); | ||
145 | if (err) | ||
146 | return err; | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | case FBIOGETCMAP_SPARC: { | ||
151 | struct fbcmap __user *c = (struct fbcmap __user *) arg; | ||
152 | unsigned char __user *ured; | ||
153 | unsigned char __user *ugreen; | ||
154 | unsigned char __user *ublue; | ||
155 | struct fb_cmap *cmap = &info->cmap; | ||
156 | int index, count, i; | ||
157 | u8 red, green, blue; | ||
158 | |||
159 | if (get_user(index, &c->index) || | ||
160 | __get_user(count, &c->count) || | ||
161 | __get_user(ured, &c->red) || | ||
162 | __get_user(ugreen, &c->green) || | ||
163 | __get_user(ublue, &c->blue)) | ||
164 | return -EFAULT; | ||
165 | |||
166 | if (index + count > cmap->len) | ||
167 | return -EINVAL; | ||
168 | |||
169 | for (i = 0; i < count; i++) { | ||
170 | red = cmap->red[index + i] >> 8; | ||
171 | green = cmap->green[index + i] >> 8; | ||
172 | blue = cmap->blue[index + i] >> 8; | ||
173 | if (put_user(red, &ured[i]) || | ||
174 | put_user(green, &ugreen[i]) || | ||
175 | put_user(blue, &ublue[i])) | ||
176 | return -EFAULT; | ||
177 | } | ||
178 | return 0; | ||
179 | } | ||
180 | default: | ||
181 | return -EINVAL; | ||
182 | }; | ||
183 | } | ||
184 | EXPORT_SYMBOL(sbusfb_ioctl_helper); | ||