view.c revision 1.19 1 /* $NetBSD: view.c,v 1.19 2002/09/06 13:18:43 gehenna Exp $ */
2
3 /*
4 * Copyright (c) 1994 Christian E. Hopps
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christian E. Hopps.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* The view major device is a placeholder device. It serves
34 * simply to map the semantics of a graphics dipslay to
35 * the semantics of a character block device. In other
36 * words the graphics system as currently built does not like to be
37 * refered to by open/close/ioctl. This device serves as
38 * a interface to graphics. */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/ioctl.h>
44 #include <sys/file.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47 #include <sys/queue.h>
48 #include <sys/conf.h>
49 #include <sys/poll.h>
50 #include <machine/cpu.h>
51 #include <atari/dev/grfabs_reg.h>
52 #include <atari/dev/viewioctl.h>
53 #include <atari/dev/viewvar.h>
54 #include "view.h"
55
56 static void view_display __P((struct view_softc *));
57 static void view_remove __P((struct view_softc *));
58 static int view_setsize __P((struct view_softc *, struct view_size *));
59 static int view_get_colormap __P((struct view_softc *, colormap_t *));
60 static int view_set_colormap __P((struct view_softc *, colormap_t *));
61
62 struct view_softc views[NVIEW];
63 static int view_inited;
64
65 int view_default_x;
66 int view_default_y;
67 int view_default_width = 640;
68 int view_default_height = 400;
69 int view_default_depth = 1;
70
71 dev_type_open(viewopen);
72 dev_type_close(viewclose);
73 dev_type_ioctl(viewioctl);
74 dev_type_poll(viewpoll);
75 dev_type_mmap(viewmmap);
76
77 const struct cdevsw view_cdevsw = {
78 viewopen, viewclose, nullread, nullwrite, viewioctl,
79 nostop, notty, viewpoll, viewmmap,
80 };
81
82 /*
83 * functions for probeing.
84 */
85 void viewattach __P((int));
86
87 void
88 viewattach(cnt)
89 int cnt;
90 {
91 viewprobe();
92 printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
93 }
94
95 /* this function is called early to set up a display. */
96 int
97 viewprobe()
98 {
99 int i;
100
101 if(view_inited)
102 return(1);
103
104 view_inited = 1;
105
106 for(i=0; i<NVIEW; i++) {
107 views[i].view = NULL;
108 views[i].flags = 0;
109 }
110 return(1);
111 }
112
113
114 /*
115 * Internal functions.
116 */
117
118 static void
119 view_display (vu)
120 struct view_softc *vu;
121 {
122 int s, i;
123
124 if (vu == NULL)
125 return;
126
127 s = spltty();
128
129 /*
130 * mark views that share this monitor as not displaying
131 */
132 for (i = 0; i < NVIEW; i++) {
133 if(views[i].flags & VUF_DISPLAY) {
134 if (vu->view && (vu->view == views[i].view)) {
135 splx(s);
136 return;
137 }
138 if (views[i].view) {
139 grf_save_view(views[i].view);
140 views[i].view->flags &= ~VF_DISPLAY;
141 }
142 views[i].flags &= ~VUF_DISPLAY;
143 }
144 }
145
146 vu->flags |= VUF_ADDED;
147 if (vu->view) {
148 vu->view->display.x = vu->size.x;
149 vu->view->display.y = vu->size.y;
150
151 grf_display_view(vu->view);
152 vu->view->flags |= VF_DISPLAY;
153
154 vu->size.x = vu->view->display.x;
155 vu->size.y = vu->view->display.y;
156 vu->flags |= VUF_DISPLAY;
157 }
158 splx(s);
159 }
160
161 /*
162 * remove a view from our added list if it is marked as displaying
163 * switch to a new display.
164 */
165 static void
166 view_remove(vu)
167 struct view_softc *vu;
168 {
169 int i;
170
171 if ((vu->flags & VUF_ADDED) == 0)
172 return;
173
174 vu->flags &= ~VUF_ADDED;
175 if (vu->flags & VUF_DISPLAY) {
176 for (i = 0; i < NVIEW; i++) {
177 if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
178 view_display(&views[i]);
179 break;
180 }
181 }
182 }
183 vu->flags &= ~VUF_DISPLAY;
184 grf_remove_view(vu->view);
185 }
186
187 static int
188 view_setsize(vu, vs)
189 struct view_softc *vu;
190 struct view_size *vs;
191 {
192 view_t *new, *old;
193 dmode_t *dmode;
194 dimen_t ns;
195 int co, cs;
196
197 co = 0;
198 cs = 0;
199 if (vs->x != vu->size.x || vs->y != vu->size.y)
200 co = 1;
201
202 if (vs->width != vu->size.width || vs->height != vu->size.height ||
203 vs->depth != vu->size.depth)
204 cs = 1;
205
206 if (cs == 0 && co == 0)
207 return(0);
208
209 ns.width = vs->width;
210 ns.height = vs->height;
211
212 if((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
213 /*
214 * If we can't do better, leave it
215 */
216 if(dmode == vu->view->mode)
217 return(0);
218 }
219 new = grf_alloc_view(dmode, &ns, vs->depth);
220 if (new == NULL)
221 return(ENOMEM);
222
223 old = vu->view;
224 vu->view = new;
225 vu->size.x = new->display.x;
226 vu->size.y = new->display.y;
227 vu->size.width = new->display.width;
228 vu->size.height = new->display.height;
229 vu->size.depth = new->bitmap->depth;
230
231 /*
232 * we need a custom remove here to avoid letting
233 * another view display mark as not added or displayed
234 */
235 if (vu->flags & VUF_DISPLAY) {
236 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
237 view_display(vu);
238 }
239 grf_free_view(old);
240 return(0);
241 }
242
243 static int
244 view_get_colormap (vu, ucm)
245 struct view_softc *vu;
246 colormap_t *ucm;
247 {
248 int error;
249 long *cme;
250 long *uep;
251
252 if(ucm->size > MAX_CENTRIES)
253 return(EINVAL);
254
255 /* add one incase of zero, ick. */
256 cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_IOCTLOPS,M_WAITOK);
257 if (cme == NULL)
258 return(ENOMEM);
259
260 error = 0;
261 uep = ucm->entry;
262 ucm->entry = cme; /* set entry to out alloc. */
263 if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
264 error = EINVAL;
265 else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
266 ucm->entry = uep; /* set entry back to users. */
267 free(cme, M_IOCTLOPS);
268 return(error);
269 }
270
271 static int
272 view_set_colormap(vu, ucm)
273 struct view_softc *vu;
274 colormap_t *ucm;
275 {
276 colormap_t *cm;
277 int error = 0;
278
279 if(ucm->size > MAX_CENTRIES)
280 return(EINVAL);
281
282 cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_IOCTLOPS,
283 M_WAITOK);
284 if(cm == NULL)
285 return(ENOMEM);
286
287 bcopy(ucm, cm, sizeof(colormap_t));
288 cm->entry = (long *)&cm[1]; /* table directly after. */
289 if (((error =
290 copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
291 && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
292 error = EINVAL;
293 free(cm, M_IOCTLOPS);
294 return(error);
295 }
296
297 /*
298 * functions made available by conf.c
299 */
300
301 /*ARGSUSED*/
302 int
303 viewopen(dev, flags, mode, p)
304 dev_t dev;
305 int flags;
306 int mode;
307 struct proc *p;
308 {
309 dimen_t size;
310 struct view_softc *vu;
311
312 vu = &views[minor(dev)];
313
314 if(minor(dev) >= NVIEW)
315 return(EXDEV);
316 if(vu->flags & VUF_OPEN)
317 return(EBUSY);
318
319 vu->size.x = view_default_x;
320 vu->size.y = view_default_y;
321 size.width = vu->size.width = view_default_width;
322 size.height = vu->size.height = view_default_height;
323 vu->size.depth = view_default_depth;
324 vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
325 if (vu->view == NULL)
326 return(ENOMEM);
327
328 vu->size.x = vu->view->display.x;
329 vu->size.y = vu->view->display.y;
330 vu->size.width = vu->view->display.width;
331 vu->size.height = vu->view->display.height;
332 vu->size.depth = vu->view->bitmap->depth;
333 vu->flags |= VUF_OPEN;
334 return(0);
335 }
336
337 /*ARGSUSED*/
338 int
339 viewclose (dev, flags, mode, p)
340 dev_t dev;
341 int flags;
342 int mode;
343 struct proc *p;
344 {
345 struct view_softc *vu;
346
347 vu = &views[minor(dev)];
348
349 if ((vu->flags & VUF_OPEN) == 0)
350 return (0); /* XXX not open? */
351 view_remove (vu);
352 grf_free_view (vu->view);
353 vu->flags = 0;
354 vu->view = NULL;
355 return (0);
356 }
357
358
359 /*ARGSUSED*/
360 int
361 viewioctl (dev, cmd, data, flag, p)
362 dev_t dev;
363 u_long cmd;
364 caddr_t data;
365 int flag;
366 struct proc *p;
367 {
368 struct view_softc *vu;
369 bmap_t *bm;
370 int error;
371
372 vu = &views[minor(dev)];
373 error = 0;
374
375 switch (cmd) {
376 case VIOCDISPLAY:
377 view_display(vu);
378 break;
379 case VIOCREMOVE:
380 view_remove(vu);
381 break;
382 case VIOCGSIZE:
383 bcopy(&vu->size, data, sizeof (struct view_size));
384 break;
385 case VIOCSSIZE:
386 error = view_setsize(vu, (struct view_size *)data);
387 break;
388 case VIOCGBMAP:
389 bm = (bmap_t *)data;
390 bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
391 if (p != NOPROC) {
392 bm->plane = NULL;
393 bm->hw_address = NULL;
394 bm->regs = NULL;
395 bm->hw_regs = NULL;
396 }
397 break;
398 case VIOCGCMAP:
399 error = view_get_colormap(vu, (colormap_t *)data);
400 break;
401 case VIOCSCMAP:
402 error = view_set_colormap(vu, (colormap_t *)data);
403 break;
404 default:
405 error = EPASSTHROUGH;
406 break;
407 }
408 return(error);
409 }
410
411 /*ARGSUSED*/
412 paddr_t
413 viewmmap(dev, off, prot)
414 dev_t dev;
415 off_t off;
416 int prot;
417 {
418 struct view_softc *vu;
419 bmap_t *bm;
420 u_char *bmd_start;
421 u_long bmd_lin, bmd_vga;
422
423 vu = &views[minor(dev)];
424 bm = vu->view->bitmap;
425 bmd_start = bm->hw_address;
426 bmd_lin = bm->lin_base;
427 bmd_vga = bm->vga_base;
428
429 /*
430 * control registers
431 */
432 if (off >= 0 && off < bm->reg_size)
433 return(((paddr_t)bm->hw_regs + off) >> PGSHIFT);
434
435 /*
436 * VGA memory
437 */
438 if (off >= bmd_vga && off < (bmd_vga + bm->vga_mappable))
439 return(((paddr_t)bm->vga_address - bmd_vga + off) >> PGSHIFT);
440
441 /*
442 * frame buffer
443 */
444 if (off >= bmd_lin && off < (bmd_lin + bm->phys_mappable))
445 return(((paddr_t)bmd_start - bmd_lin + off) >> PGSHIFT);
446
447 return(-1);
448 }
449
450 /*ARGSUSED*/
451 int
452 viewpoll(dev, events, p)
453 dev_t dev;
454 int events;
455 struct proc *p;
456 {
457 int revents = 0;
458
459 if (events & (POLLOUT | POLLWRNORM))
460 revents |= events & (POLLOUT | POLLWRNORM);
461 return (revents);
462 }
463
464 view_t *
465 viewview(dev)
466 dev_t dev;
467 {
468 return(views[minor(dev)].view);
469 }
470