|
|
1.1 root 1: /*
2: * Copyright (c) 1988 University of Utah.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * This code is derived from software contributed to Berkeley by
7: * the Systems Programming Group of the University of Utah Computer
8: * Science Department.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
38: * from: Utah $Hdr: grf.c 1.31 91/01/21$
39: *
40: * @(#)grf.c 7.8 (Berkeley) 5/7/91
41: */
42:
43: /*
44: * Graphics display driver for the AMIGA
45: * This is the hardware-independent portion of the driver.
46: * Hardware access is through the grfdev routines below.
47: */
48:
49: #include "grf.h"
50: #if NGRF > 0
51:
52: #include "param.h"
53: #include "proc.h"
54: #include "ioctl.h"
55: #include "file.h"
56: #include "malloc.h"
57:
58: #include "device.h"
59: #include "grfioctl.h"
60: #include "grfvar.h"
61:
62: #include "machine/cpu.h"
63:
64: #include "vm/vm.h"
65: #include "vm/vm_kern.h"
66: #include "vm/vm_page.h"
67: #include "vm/vm_pager.h"
68:
69: #include "specdev.h"
70: #include "vnode.h"
71: #include "mman.h"
72:
73: #include "ite.h"
74: #if NITE == 0
75: #define iteon(u,f)
76: #define iteoff(u,f)
77: #endif
78:
79: int grfprobe();
80: int cc_init(), cc_mode();
81: int tg_init(), tg_mode();
82:
83: struct grfdev grfdev[] = {
84: MANUF_BUILTIN, PROD_BUILTIN_DISPLAY,
85: cc_init, cc_mode, "custom chips",
86: MANUF_UNILOWELL, PROD_UNILOWELL_A2410,
87: tg_init, tg_mode, "A2410 TIGA board",
88: };
89: int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]);
90:
91: struct driver grfdriver = { grfprobe, "grf" };
92: struct grf_softc grf_softc[NGRF];
93:
94: #ifdef DEBUG
95: int grfdebug = 0;
96: #define GDB_DEVNO 0x01
97: #define GDB_MMAP 0x02
98: #define GDB_IOMAP 0x04
99: #define GDB_LOCK 0x08
100: #endif
101:
102: /*
103: * XXX: called from ite console init routine.
104: * Does just what configure will do later but without printing anything.
105: */
106: grfconfig()
107: {
108: register caddr_t addr;
109: register struct amiga_hw *hw;
110: register struct amiga_device *ad, *nad;
111:
112: for (hw = sc_table; hw->hw_type; hw++) {
113: if (!HW_ISDEV(hw, D_BITMAP))
114: continue;
115: /*
116: * Found one, now match up with a logical unit number
117: */
118: nad = NULL;
119: addr = hw->hw_kva;
120: for (ad = amiga_dinit; ad->amiga_driver; ad++) {
121: if (ad->amiga_driver != &grfdriver || ad->amiga_alive)
122: continue;
123: /*
124: * Wildcarded. If first, remember as possible match.
125: */
126: if (ad->amiga_addr == NULL) {
127: if (nad == NULL)
128: nad = ad;
129: continue;
130: }
131: /*
132: * Not wildcarded.
133: * If exact match done searching, else keep looking.
134: */
135: if (((hw->hw_manufacturer << 16) | hw->hw_product)
136: == ad->amiga_addr) {
137: nad = ad;
138: break;
139: }
140: }
141: /*
142: * Found a match, initialize
143: */
144: if (nad && grfinit (nad))
145: nad->amiga_addr = addr;
146: }
147: }
148:
149: /*
150: * Normal init routine called by configure() code
151: */
152: grfprobe(ad)
153: struct amiga_device *ad;
154: {
155: struct grf_softc *gp = &grf_softc[ad->amiga_unit];
156:
157: if ((gp->g_flags & GF_ALIVE) == 0 &&
158: !grfinit (ad))
159: return(0);
160: printf("grf%d: %d x %d ", ad->amiga_unit,
161: gp->g_display.gd_dwidth, gp->g_display.gd_dheight);
162: if (gp->g_display.gd_colors == 2)
163: printf("monochrome");
164: else
165: printf("%d color", gp->g_display.gd_colors);
166: printf(" %s display\n", grfdev[gp->g_type].gd_desc);
167: return(1);
168: }
169:
170: grfinit(ad)
171: struct amiga_device *ad;
172: {
173: struct grf_softc *gp = &grf_softc[ad->amiga_unit];
174: register struct grfdev *gd;
175:
176: for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++)
177: if (((gd->gd_manuf << 16) | gd->gd_prod) == ad->amiga_addr)
178: break;
179:
180: if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, ad)) {
181: gp->g_type = gd - grfdev;
182: gp->g_flags = GF_ALIVE;
183: return(1);
184: }
185: return(0);
186: }
187:
188: /*ARGSUSED*/
189: grfopen(dev, flags)
190: dev_t dev;
191: {
192: int unit = GRFUNIT(dev);
193: register struct grf_softc *gp = &grf_softc[unit];
194: int error = 0;
195:
196: if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0)
197: return(ENXIO);
198: if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
199: return(EBUSY);
200: /*
201: * First open.
202: * XXX: always put in graphics mode.
203: */
204: error = 0;
205: if ((gp->g_flags & GF_OPEN) == 0) {
206: gp->g_flags |= GF_OPEN;
207: error = grfon(dev);
208: }
209: return(error);
210: }
211:
212: /*ARGSUSED*/
213: grfclose(dev, flags)
214: dev_t dev;
215: {
216: register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
217:
218: (void) grfoff(dev);
219: (void) grfunlock(gp);
220: gp->g_flags &= GF_ALIVE;
221: return(0);
222: }
223:
224: /*ARGSUSED*/
225: grfioctl(dev, cmd, data, flag, p)
226: dev_t dev;
227: caddr_t data;
228: struct proc *p;
229: {
230: register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
231: int error;
232:
233: error = 0;
234: switch (cmd) {
235:
236: case GRFIOCGINFO:
237: bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
238: break;
239:
240: case GRFIOCON:
241: error = grfon(dev);
242: break;
243:
244: case GRFIOCOFF:
245: error = grfoff(dev);
246: break;
247:
248: case GRFIOCMAP:
249: error = grfmmap(dev, (caddr_t *)data, p);
250: break;
251:
252: case GRFIOCUNMAP:
253: error = grfunmmap(dev, *(caddr_t *)data, p);
254: break;
255:
256: case GRFIOCSINFO:
257: error = grfsinfo (dev, (struct grfdyninfo *) data);
258: break;
259:
260: default:
261: error = EINVAL;
262: break;
263:
264: }
265: return(error);
266: }
267:
268: /*ARGSUSED*/
269: grfselect(dev, rw)
270: dev_t dev;
271: {
272: if (rw == FREAD)
273: return(0);
274: return(1);
275: }
276:
277: grflock(gp, block)
278: register struct grf_softc *gp;
279: int block;
280: {
281: struct proc *p = curproc; /* XXX */
282: int error;
283: extern char devioc[];
284:
285: #ifdef DEBUG
286: if (grfdebug & GDB_LOCK)
287: printf("grflock(%d): dev %x flags %x lockpid %x\n",
288: p->p_pid, gp-grf_softc, gp->g_flags,
289: gp->g_lockp ? gp->g_lockp->p_pid : -1);
290: #endif
291: if (gp->g_lockp) {
292: if (gp->g_lockp == p)
293: return(EBUSY);
294: if (!block)
295: return(EAGAIN);
296: do {
297: gp->g_flags |= GF_WANTED;
298: if (error = tsleep((caddr_t)&gp->g_flags,
299: (PZERO+1) | PCATCH, devioc, 0))
300: return (error);
301: } while (gp->g_lockp);
302: }
303: gp->g_lockp = p;
304: return(0);
305: }
306:
307: grfunlock(gp)
308: register struct grf_softc *gp;
309: {
310: #ifdef DEBUG
311: if (grfdebug & GDB_LOCK)
312: printf("grfunlock(%d): dev %x flags %x lockpid %d\n",
313: curproc->p_pid, gp-grf_softc, gp->g_flags,
314: gp->g_lockp ? gp->g_lockp->p_pid : -1);
315: #endif
316: if (gp->g_lockp != curproc)
317: return(EBUSY);
318: if (gp->g_flags & GF_WANTED) {
319: wakeup((caddr_t)&gp->g_flags);
320: gp->g_flags &= ~GF_WANTED;
321: }
322: gp->g_lockp = NULL;
323: return(0);
324: }
325:
326: /*ARGSUSED*/
327: grfmap(dev, off, prot)
328: dev_t dev;
329: {
330: return(grfaddr(&grf_softc[GRFUNIT(dev)], off));
331: }
332:
333:
334: grfon(dev)
335: dev_t dev;
336: {
337: int unit = GRFUNIT(dev);
338: struct grf_softc *gp = &grf_softc[unit];
339:
340: /*
341: * XXX: iteoff call relies on devices being in same order
342: * as ITEs and the fact that iteoff only uses the minor part
343: * of the dev arg.
344: */
345: iteoff(unit, 3);
346: return((*grfdev[gp->g_type].gd_mode)
347: (gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
348: }
349:
350: grfoff(dev)
351: dev_t dev;
352: {
353: int unit = GRFUNIT(dev);
354: struct grf_softc *gp = &grf_softc[unit];
355: int error;
356:
357: (void) grfunmmap(dev, (caddr_t)0, curproc);
358: error = (*grfdev[gp->g_type].gd_mode)
359: (gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
360: /* XXX: see comment for iteoff above */
361: iteon(unit, 2);
362: return(error);
363: }
364:
365: grfsinfo(dev, dyninfo)
366: dev_t dev;
367: struct grfdyninfo *dyninfo;
368: {
369: int unit = GRFUNIT(dev);
370: struct grf_softc *gp = &grf_softc[unit];
371: int error;
372:
373: error = grfdev[gp->g_type].gd_mode (gp, GM_GRFCONFIG, dyninfo);
374: /* XXX: see comment for iteoff above */
375: itereinit (unit);
376: return(error);
377: }
378:
379: grfaddr(gp, off)
380: struct grf_softc *gp;
381: register int off;
382: {
383: register struct grfinfo *gi = &gp->g_display;
384:
385: #if 0
386: /* control registers */
387: if (off >= 0 && off < gi->gd_regsize)
388: return(((u_int)gi->gd_regaddr + off) >> PGSHIFT);
389:
390: /* frame buffer */
391: if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
392: off -= gi->gd_regsize;
393: return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
394: }
395: #endif
396: /* bogus */
397: return(-1);
398: }
399:
400: grfmmap(dev, addrp, p)
401: dev_t dev;
402: caddr_t *addrp;
403: struct proc *p;
404: {
405: struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
406: int len, error;
407: struct vnode vn;
408: struct specinfo si;
409: int flags;
410:
411: #ifdef DEBUG
412: if (grfdebug & GDB_MMAP)
413: printf("grfmmap(%d): addr %x\n", p->p_pid, *addrp);
414: #endif
415: len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize;
416: flags = MAP_FILE|MAP_SHARED;
417: if (*addrp)
418: flags |= MAP_FIXED;
419: else
420: *addrp = (caddr_t)0x1000000; /* XXX */
421: vn.v_type = VCHR; /* XXX */
422: vn.v_specinfo = &si; /* XXX */
423: vn.v_rdev = dev; /* XXX */
424: error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)addrp,
425: (vm_size_t)len, VM_PROT_ALL, flags, (caddr_t)&vn, 0);
426: return(error);
427: }
428:
429: grfunmmap(dev, addr, p)
430: dev_t dev;
431: caddr_t addr;
432: struct proc *p;
433: {
434: struct grf_softc *gp = &grf_softc[GRFUNIT(dev)];
435: vm_size_t size;
436: int rv;
437:
438: #ifdef DEBUG
439: if (grfdebug & GDB_MMAP)
440: printf("grfunmmap(%d): dev %x addr %x\n", p->p_pid, dev, addr);
441: #endif
442: if (addr == 0)
443: return(EINVAL); /* XXX: how do we deal with this? */
444: size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize);
445: rv = vm_deallocate(p->p_vmspace->vm_map, (vm_offset_t)addr, size);
446: return(rv == KERN_SUCCESS ? 0 : EINVAL);
447: }
448:
449:
450: #endif /* NGRF > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.