view.c revision 1.33 1 /* $NetBSD: view.c,v 1.33 2014/03/16 05:20:23 dholland 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/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: view.c,v 1.33 2014/03/16 05:20:23 dholland Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/ioctl.h>
47 #include <sys/file.h>
48 #include <sys/device.h>
49 #include <sys/malloc.h>
50 #include <sys/queue.h>
51 #include <sys/conf.h>
52 #include <machine/cpu.h>
53 #include <atari/dev/grfabs_reg.h>
54 #include <atari/dev/viewioctl.h>
55 #include <atari/dev/viewvar.h>
56 #include "view.h"
57
58 static void view_display(struct view_softc *);
59 static void view_remove(struct view_softc *);
60 static int view_setsize(struct view_softc *, struct view_size *);
61 static int view_get_colormap(struct view_softc *, colormap_t *);
62 static int view_set_colormap(struct view_softc *, colormap_t *);
63
64 struct view_softc views[NVIEW];
65 static int view_inited;
66
67 int view_default_x;
68 int view_default_y;
69 int view_default_width = 640;
70 int view_default_height = 400;
71 int view_default_depth = 1;
72
73 dev_type_open(viewopen);
74 dev_type_close(viewclose);
75 dev_type_ioctl(viewioctl);
76 dev_type_mmap(viewmmap);
77
78 const struct cdevsw view_cdevsw = {
79 .d_open = viewopen,
80 .d_close = viewclose,
81 .d_read = nullread,
82 .d_write = nullwrite,
83 .d_ioctl = viewioctl,
84 .d_stop = nostop,
85 .d_tty = notty,
86 .d_poll = nopoll,
87 .d_mmap = viewmmap,
88 .d_kqfilter = nokqfilter,
89 .d_flag = 0
90 };
91
92 /*
93 * functions for probeing.
94 */
95 void viewattach(int);
96
97 void
98 viewattach(int cnt)
99 {
100 viewprobe();
101 printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
102 }
103
104 /* this function is called early to set up a display. */
105 int
106 viewprobe(void)
107 {
108 int i;
109
110 if (view_inited)
111 return 1;
112
113 view_inited = 1;
114
115 for (i = 0; i < NVIEW; i++) {
116 views[i].view = NULL;
117 views[i].flags = 0;
118 }
119 return 1;
120 }
121
122
123 /*
124 * Internal functions.
125 */
126
127 static void
128 view_display (struct view_softc *vu)
129 {
130 int s, i;
131
132 if (vu == NULL)
133 return;
134
135 s = spltty();
136
137 /*
138 * mark views that share this monitor as not displaying
139 */
140 for (i = 0; i < NVIEW; i++) {
141 if (views[i].flags & VUF_DISPLAY) {
142 if (vu->view && (vu->view == views[i].view)) {
143 splx(s);
144 return;
145 }
146 if (views[i].view) {
147 grf_save_view(views[i].view);
148 views[i].view->flags &= ~VF_DISPLAY;
149 }
150 views[i].flags &= ~VUF_DISPLAY;
151 }
152 }
153
154 vu->flags |= VUF_ADDED;
155 if (vu->view) {
156 vu->view->display.x = vu->size.x;
157 vu->view->display.y = vu->size.y;
158
159 grf_display_view(vu->view);
160 vu->view->flags |= VF_DISPLAY;
161
162 vu->size.x = vu->view->display.x;
163 vu->size.y = vu->view->display.y;
164 vu->flags |= VUF_DISPLAY;
165 }
166 splx(s);
167 }
168
169 /*
170 * remove a view from our added list if it is marked as displaying
171 * switch to a new display.
172 */
173 static void
174 view_remove(struct view_softc *vu)
175 {
176 int i;
177
178 if ((vu->flags & VUF_ADDED) == 0)
179 return;
180
181 vu->flags &= ~VUF_ADDED;
182 if (vu->flags & VUF_DISPLAY) {
183 for (i = 0; i < NVIEW; i++) {
184 if ((views[i].flags & VUF_ADDED) && &views[i] != vu) {
185 view_display(&views[i]);
186 break;
187 }
188 }
189 }
190 vu->flags &= ~VUF_DISPLAY;
191 grf_remove_view(vu->view);
192 }
193
194 static int
195 view_setsize(struct view_softc *vu, struct view_size *vs)
196 {
197 view_t *new, *old;
198 dmode_t *dmode;
199 dimen_t ns;
200 int co, cs;
201
202 co = 0;
203 cs = 0;
204 if (vs->x != vu->size.x || vs->y != vu->size.y)
205 co = 1;
206
207 if (vs->width != vu->size.width || vs->height != vu->size.height ||
208 vs->depth != vu->size.depth)
209 cs = 1;
210
211 if (cs == 0 && co == 0)
212 return 0;
213
214 ns.width = vs->width;
215 ns.height = vs->height;
216
217 if ((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
218 /*
219 * If we can't do better, leave it
220 */
221 if (dmode == vu->view->mode)
222 return 0;
223 }
224 new = grf_alloc_view(dmode, &ns, vs->depth);
225 if (new == NULL)
226 return ENOMEM;
227
228 old = vu->view;
229 vu->view = new;
230 vu->size.x = new->display.x;
231 vu->size.y = new->display.y;
232 vu->size.width = new->display.width;
233 vu->size.height = new->display.height;
234 vu->size.depth = new->bitmap->depth;
235
236 /*
237 * we need a custom remove here to avoid letting
238 * another view display mark as not added or displayed
239 */
240 if (vu->flags & VUF_DISPLAY) {
241 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
242 view_display(vu);
243 }
244 grf_free_view(old);
245 return 0;
246 }
247
248 static int
249 view_get_colormap (struct view_softc *vu, colormap_t *ucm)
250 {
251 int error;
252 long *cme;
253 long *uep;
254
255 if (ucm->size > MAX_CENTRIES)
256 return EINVAL;
257
258 /* add one incase of zero, ick. */
259 cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_TEMP,M_WAITOK);
260 if (cme == NULL)
261 return ENOMEM;
262
263 error = 0;
264 uep = ucm->entry;
265 ucm->entry = cme; /* set entry to out alloc. */
266 if (vu->view == NULL || grf_get_colormap(vu->view, ucm))
267 error = EINVAL;
268 else
269 error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
270 ucm->entry = uep; /* set entry back to users. */
271 free(cme, M_TEMP);
272 return error;
273 }
274
275 static int
276 view_set_colormap(struct view_softc *vu, colormap_t *ucm)
277 {
278 colormap_t *cm;
279 int error = 0;
280
281 if (ucm->size > MAX_CENTRIES)
282 return EINVAL;
283
284 cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm),
285 M_TEMP, M_WAITOK);
286 if (cm == NULL)
287 return ENOMEM;
288
289 memcpy(cm, ucm, sizeof(colormap_t));
290 cm->entry = (long *)&cm[1]; /* table directly after. */
291 if (((error =
292 copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
293 && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
294 error = EINVAL;
295 free(cm, M_TEMP);
296 return error;
297 }
298
299 /*
300 * functions made available by conf.c
301 */
302
303 /*ARGSUSED*/
304 int
305 viewopen(dev_t dev, int flags, int mode, struct lwp *l)
306 {
307 dimen_t size;
308 struct view_softc *vu;
309
310 vu = &views[minor(dev)];
311
312 if (minor(dev) >= NVIEW)
313 return EXDEV;
314 if (vu->flags & VUF_OPEN)
315 return EBUSY;
316
317 vu->size.x = view_default_x;
318 vu->size.y = view_default_y;
319 size.width = vu->size.width = view_default_width;
320 size.height = vu->size.height = view_default_height;
321 vu->size.depth = view_default_depth;
322 vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
323 if (vu->view == NULL)
324 return ENOMEM;
325
326 vu->size.x = vu->view->display.x;
327 vu->size.y = vu->view->display.y;
328 vu->size.width = vu->view->display.width;
329 vu->size.height = vu->view->display.height;
330 vu->size.depth = vu->view->bitmap->depth;
331 vu->flags |= VUF_OPEN;
332 return 0;
333 }
334
335 /*ARGSUSED*/
336 int
337 viewclose (dev_t dev, int flags, int mode, struct lwp *l)
338 {
339 struct view_softc *vu;
340
341 vu = &views[minor(dev)];
342
343 if ((vu->flags & VUF_OPEN) == 0)
344 return 0; /* XXX not open? */
345 view_remove (vu);
346 grf_free_view (vu->view);
347 vu->flags = 0;
348 vu->view = NULL;
349 return 0;
350 }
351
352
353 /*ARGSUSED*/
354 int
355 viewioctl (dev_t dev, u_long cmd, void * data, int flag, struct lwp *l)
356 {
357 struct view_softc *vu;
358 bmap_t *bm;
359 int error;
360
361 vu = &views[minor(dev)];
362 error = 0;
363
364 switch (cmd) {
365 case VIOCDISPLAY:
366 view_display(vu);
367 break;
368 case VIOCREMOVE:
369 view_remove(vu);
370 break;
371 case VIOCGSIZE:
372 memcpy(data, &vu->size, sizeof (struct view_size));
373 break;
374 case VIOCSSIZE:
375 error = view_setsize(vu, (struct view_size *)data);
376 break;
377 case VIOCGBMAP:
378 bm = (bmap_t *)data;
379 memcpy(bm, vu->view->bitmap, sizeof(bmap_t));
380 if (l != NOLWP) {
381 bm->plane = NULL;
382 bm->hw_address = NULL;
383 bm->regs = NULL;
384 bm->hw_regs = NULL;
385 }
386 break;
387 case VIOCGCMAP:
388 error = view_get_colormap(vu, (colormap_t *)data);
389 break;
390 case VIOCSCMAP:
391 error = view_set_colormap(vu, (colormap_t *)data);
392 break;
393 default:
394 error = EPASSTHROUGH;
395 break;
396 }
397 return error;
398 }
399
400 /*ARGSUSED*/
401 paddr_t
402 viewmmap(dev_t dev, off_t off, int prot)
403 {
404 struct view_softc *vu;
405 bmap_t *bm;
406 u_char *bmd_start;
407 u_long bmd_lin, bmd_vga;
408
409 vu = &views[minor(dev)];
410 bm = vu->view->bitmap;
411 bmd_start = bm->hw_address;
412 bmd_lin = bm->lin_base;
413 bmd_vga = bm->vga_base;
414
415 /*
416 * control registers
417 */
418 if (off >= 0 && off < bm->reg_size)
419 return ((paddr_t)bm->hw_regs + off) >> PGSHIFT;
420
421 /*
422 * VGA memory
423 */
424 if (off >= bmd_vga && off < (bmd_vga + bm->vga_mappable))
425 return ((paddr_t)bm->vga_address - bmd_vga + off) >> PGSHIFT;
426
427 /*
428 * frame buffer
429 */
430 if (off >= bmd_lin && off < (bmd_lin + bm->phys_mappable))
431 return ((paddr_t)bmd_start - bmd_lin + off) >> PGSHIFT;
432
433 return -1;
434 }
435
436 view_t *
437 viewview(dev_t dev)
438 {
439
440 return views[minor(dev)].view;
441 }
442