~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/sgi/char/graphics.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $
  2  *
  3  * gfx.c: support for SGI's /dev/graphics, /dev/opengl
  4  *
  5  * Author: Miguel de Icaza (miguel@nuclecu.unam.mx)
  6  *         Ralf Baechle (ralf@gnu.org)
  7  *         Ulf Carlsson (ulfc@bun.falkenberg.se)
  8  *
  9  * On IRIX, /dev/graphics is [10, 146]
 10  *          /dev/opengl   is [10, 147]
 11  *
 12  * From a mail with Mark J. Kilgard, /dev/opengl and /dev/graphics are
 13  * the same thing, the use of /dev/graphics seems deprecated though.
 14  *
 15  * The reason that the original SGI programmer had to use only one
 16  * device for all the graphic cards on the system will remain a
 17  * mistery for the rest of our lives.  Why some ioctls take a board
 18  * number and some others not?  Mistery.  Why do they map the hardware
 19  * registers into the user address space with an ioctl instead of
 20  * mmap?  Mistery too.  Why they did not use the standard way of
 21  * making ioctl constants and instead sticked a random constant?
 22  * Mistery too.
 23  *
 24  * We implement those misterious things, and tried not to think about
 25  * the reasons behind them.
 26  */
 27 #include <linux/kernel.h>
 28 #include <linux/fs.h>
 29 #include <linux/init.h>
 30 #include <linux/miscdevice.h>
 31 #include <linux/sched.h>
 32 #include <linux/mm.h>
 33 #include <linux/mman.h>
 34 #include <linux/malloc.h>
 35 #include <linux/module.h>
 36 #include <linux/smp_lock.h>
 37 #include <asm/uaccess.h>
 38 #include "gconsole.h"
 39 #include "graphics.h"
 40 #include "usema.h"
 41 #include <asm/gfx.h>
 42 #include <asm/rrm.h>
 43 #include <asm/page.h>
 44 #include <asm/pgtable.h>
 45 #include <video/newport.h>
 46 
 47 #define DEBUG
 48 
 49 /* The boards */
 50 extern struct graphics_ops *newport_probe (int, const char **);
 51 
 52 static struct graphics_ops cards [MAXCARDS];
 53 static int boards;
 54 
 55 #define GRAPHICS_CARD(inode) 0
 56 
 57 /*
 58 void enable_gconsole(void) {};
 59 void disable_gconsole(void) {};
 60 */
 61 
 62 
 63 int
 64 sgi_graphics_open (struct inode *inode, struct file *file)
 65 {
 66         struct newport_regs *nregs =
 67                 (struct newport_regs *) KSEG1ADDR(cards[0].g_regs);
 68 
 69         newport_wait();
 70         nregs->set.wrmask = 0xffffffff;
 71         nregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
 72                              NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
 73                              NPORT_DMODE0_STOPY);
 74         nregs->set.colori = 1;
 75         nregs->set.xystarti = (0 << 16) | 0;
 76         nregs->go.xyendi = (1280 << 16) | 1024;
 77 
 78         return 0;
 79 }
 80 
 81 int
 82 sgi_graphics_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 83 {
 84         unsigned int board;
 85         unsigned int devnum = GRAPHICS_CARD (inode->i_rdev);
 86         int i;
 87 
 88         if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT))
 89                 return rrm_command (cmd-RRM_BASE, (void *) arg);
 90 
 91         switch (cmd){
 92         case GFX_GETNUM_BOARDS:
 93                 return boards;
 94 
 95         case GFX_GETBOARD_INFO: {
 96                 struct gfx_getboardinfo_args *bia = (void *) arg;
 97                 void   *dest_buf;
 98                 int    max_len;
 99                 
100                 i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct gfx_getboardinfo_args));
101                 if (i) return i;
102                 
103                 if (__get_user (board,    &bia->board) ||
104                     __get_user (dest_buf, &bia->buf) ||
105                     __get_user (max_len,  &bia->len))
106                         return -EFAULT;
107 
108                 if (board >= boards)
109                         return -EINVAL;
110                 if (max_len < sizeof (struct gfx_getboardinfo_args))
111                         return -EINVAL;
112                 if (max_len > cards [board].g_board_info_len)
113                         max_len = cards [boards].g_board_info_len;
114                 i = verify_area (VERIFY_WRITE, dest_buf, max_len);
115                 if (i) return i;
116                 if (copy_to_user (dest_buf, cards [board].g_board_info, max_len))
117                         return -EFAULT;
118                 return max_len;
119         }
120 
121         case GFX_ATTACH_BOARD: {
122                 struct gfx_attach_board_args *att = (void *) arg;
123                 void *vaddr;
124                 int  r;
125 
126                 i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct gfx_attach_board_args));
127                 if (i) return i;
128 
129                 if (__get_user (board, &att->board) ||
130                     __get_user (vaddr, &att->vaddr))
131                         return -EFAULT;
132 
133                 /* Ok for now we are assuming /dev/graphicsN -> head N even
134                  * if the ioctl api suggests that this is not quite the case.
135                  *
136                  * Otherwise we fail, we use this assumption in the mmap code
137                  * below to find our board information.
138                  */
139                 if (board != devnum){
140                         printk ("Parameter board does not match the current board\n");
141                         return -EINVAL;
142                 }
143 
144                 if (board >= boards)
145                         return -EINVAL;
146 
147                 /* If it is the first opening it, then make it the board owner */
148                 if (!cards [board].g_owner)
149                         cards [board].g_owner = current;
150 
151                 /*
152                  * Ok, we now call mmap on this file, which will end up calling
153                  * sgi_graphics_mmap
154                  */
155                 disable_gconsole ();
156                 down(&current->mm->mmap_sem);
157                 r = do_mmap (file, (unsigned long)vaddr,
158                              cards[board].g_regs_size, PROT_READ|PROT_WRITE,
159                              MAP_FIXED|MAP_PRIVATE, 0);
160                 up(&current->mm->mmap_sem);
161                 if (r)
162                         return r;
163         }
164 
165         /* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD,
166          * GFX_MAPALL is not even used by IRIX X server
167          */
168         case GFX_MAPALL:
169                 return 0;
170 
171         case GFX_LABEL:
172                 return 0;
173 
174                 /* Version check
175                  * for my IRIX 6.2 X server, this is what the kernel returns
176                  */
177         case 1:
178                 return 3;
179 
180         /* Xsgi does not use this one, I assume minor is the board being queried */
181         case GFX_IS_MANAGED:
182                 if (devnum > boards)
183                         return -EINVAL;
184                 return (cards [devnum].g_owner != 0);
185 
186         default:
187                 if (cards [devnum].g_ioctl)
188                         return (*cards [devnum].g_ioctl)(devnum, cmd, arg);
189                 
190         }
191         return -EINVAL;
192 }
193 
194 int
195 sgi_graphics_close (struct inode *inode, struct file *file)
196 {
197         int board = GRAPHICS_CARD (inode->i_rdev);
198 
199         /* Tell the rendering manager that one client is going away */
200         lock_kernel();
201         rrm_close (inode, file);
202 
203         /* Was this file handle from the board owner?, clear it */
204         if (current == cards [board].g_owner){
205                 cards [board].g_owner = 0;
206                 if (cards [board].g_reset_console)
207                         (*cards [board].g_reset_console)();
208                 enable_gconsole ();
209         }
210         unlock_kernel();
211         return 0;
212 }
213 
214 /* 
215  * This is the core of the direct rendering engine.
216  */
217 
218 unsigned long
219 sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int
220                      no_share)
221 {
222         pgd_t *pgd; pmd_t *pmd; pte_t *pte; 
223         int board = GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev);
224 
225         unsigned long virt_add, phys_add;
226 
227 #ifdef DEBUG
228         printk ("Got a page fault for board %d address=%lx guser=%lx\n", board,
229                 address, (unsigned long) cards[board].g_user);
230 #endif
231         
232         /* Figure out if another process has this mapped, and revoke the mapping
233          * in that case. */
234         if (cards[board].g_user && cards[board].g_user != current) {
235                 /* FIXME: save graphics context here, dump it to rendering
236                  * node? */
237 
238                 remove_mapping(cards[board].g_user, vma->vm_start, vma->vm_end);
239         }
240 
241         cards [board].g_user = current;
242 
243         /* Map the physical address of the newport registers into the address
244          * space of this process */
245 
246         virt_add = address & PAGE_MASK;
247         phys_add = cards[board].g_regs + virt_add - vma->vm_start;
248         remap_page_range(virt_add, phys_add, PAGE_SIZE, vma->vm_page_prot);
249 
250         pgd = pgd_offset(current->mm, address);
251         pmd = pmd_offset(pgd, address);
252         pte = pte_offset(pmd, address);
253         printk("page: %08lx\n", pte_page(*pte));
254         return pte_page(*pte);
255 }
256 
257 /*
258  * We convert a GFX ioctl for mapping hardware registers, in a nice sys_mmap
259  * call, which takes care of everything that must be taken care of.
260  *
261  */
262 
263 static struct vm_operations_struct graphics_mmap = {
264         nopage: sgi_graphics_nopage,    /* our magic no-page fault handler */
265 };
266         
267 int
268 sgi_graphics_mmap (struct file *file, struct vm_area_struct *vma)
269 {
270         uint size;
271 
272         size = vma->vm_end - vma->vm_start;
273 
274         /* 1. Set our special graphic virtualizer  */
275         vma->vm_ops = &graphics_mmap;
276 
277         /* 2. Set the special tlb permission bits */
278         vma->vm_page_prot = PAGE_USERIO;
279 
280         /* final setup */
281         vma->vm_file = file;
282         return 0;
283 }
284 
285 #if 0
286 /* Do any post card-detection setup on graphics_ops */
287 static void
288 graphics_ops_post_init (int slot)
289 {
290         /* There is no owner for the card initially */
291         cards [slot].g_owner = (struct task_struct *) 0;
292         cards [slot].g_user  = (struct task_struct *) 0;
293 }
294 #endif
295 
296 struct file_operations sgi_graphics_fops = {
297         ioctl:          sgi_graphics_ioctl,
298         mmap:           sgi_graphics_mmap,
299         open:           sgi_graphics_open,
300         release:        sgi_graphics_close,
301 };
302 
303 /* /dev/graphics */
304 static struct miscdevice dev_graphics = {
305         SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops
306 };
307 
308 /* /dev/opengl */
309 static struct miscdevice dev_opengl = {
310         SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops
311 };
312 
313 /* This is called later from the misc-init routine */
314 void __init gfx_register (void)
315 {
316         misc_register (&dev_graphics);
317         misc_register (&dev_opengl);
318 }
319 
320 void __init gfx_init (const char **name)
321 {
322 #if 0
323         struct console_ops *console;
324         struct graphics_ops *g;
325 #endif
326 
327         printk ("GFX INIT: ");
328         shmiq_init ();
329         usema_init ();
330 
331         boards++;
332 
333 #if 0
334         if ((g = newport_probe (boards, name)) != 0) {
335                 cards [boards] = *g;
336                 graphics_ops_post_init (boards);
337                 boards++;
338                 console = 0;
339         }
340         /* Add more graphic drivers here */
341         /* Keep passing console around */
342 #endif
343 
344         if (boards > MAXCARDS)
345                 printk (KERN_WARNING "Too many cards found on the system\n");
346 }
347 
348 #ifdef MODULE
349 int init_module(void) {
350         static int initiated = 0;
351 
352         printk("SGI Newport Graphics version %i.%i.%i\n",42,54,69);
353 
354         if (!initiated++) {
355                 shmiq_init();
356                 usema_init();
357                 printk("Adding first board\n");
358                 boards++;
359                 cards[0].g_regs = 0x1f0f0000;
360                 cards[0].g_regs_size = sizeof (struct newport_regs);
361         }
362 
363         printk("Boards: %d\n", boards);
364 
365         misc_register (&dev_graphics);
366         misc_register (&dev_opengl);
367 
368         return 0;
369 }
370 
371 void cleanup_module(void) {
372         printk("Shutting down SGI Newport Graphics\n");
373 
374         misc_deregister (&dev_graphics);
375         misc_deregister (&dev_opengl);
376 }
377 #endif
378 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.