This source file includes following definitions.
- mgxmatch
- mgxattach
- mgx_ioctl
- mgx_mmap
- mgx_alloc_screen
- mgx_free_screen
- mgx_show_screen
- mgx_burner
- mgx_setcolor
- mgx_loadcmap
- mgx_getcmap
- mgx_putcmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/buf.h>
41 #include <sys/device.h>
42 #include <sys/ioctl.h>
43 #include <sys/malloc.h>
44 #include <sys/mman.h>
45 #include <sys/tty.h>
46 #include <sys/conf.h>
47
48 #include <uvm/uvm_extern.h>
49
50 #include <machine/autoconf.h>
51 #include <machine/pmap.h>
52 #include <machine/cpu.h>
53 #include <machine/conf.h>
54
55 #include <dev/wscons/wsconsio.h>
56 #include <dev/wscons/wsdisplayvar.h>
57 #include <dev/rasops/rasops.h>
58 #include <machine/fbvar.h>
59
60 #include <dev/sbus/sbusvar.h>
61
62
63
64
65
66 #define MGX_NREG 9
67 #define MGX_REG_CRTC 4
68 #define MGX_REG_CTRL 5
69 #define MGX_REG_VRAM8 8
70
71
72
73
74 #if _BYTE_ORDER == _LITTLE_ENDIAN
75 #define IO_ADDRESS(x) (x)
76 #else
77 #define IO_ADDRESS(x) ((x) ^ 0x03)
78 #endif
79 #define CRTC_INDEX IO_ADDRESS(0x03c4)
80 #define CRTC_DATA IO_ADDRESS(0x03c5)
81 #define CD_DISABLEVIDEO 0x0020
82 #define CMAP_READ_INDEX IO_ADDRESS(0x03c7)
83 #define CMAP_WRITE_INDEX IO_ADDRESS(0x03c8)
84 #define CMAP_DATA IO_ADDRESS(0x03c9)
85
86
87 struct mgx_softc {
88 struct sunfb sc_sunfb;
89
90 bus_space_tag_t sc_bustag;
91 bus_addr_t sc_paddr;
92
93 u_int8_t sc_cmap[256 * 3];
94 volatile u_int8_t *sc_vidc;
95
96 int sc_nscreens;
97 };
98
99 int mgx_ioctl(void *, u_long, caddr_t, int, struct proc *);
100 int mgx_alloc_screen(void *, const struct wsscreen_descr *, void **,
101 int *, int *, long *);
102 void mgx_free_screen(void *, void *);
103 int mgx_show_screen(void *, void *, int, void (*cb)(void *, int, int),
104 void *);
105 paddr_t mgx_mmap(void *, off_t, int);
106 void mgx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
107 int mgx_getcmap(u_int8_t *, struct wsdisplay_cmap *);
108 int mgx_putcmap(u_int8_t *, struct wsdisplay_cmap *);
109 void mgx_loadcmap(struct mgx_softc *, int, int);
110 void mgx_burner(void *, u_int ,u_int);
111
112 struct wsdisplay_accessops mgx_accessops = {
113 mgx_ioctl,
114 mgx_mmap,
115 mgx_alloc_screen,
116 mgx_free_screen,
117 mgx_show_screen,
118 NULL,
119 NULL,
120 NULL,
121 mgx_burner
122 };
123
124 int mgxmatch(struct device *, void *, void *);
125 void mgxattach(struct device *, struct device *, void *);
126
127 struct cfattach mgx_ca = {
128 sizeof(struct mgx_softc), mgxmatch, mgxattach
129 };
130
131 struct cfdriver mgx_cd = {
132 NULL, "mgx", DV_DULL
133 };
134
135
136
137
138 int
139 mgxmatch(struct device *parent, void *vcf, void *aux)
140 {
141 struct sbus_attach_args *sa = aux;
142
143 if (strcmp(sa->sa_name, "SMSI,mgx") != 0 &&
144 strcmp(sa->sa_name, "mgx") != 0)
145 return (0);
146
147 return (1);
148 }
149
150
151
152
153
154
155 void
156 mgxattach(struct device *parent, struct device *self, void *args)
157 {
158 struct mgx_softc *sc = (struct mgx_softc *)self;
159 struct sbus_attach_args *sa = args;
160 bus_space_tag_t bt;
161 bus_space_handle_t bh;
162 int node, fbsize;
163 int isconsole;
164
165 bt = sa->sa_bustag;
166 node = sa->sa_node;
167
168 printf(": %s", getpropstring(node, "model"));
169
170 isconsole = node == fbnode;
171
172
173 if (sa->sa_nreg < MGX_NREG) {
174 printf("\n%s: expected %d registers, got %d\n",
175 self->dv_xname, MGX_NREG, sa->sa_nreg);
176 return;
177 }
178
179 sc->sc_bustag = bt;
180 if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot,
181 sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE,
182 BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
183 printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
184 return;
185 }
186 sc->sc_vidc = (volatile u_int8_t *)bus_space_vaddr(bt, bh);
187
188
189 mgx_burner(sc, 1, 0);
190
191 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
192
193
194 fbsize = getpropint(node, "fb_size", 0);
195 if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
196 printf("\n%s: expected at least %d bytes of vram, but card "
197 "only provides %d\n",
198 self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
199 return;
200 }
201
202
203 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
204 sa->sa_reg[MGX_REG_VRAM8].sbr_offset);
205 if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
206 sa->sa_reg[MGX_REG_VRAM8].sbr_offset,
207 round_page(sc->sc_sunfb.sf_fbsize),
208 BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
209 printf("\n%s: couldn't map video memory\n", self->dv_xname);
210 return;
211 }
212 sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
213 sc->sc_sunfb.sf_ro.ri_hw = sc;
214
215 fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
216
217 bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
218 fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);
219
220 printf(", %dx%d\n",
221 sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
222
223 if (isconsole) {
224 fbwscons_console_init(&sc->sc_sunfb, -1);
225 }
226
227 fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
228 }
229
230
231
232
233
234 int
235 mgx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
236 {
237 struct mgx_softc *sc = dev;
238 struct wsdisplay_cmap *cm;
239 struct wsdisplay_fbinfo *wdf;
240 int error;
241
242 switch (cmd) {
243 case WSDISPLAYIO_GTYPE:
244 *(u_int *)data = WSDISPLAY_TYPE_MGX;
245 break;
246 case WSDISPLAYIO_GINFO:
247 wdf = (struct wsdisplay_fbinfo *)data;
248 wdf->height = sc->sc_sunfb.sf_height;
249 wdf->width = sc->sc_sunfb.sf_width;
250 wdf->depth = sc->sc_sunfb.sf_depth;
251 wdf->cmsize = 256;
252 break;
253 case WSDISPLAYIO_LINEBYTES:
254 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
255 break;
256
257 case WSDISPLAYIO_GETCMAP:
258 cm = (struct wsdisplay_cmap *)data;
259 error = mgx_getcmap(sc->sc_cmap, cm);
260 if (error != 0)
261 return (error);
262 break;
263 case WSDISPLAYIO_PUTCMAP:
264 cm = (struct wsdisplay_cmap *)data;
265 error = mgx_putcmap(sc->sc_cmap, cm);
266 if (error != 0)
267 return (error);
268 mgx_loadcmap(sc, cm->index, cm->count);
269 break;
270
271 case WSDISPLAYIO_SVIDEO:
272 case WSDISPLAYIO_GVIDEO:
273 break;
274
275 default:
276 return (-1);
277 }
278
279 return (0);
280 }
281
282 paddr_t
283 mgx_mmap(void *v, off_t offset, int prot)
284 {
285 struct mgx_softc *sc = v;
286
287 if (offset & PGOFSET)
288 return (-1);
289
290
291 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
292 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
293 offset, prot, BUS_SPACE_MAP_LINEAR));
294 }
295
296 return (-1);
297 }
298
299 int
300 mgx_alloc_screen(void *v, const struct wsscreen_descr *type,
301 void **cookiep, int *curxp, int *curyp, long *attrp)
302 {
303 struct mgx_softc *sc = v;
304
305 if (sc->sc_nscreens > 0)
306 return (ENOMEM);
307
308 *cookiep = &sc->sc_sunfb.sf_ro;
309 *curyp = 0;
310 *curxp = 0;
311 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
312 0, 0, 0, attrp);
313 sc->sc_nscreens++;
314 return (0);
315 }
316
317 void
318 mgx_free_screen(void *v, void *cookie)
319 {
320 struct mgx_softc *sc = v;
321
322 sc->sc_nscreens--;
323 }
324
325 int
326 mgx_show_screen(void *v, void *cookie, int waitok,
327 void (*cb)(void *, int, int), void *cbarg)
328 {
329 return (0);
330 }
331
332 void
333 mgx_burner(void *v, u_int on, u_int flags)
334 {
335 struct mgx_softc *sc = v;
336
337 sc->sc_vidc[CRTC_INDEX] = 1;
338 if (on)
339 sc->sc_vidc[CRTC_DATA] &= ~CD_DISABLEVIDEO;
340 else
341 sc->sc_vidc[CRTC_DATA] |= CD_DISABLEVIDEO;
342 }
343
344
345
346
347
348 void
349 mgx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
350 {
351 struct mgx_softc *sc = v;
352
353 index *= 3;
354 sc->sc_cmap[index++] = r;
355 sc->sc_cmap[index++] = g;
356 sc->sc_cmap[index] = b;
357
358 mgx_loadcmap(sc, index, 1);
359 }
360
361 void
362 mgx_loadcmap(struct mgx_softc *sc, int start, int ncolors)
363 {
364 u_int8_t *color;
365 int i;
366
367 #if 0
368 sc->sc_vidc[CMAP_WRITE_INDEX] = start;
369 color = sc->sc_cmap + start * 3;
370 #else
371
372
373
374
375 ncolors = 256;
376 color = sc->sc_cmap;
377 #endif
378 for (i = ncolors * 3; i != 0; i--)
379 sc->sc_vidc[CMAP_DATA] = *color++;
380 }
381
382 int
383 mgx_getcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
384 {
385 u_int index = rcm->index, count = rcm->count, i;
386 int error;
387
388 if (index >= 256 || count > 256 - index)
389 return (EINVAL);
390
391 for (i = 0; i < count; i++) {
392 if ((error =
393 copyout(cm + (index + i) * 3 + 0, &rcm->red[i], 1)) != 0)
394 return (error);
395 if ((error =
396 copyout(cm + (index + i) * 3 + 1, &rcm->green[i], 1)) != 0)
397 return (error);
398 if ((error =
399 copyout(cm + (index + i) * 3 + 2, &rcm->blue[i], 1)) != 0)
400 return (error);
401 }
402
403 return (0);
404 }
405
406 int
407 mgx_putcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
408 {
409 u_int index = rcm->index, count = rcm->count, i;
410 int error;
411
412 if (index >= 256 || count > 256 - index)
413 return (EINVAL);
414
415 for (i = 0; i < count; i++) {
416 if ((error =
417 copyin(&rcm->red[i], cm + (index + i) * 3 + 0, 1)) != 0)
418 return (error);
419 if ((error =
420 copyin(&rcm->green[i], cm + (index + i) * 3 + 1, 1)) != 0)
421 return (error);
422 if ((error =
423 copyin(&rcm->blue[i], cm + (index + i) * 3 + 2, 1)) != 0)
424 return (error);
425 }
426
427 return (0);
428 }