Commit | Line | Data |
---|---|---|
984263bc | 1 | /*- |
22ff886e AH |
2 | * (MPSAFE) |
3 | * | |
984263bc MD |
4 | * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> |
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 as | |
12 | * the first lines of this file unmodified. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. The name of the author may not be used to endorse or promote products | |
17 | * derived from this software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
22 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | * | |
30 | * $FreeBSD: src/sys/dev/fb/fb.c,v 1.11.2.2 2000/08/02 22:35:22 peter Exp $ | |
31 | */ | |
32 | ||
33 | #include "opt_fb.h" | |
34 | ||
35 | #include <sys/param.h> | |
36 | #include <sys/systm.h> | |
37 | #include <sys/conf.h> | |
38 | #include <sys/bus.h> | |
39 | #include <sys/kernel.h> | |
40 | #include <sys/malloc.h> | |
41 | #include <sys/uio.h> | |
42 | #include <sys/fbio.h> | |
dc62b251 | 43 | #include <sys/linker_set.h> |
335dda38 | 44 | #include <sys/device.h> |
052b6ffa | 45 | #include <sys/thread2.h> |
984263bc MD |
46 | |
47 | #include <vm/vm.h> | |
48 | #include <vm/pmap.h> | |
49 | ||
1f2de5d4 | 50 | #include "fbreg.h" |
984263bc | 51 | |
dc62b251 MD |
52 | SET_DECLARE(videodriver_set, const video_driver_t); |
53 | ||
984263bc MD |
54 | /* local arrays */ |
55 | ||
56 | /* | |
57 | * We need at least one entry each in order to initialize a video card | |
58 | * for the kernel console. The arrays will be increased dynamically | |
59 | * when necessary. | |
60 | */ | |
61 | ||
62 | static int vid_malloc; | |
63 | static int adapters = 1; | |
64 | static video_adapter_t *adp_ini; | |
65 | static video_adapter_t **adapter = &adp_ini; | |
66 | static video_switch_t *vidsw_ini; | |
67 | video_switch_t **vidsw = &vidsw_ini; | |
68 | ||
69 | #ifdef FB_INSTALL_CDEV | |
b13267a5 MD |
70 | static cdev_t vidcdevsw_ini; |
71 | static cdev_t *vidcdevsw = &vidcdevsw_ini; | |
984263bc MD |
72 | #endif |
73 | ||
74 | #define ARRAY_DELTA 4 | |
75 | ||
76 | static int | |
77 | vid_realloc_array(void) | |
78 | { | |
79 | video_adapter_t **new_adp; | |
80 | video_switch_t **new_vidsw; | |
81 | #ifdef FB_INSTALL_CDEV | |
b13267a5 | 82 | cdev_t *new_cdevsw; |
984263bc MD |
83 | #endif |
84 | int newsize; | |
984263bc MD |
85 | |
86 | if (!vid_malloc) | |
87 | return ENOMEM; | |
88 | ||
052b6ffa | 89 | crit_enter(); |
ed183f8c | 90 | newsize = rounddown(adapters + ARRAY_DELTA, ARRAY_DELTA); |
efda3bd0 MD |
91 | new_adp = kmalloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO); |
92 | new_vidsw = kmalloc(sizeof(*new_vidsw)*newsize, M_DEVBUF, | |
0dcfa558 | 93 | M_WAITOK | M_ZERO); |
984263bc | 94 | #ifdef FB_INSTALL_CDEV |
efda3bd0 | 95 | new_cdevsw = kmalloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, |
0dcfa558 | 96 | M_WAITOK | M_ZERO); |
984263bc | 97 | #endif |
984263bc MD |
98 | bcopy(adapter, new_adp, sizeof(*adapter)*adapters); |
99 | bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters); | |
100 | #ifdef FB_INSTALL_CDEV | |
984263bc MD |
101 | bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters); |
102 | #endif | |
103 | if (adapters > 1) { | |
efda3bd0 MD |
104 | kfree(adapter, M_DEVBUF); |
105 | kfree(vidsw, M_DEVBUF); | |
984263bc | 106 | #ifdef FB_INSTALL_CDEV |
efda3bd0 | 107 | kfree(vidcdevsw, M_DEVBUF); |
984263bc MD |
108 | #endif |
109 | } | |
110 | adapter = new_adp; | |
111 | vidsw = new_vidsw; | |
112 | #ifdef FB_INSTALL_CDEV | |
113 | vidcdevsw = new_cdevsw; | |
114 | #endif | |
115 | adapters = newsize; | |
052b6ffa | 116 | crit_exit(); |
984263bc MD |
117 | |
118 | if (bootverbose) | |
e3869ec7 | 119 | kprintf("fb: new array size %d\n", adapters); |
984263bc MD |
120 | |
121 | return 0; | |
122 | } | |
123 | ||
124 | static void | |
125 | vid_malloc_init(void *arg) | |
126 | { | |
127 | vid_malloc = TRUE; | |
128 | } | |
129 | ||
ba39e2e0 | 130 | SYSINIT(vid_mem, SI_BOOT1_POST, SI_ORDER_ANY, vid_malloc_init, NULL); |
984263bc MD |
131 | |
132 | /* | |
133 | * Low-level frame buffer driver functions | |
134 | * frame buffer subdrivers, such as the VGA driver, call these functions | |
135 | * to initialize the video_adapter structure and register it to the virtual | |
136 | * frame buffer driver `fb'. | |
137 | */ | |
138 | ||
139 | /* initialize the video_adapter_t structure */ | |
140 | void | |
141 | vid_init_struct(video_adapter_t *adp, char *name, int type, int unit) | |
142 | { | |
143 | adp->va_flags = 0; | |
144 | adp->va_name = name; | |
145 | adp->va_type = type; | |
146 | adp->va_unit = unit; | |
147 | } | |
148 | ||
149 | /* Register a video adapter */ | |
150 | int | |
151 | vid_register(video_adapter_t *adp) | |
152 | { | |
153 | const video_driver_t **list; | |
154 | const video_driver_t *p; | |
155 | int index; | |
156 | ||
157 | for (index = 0; index < adapters; ++index) { | |
158 | if (adapter[index] == NULL) | |
159 | break; | |
160 | } | |
161 | if (index >= adapters) { | |
162 | if (vid_realloc_array()) | |
163 | return -1; | |
164 | } | |
165 | ||
166 | adp->va_index = index; | |
167 | adp->va_token = NULL; | |
2efb75f3 | 168 | lwkt_gettoken(&vga_token); |
dc62b251 MD |
169 | SET_FOREACH(list, videodriver_set) { |
170 | p = *list; | |
984263bc MD |
171 | if (strcmp(p->name, adp->va_name) == 0) { |
172 | adapter[index] = adp; | |
173 | vidsw[index] = p->vidsw; | |
2efb75f3 | 174 | lwkt_reltoken(&vga_token); |
984263bc MD |
175 | return index; |
176 | } | |
177 | } | |
178 | ||
2efb75f3 | 179 | lwkt_reltoken(&vga_token); |
984263bc MD |
180 | return -1; |
181 | } | |
182 | ||
183 | int | |
184 | vid_unregister(video_adapter_t *adp) | |
185 | { | |
2efb75f3 | 186 | lwkt_gettoken(&vga_token); |
22ff886e | 187 | if ((adp->va_index < 0) || (adp->va_index >= adapters)) { |
2efb75f3 | 188 | lwkt_reltoken(&vga_token); |
984263bc | 189 | return ENOENT; |
22ff886e AH |
190 | } |
191 | if (adapter[adp->va_index] != adp) { | |
2efb75f3 | 192 | lwkt_reltoken(&vga_token); |
984263bc | 193 | return ENOENT; |
22ff886e | 194 | } |
984263bc MD |
195 | |
196 | adapter[adp->va_index] = NULL; | |
197 | vidsw[adp->va_index] = NULL; | |
2efb75f3 | 198 | lwkt_reltoken(&vga_token); |
984263bc MD |
199 | return 0; |
200 | } | |
201 | ||
202 | /* Get video I/O function table */ | |
3d8ba483 SW |
203 | video_switch_t * |
204 | vid_get_switch(char *name) | |
984263bc MD |
205 | { |
206 | const video_driver_t **list; | |
207 | const video_driver_t *p; | |
208 | ||
2efb75f3 | 209 | lwkt_gettoken(&vga_token); |
dc62b251 MD |
210 | SET_FOREACH(list, videodriver_set) { |
211 | p = *list; | |
22ff886e | 212 | if (strcmp(p->name, name) == 0) { |
2efb75f3 | 213 | lwkt_reltoken(&vga_token); |
984263bc | 214 | return p->vidsw; |
22ff886e | 215 | } |
984263bc MD |
216 | } |
217 | ||
2efb75f3 | 218 | lwkt_reltoken(&vga_token); |
984263bc MD |
219 | return NULL; |
220 | } | |
221 | ||
222 | /* | |
223 | * Video card client functions | |
224 | * Video card clients, such as the console driver `syscons' and the frame | |
225 | * buffer cdev driver, use these functions to claim and release a card for | |
226 | * exclusive use. | |
227 | */ | |
228 | ||
229 | /* find the video card specified by a driver name and a unit number */ | |
230 | int | |
231 | vid_find_adapter(char *driver, int unit) | |
232 | { | |
233 | int i; | |
234 | ||
235 | for (i = 0; i < adapters; ++i) { | |
236 | if (adapter[i] == NULL) | |
237 | continue; | |
238 | if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver)) | |
239 | continue; | |
240 | if ((unit != -1) && (adapter[i]->va_unit != unit)) | |
241 | continue; | |
242 | return i; | |
243 | } | |
244 | return -1; | |
245 | } | |
246 | ||
247 | /* allocate a video card */ | |
248 | int | |
249 | vid_allocate(char *driver, int unit, void *id) | |
250 | { | |
251 | int index; | |
984263bc | 252 | |
052b6ffa | 253 | crit_enter(); |
984263bc MD |
254 | index = vid_find_adapter(driver, unit); |
255 | if (index >= 0) { | |
256 | if (adapter[index]->va_token) { | |
052b6ffa | 257 | crit_exit(); |
984263bc MD |
258 | return -1; |
259 | } | |
260 | adapter[index]->va_token = id; | |
261 | } | |
052b6ffa | 262 | crit_exit(); |
984263bc MD |
263 | return index; |
264 | } | |
265 | ||
266 | int | |
267 | vid_release(video_adapter_t *adp, void *id) | |
268 | { | |
269 | int error; | |
984263bc | 270 | |
052b6ffa | 271 | crit_enter(); |
984263bc MD |
272 | if (adp->va_token == NULL) { |
273 | error = EINVAL; | |
274 | } else if (adp->va_token != id) { | |
275 | error = EPERM; | |
276 | } else { | |
277 | adp->va_token = NULL; | |
278 | error = 0; | |
279 | } | |
052b6ffa | 280 | crit_exit(); |
984263bc MD |
281 | return error; |
282 | } | |
283 | ||
284 | /* Get a video adapter structure */ | |
3d8ba483 SW |
285 | video_adapter_t * |
286 | vid_get_adapter(int index) | |
984263bc MD |
287 | { |
288 | if ((index < 0) || (index >= adapters)) | |
289 | return NULL; | |
290 | return adapter[index]; | |
291 | } | |
292 | ||
293 | /* Configure drivers: this is a backdoor for the console driver XXX */ | |
294 | int | |
295 | vid_configure(int flags) | |
296 | { | |
297 | const video_driver_t **list; | |
298 | const video_driver_t *p; | |
299 | ||
dc62b251 MD |
300 | SET_FOREACH(list, videodriver_set) { |
301 | p = *list; | |
984263bc MD |
302 | if (p->configure != NULL) |
303 | (*p->configure)(flags); | |
304 | } | |
305 | ||
306 | return 0; | |
307 | } | |
308 | ||
309 | /* | |
310 | * Virtual frame buffer cdev driver functions | |
311 | * The virtual frame buffer driver dispatches driver functions to | |
312 | * appropriate subdrivers. | |
313 | */ | |
314 | ||
315 | #define FB_DRIVER_NAME "fb" | |
316 | ||
317 | #ifdef FB_INSTALL_CDEV | |
318 | ||
122df98f | 319 | #if 0 /* experimental */ |
984263bc MD |
320 | |
321 | static devclass_t fb_devclass; | |
322 | ||
323 | static int fbprobe(device_t dev); | |
324 | static int fbattach(device_t dev); | |
325 | ||
326 | static device_method_t fb_methods[] = { | |
327 | DEVMETHOD(device_probe, fbprobe), | |
328 | DEVMETHOD(device_attach, fbattach), | |
329 | ||
330 | DEVMETHOD(bus_print_child, bus_generic_print_child), | |
d3c9c58e | 331 | DEVMETHOD_END |
984263bc MD |
332 | }; |
333 | ||
334 | static driver_t fb_driver = { | |
335 | FB_DRIVER_NAME, | |
336 | fb_methods, | |
337 | 0, | |
338 | }; | |
339 | ||
340 | static int | |
341 | fbprobe(device_t dev) | |
342 | { | |
343 | int unit; | |
344 | ||
345 | unit = device_get_unit(dev); | |
346 | if (unit >= adapters) | |
347 | return ENXIO; | |
348 | if (adapter[unit] == NULL) | |
349 | return ENXIO; | |
350 | ||
351 | device_set_desc(dev, "generic frame buffer"); | |
352 | return 0; | |
353 | } | |
354 | ||
355 | static int | |
356 | fbattach(device_t dev) | |
357 | { | |
e3869ec7 | 358 | kprintf("fbattach: about to attach children\n"); |
984263bc MD |
359 | bus_generic_attach(dev); |
360 | return 0; | |
361 | } | |
362 | ||
363 | #endif /* experimental */ | |
364 | ||
365 | #define FB_UNIT(dev) minor(dev) | |
366 | #define FB_MKMINOR(unit) (u) | |
367 | ||
1dc9faeb | 368 | #if 0 |
fef8985e | 369 | static d_default_t fboperate; |
984263bc | 370 | static d_open_t fbopen; |
984263bc | 371 | |
fef8985e | 372 | static struct dev_ops fb_ops = { |
88abd8b5 | 373 | { FB_DRIVER_NAME, 0, 0 }, |
fef8985e MD |
374 | .d_default = fboperate, |
375 | .d_open = fbopen | |
984263bc | 376 | }; |
1dc9faeb | 377 | #endif |
984263bc MD |
378 | |
379 | static void | |
380 | vfbattach(void *arg) | |
381 | { | |
382 | static int fb_devsw_installed = FALSE; | |
383 | ||
384 | if (!fb_devsw_installed) { | |
7e0245d8 | 385 | #if 0 |
fef8985e | 386 | dev_ops_add(&fb_ops, 0, 0); |
7e0245d8 | 387 | #endif |
984263bc MD |
388 | fb_devsw_installed = TRUE; |
389 | } | |
390 | } | |
391 | ||
392 | PSEUDO_SET(vfbattach, fb); | |
393 | ||
335dda38 MD |
394 | /* |
395 | * Note: dev represents the actual video device, not the frame buffer | |
396 | */ | |
984263bc | 397 | int |
b13267a5 | 398 | fb_attach(cdev_t dev, video_adapter_t *adp) |
984263bc | 399 | { |
984263bc MD |
400 | if (adp->va_index >= adapters) |
401 | return EINVAL; | |
402 | if (adapter[adp->va_index] != adp) | |
403 | return EINVAL; | |
404 | ||
052b6ffa | 405 | crit_enter(); |
e4c9c0c8 | 406 | reference_dev(dev); |
984263bc | 407 | adp->va_minor = minor(dev); |
e4c9c0c8 | 408 | vidcdevsw[adp->va_index] = dev; |
052b6ffa | 409 | crit_exit(); |
984263bc | 410 | |
e3869ec7 | 411 | kprintf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit); |
984263bc MD |
412 | return 0; |
413 | } | |
414 | ||
335dda38 MD |
415 | /* |
416 | * Note: dev represents the actual video device, not the frame buffer | |
417 | */ | |
984263bc | 418 | int |
b13267a5 | 419 | fb_detach(cdev_t dev, video_adapter_t *adp) |
984263bc | 420 | { |
984263bc MD |
421 | if (adp->va_index >= adapters) |
422 | return EINVAL; | |
423 | if (adapter[adp->va_index] != adp) | |
424 | return EINVAL; | |
e4c9c0c8 | 425 | if (vidcdevsw[adp->va_index] != dev) |
984263bc MD |
426 | return EINVAL; |
427 | ||
052b6ffa | 428 | crit_enter(); |
984263bc | 429 | vidcdevsw[adp->va_index] = NULL; |
052b6ffa | 430 | crit_exit(); |
e4c9c0c8 | 431 | release_dev(dev); |
984263bc MD |
432 | return 0; |
433 | } | |
434 | ||
1dc9faeb | 435 | #if 0 |
984263bc | 436 | static int |
fef8985e | 437 | fbopen(struct dev_open_args *ap) |
984263bc | 438 | { |
b13267a5 | 439 | cdev_t dev = ap->a_head.a_dev; |
984263bc | 440 | int unit; |
b13267a5 | 441 | cdev_t fdev; |
984263bc MD |
442 | |
443 | unit = FB_UNIT(dev); | |
fef8985e | 444 | if (unit < 0 || unit >= adapters) |
984263bc | 445 | return ENXIO; |
e4c9c0c8 | 446 | if ((fdev = vidcdevsw[unit]) == NULL) |
984263bc | 447 | return ENXIO; |
8c530b23 | 448 | return dev_dopen(fdev, ap->a_oflags, ap->a_devtype, ap->a_cred, NULL); |
984263bc MD |
449 | } |
450 | ||
451 | static int | |
fef8985e | 452 | fboperate(struct dev_generic_args *ap) |
984263bc | 453 | { |
b13267a5 | 454 | cdev_t dev = ap->a_dev; |
984263bc | 455 | int unit; |
b13267a5 | 456 | cdev_t fdev; |
984263bc MD |
457 | |
458 | unit = FB_UNIT(dev); | |
e4c9c0c8 | 459 | if ((fdev = vidcdevsw[unit]) == NULL) |
984263bc | 460 | return ENXIO; |
fef8985e MD |
461 | ap->a_dev = fdev; |
462 | return dev_doperate(ap); | |
984263bc | 463 | } |
1dc9faeb | 464 | #endif |
984263bc | 465 | |
984263bc MD |
466 | /* |
467 | * Generic frame buffer cdev driver functions | |
468 | * Frame buffer subdrivers may call these functions to implement common | |
469 | * driver functions. | |
470 | */ | |
471 | ||
472 | int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode, | |
fef8985e | 473 | struct ucred *cred) |
984263bc | 474 | { |
052b6ffa | 475 | crit_enter(); |
984263bc MD |
476 | if (!(sc->gfb_flags & FB_OPEN)) |
477 | sc->gfb_flags |= FB_OPEN; | |
052b6ffa | 478 | crit_exit(); |
984263bc MD |
479 | return 0; |
480 | } | |
481 | ||
fef8985e | 482 | int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode) |
984263bc | 483 | { |
052b6ffa | 484 | crit_enter(); |
984263bc | 485 | sc->gfb_flags &= ~FB_OPEN; |
052b6ffa | 486 | crit_exit(); |
984263bc MD |
487 | return 0; |
488 | } | |
489 | ||
490 | int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio, | |
491 | int flag) | |
492 | { | |
493 | int size; | |
494 | int offset; | |
495 | int error; | |
496 | int len; | |
497 | ||
2efb75f3 | 498 | lwkt_gettoken(&vga_token); |
984263bc MD |
499 | error = 0; |
500 | size = adp->va_buffer_size/adp->va_info.vi_planes; | |
501 | while (uio->uio_resid > 0) { | |
502 | if (uio->uio_offset >= size) | |
503 | break; | |
504 | offset = uio->uio_offset%adp->va_window_size; | |
e54488bb | 505 | len = (int)szmin(uio->uio_resid, size - uio->uio_offset); |
984263bc MD |
506 | len = imin(len, adp->va_window_size - offset); |
507 | if (len <= 0) | |
508 | break; | |
509 | (*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset); | |
e54488bb MD |
510 | error = uiomove((caddr_t)(adp->va_window + offset), |
511 | (size_t)len, uio); | |
984263bc MD |
512 | if (error) |
513 | break; | |
514 | } | |
2efb75f3 | 515 | lwkt_reltoken(&vga_token); |
984263bc MD |
516 | return error; |
517 | } | |
518 | ||
519 | int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio, | |
520 | int flag) | |
521 | { | |
522 | return ENODEV; | |
523 | } | |
524 | ||
525 | int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd, | |
fef8985e | 526 | caddr_t arg, int flag, struct ucred *cred) |
984263bc MD |
527 | { |
528 | int error; | |
529 | ||
530 | if (adp == NULL) /* XXX */ | |
531 | return ENXIO; | |
2efb75f3 | 532 | lwkt_gettoken(&vga_token); |
984263bc MD |
533 | error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg); |
534 | if (error == ENOIOCTL) | |
535 | error = ENODEV; | |
2efb75f3 | 536 | lwkt_reltoken(&vga_token); |
984263bc MD |
537 | return error; |
538 | } | |
539 | ||
540 | int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset, | |
541 | int prot) | |
542 | { | |
261a35c1 MD |
543 | int error; |
544 | ||
2efb75f3 | 545 | lwkt_gettoken(&vga_token); |
261a35c1 | 546 | error = (*vidsw[adp->va_index]->mmap)(adp, offset, prot); |
2efb75f3 | 547 | lwkt_reltoken(&vga_token); |
261a35c1 | 548 | return (error); |
984263bc MD |
549 | } |
550 | ||
551 | #endif /* FB_INSTALL_CDEV */ | |
552 | ||
3d8ba483 SW |
553 | static char * |
554 | adapter_name(int type) | |
984263bc MD |
555 | { |
556 | static struct { | |
557 | int type; | |
558 | char *name; | |
559 | } names[] = { | |
560 | { KD_MONO, "MDA" }, | |
561 | { KD_HERCULES, "Hercules" }, | |
562 | { KD_CGA, "CGA" }, | |
563 | { KD_EGA, "EGA" }, | |
564 | { KD_VGA, "VGA" }, | |
984263bc MD |
565 | { KD_TGA, "TGA" }, |
566 | { -1, "Unknown" }, | |
567 | }; | |
568 | int i; | |
569 | ||
570 | for (i = 0; names[i].type != -1; ++i) | |
571 | if (names[i].type == type) | |
572 | break; | |
573 | return names[i].name; | |
574 | } | |
575 | ||
576 | /* | |
577 | * Generic low-level frame buffer functions | |
578 | * The low-level functions in the frame buffer subdriver may use these | |
579 | * functions. | |
580 | */ | |
581 | ||
582 | void | |
583 | fb_dump_adp_info(char *driver, video_adapter_t *adp, int level) | |
584 | { | |
585 | if (level <= 0) | |
586 | return; | |
587 | ||
e3869ec7 | 588 | kprintf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n", |
984263bc MD |
589 | FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name, |
590 | adapter_name(adp->va_type), adp->va_type, adp->va_flags); | |
4e193d20 | 591 | kprintf("%s%d: port:0x%x-0x%x, mem:0x%x 0x%x\n", |
984263bc MD |
592 | FB_DRIVER_NAME, adp->va_index, |
593 | adp->va_io_base, adp->va_io_base + adp->va_io_size - 1, | |
4e193d20 | 594 | adp->va_mem_base, adp->va_mem_size); |
e3869ec7 | 595 | kprintf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n", |
984263bc MD |
596 | FB_DRIVER_NAME, adp->va_index, |
597 | adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode); | |
e3869ec7 | 598 | kprintf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n", |
984263bc MD |
599 | FB_DRIVER_NAME, adp->va_index, |
600 | (void *)adp->va_window, (int)adp->va_window_size/1024, | |
601 | (int)adp->va_window_gran/1024, (void *)adp->va_buffer, | |
602 | (int)adp->va_buffer_size/1024); | |
603 | } | |
604 | ||
605 | void | |
606 | fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info, | |
607 | int level) | |
608 | { | |
609 | if (level <= 0) | |
610 | return; | |
611 | ||
e3869ec7 | 612 | kprintf("%s%d: %s, mode:%d, flags:0x%x ", |
984263bc MD |
613 | driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags); |
614 | if (info->vi_flags & V_INFO_GRAPHICS) | |
e3869ec7 | 615 | kprintf("G %dx%dx%d, %d plane(s), font:%dx%d, ", |
984263bc MD |
616 | info->vi_width, info->vi_height, |
617 | info->vi_depth, info->vi_planes, | |
618 | info->vi_cwidth, info->vi_cheight); | |
619 | else | |
e3869ec7 | 620 | kprintf("T %dx%d, font:%dx%d, ", |
984263bc MD |
621 | info->vi_width, info->vi_height, |
622 | info->vi_cwidth, info->vi_cheight); | |
e3869ec7 | 623 | kprintf("win:0x%x\n", info->vi_window); |
984263bc MD |
624 | } |
625 | ||
626 | int | |
627 | fb_type(int adp_type) | |
628 | { | |
629 | static struct { | |
630 | int fb_type; | |
631 | int va_type; | |
632 | } types[] = { | |
633 | { FBTYPE_MDA, KD_MONO }, | |
634 | { FBTYPE_HERCULES, KD_HERCULES }, | |
635 | { FBTYPE_CGA, KD_CGA }, | |
636 | { FBTYPE_EGA, KD_EGA }, | |
637 | { FBTYPE_VGA, KD_VGA }, | |
984263bc MD |
638 | { FBTYPE_TGA, KD_TGA }, |
639 | }; | |
640 | int i; | |
641 | ||
c157ff7a | 642 | for (i = 0; i < NELEM(types); ++i) { |
984263bc MD |
643 | if (types[i].va_type == adp_type) |
644 | return types[i].fb_type; | |
645 | } | |
646 | return -1; | |
647 | } | |
648 | ||
649 | int | |
650 | fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) | |
651 | { | |
652 | int error; | |
984263bc MD |
653 | |
654 | /* assert(adp != NULL) */ | |
655 | ||
656 | error = 0; | |
052b6ffa | 657 | crit_enter(); |
984263bc | 658 | |
2efb75f3 | 659 | lwkt_gettoken(&vga_token); |
984263bc MD |
660 | switch (cmd) { |
661 | ||
662 | case FBIO_ADAPTER: /* get video adapter index */ | |
663 | *(int *)arg = adp->va_index; | |
664 | break; | |
665 | ||
666 | case FBIO_ADPTYPE: /* get video adapter type */ | |
667 | *(int *)arg = adp->va_type; | |
668 | break; | |
669 | ||
670 | case FBIO_ADPINFO: /* get video adapter info */ | |
671 | ((video_adapter_info_t *)arg)->va_index = adp->va_index; | |
672 | ((video_adapter_info_t *)arg)->va_type = adp->va_type; | |
673 | bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name, | |
674 | imin(strlen(adp->va_name) + 1, | |
675 | sizeof(((video_adapter_info_t *)arg)->va_name))); | |
676 | ((video_adapter_info_t *)arg)->va_unit = adp->va_unit; | |
677 | ((video_adapter_info_t *)arg)->va_flags = adp->va_flags; | |
678 | ((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base; | |
679 | ((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size; | |
984263bc MD |
680 | ((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base; |
681 | ((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size; | |
d0a4041b | 682 | ((video_adapter_info_t *)arg)->va_window = adp->va_window; |
984263bc MD |
683 | ((video_adapter_info_t *)arg)->va_window_size |
684 | = adp->va_window_size; | |
685 | ((video_adapter_info_t *)arg)->va_window_gran | |
686 | = adp->va_window_gran; | |
687 | ((video_adapter_info_t *)arg)->va_window_orig | |
688 | = adp->va_window_orig; | |
d0a4041b | 689 | ((video_adapter_info_t *)arg)->va_unused0 = adp->va_buffer; |
984263bc MD |
690 | ((video_adapter_info_t *)arg)->va_buffer_size |
691 | = adp->va_buffer_size; | |
692 | ((video_adapter_info_t *)arg)->va_mode = adp->va_mode; | |
693 | ((video_adapter_info_t *)arg)->va_initial_mode | |
694 | = adp->va_initial_mode; | |
695 | ((video_adapter_info_t *)arg)->va_initial_bios_mode | |
696 | = adp->va_initial_bios_mode; | |
697 | ((video_adapter_info_t *)arg)->va_line_width | |
698 | = adp->va_line_width; | |
699 | ((video_adapter_info_t *)arg)->va_disp_start.x | |
700 | = adp->va_disp_start.x; | |
701 | ((video_adapter_info_t *)arg)->va_disp_start.y | |
702 | = adp->va_disp_start.y; | |
703 | break; | |
704 | ||
705 | case FBIO_MODEINFO: /* get mode information */ | |
706 | error = (*vidsw[adp->va_index]->get_info)(adp, | |
707 | ((video_info_t *)arg)->vi_mode, | |
708 | (video_info_t *)arg); | |
709 | if (error) | |
710 | error = ENODEV; | |
711 | break; | |
712 | ||
713 | case FBIO_FINDMODE: /* find a matching video mode */ | |
714 | error = (*vidsw[adp->va_index]->query_mode)(adp, | |
715 | (video_info_t *)arg); | |
716 | break; | |
717 | ||
718 | case FBIO_GETMODE: /* get video mode */ | |
719 | *(int *)arg = adp->va_mode; | |
720 | break; | |
721 | ||
722 | case FBIO_SETMODE: /* set video mode */ | |
723 | error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg); | |
724 | if (error) | |
725 | error = ENODEV; /* EINVAL? */ | |
726 | break; | |
727 | ||
728 | case FBIO_GETWINORG: /* get frame buffer window origin */ | |
729 | *(u_int *)arg = adp->va_window_orig; | |
730 | break; | |
731 | ||
732 | case FBIO_GETDISPSTART: /* get display start address */ | |
733 | ((video_display_start_t *)arg)->x = adp->va_disp_start.x; | |
734 | ((video_display_start_t *)arg)->y = adp->va_disp_start.y; | |
735 | break; | |
736 | ||
737 | case FBIO_GETLINEWIDTH: /* get scan line width in bytes */ | |
738 | *(u_int *)arg = adp->va_line_width; | |
739 | break; | |
740 | ||
741 | case FBIO_GETPALETTE: /* get color palette */ | |
742 | case FBIO_SETPALETTE: /* set color palette */ | |
743 | /* XXX */ | |
744 | ||
745 | case FBIOPUTCMAP: | |
746 | case FBIOGETCMAP: | |
747 | /* XXX */ | |
748 | ||
749 | case FBIO_SETWINORG: /* set frame buffer window origin */ | |
750 | case FBIO_SETDISPSTART: /* set display start address */ | |
751 | case FBIO_SETLINEWIDTH: /* set scan line width in pixel */ | |
752 | ||
753 | case FBIOGTYPE: | |
754 | case FBIOGATTR: | |
755 | case FBIOSVIDEO: | |
756 | case FBIOGVIDEO: | |
757 | case FBIOSCURSOR: | |
758 | case FBIOGCURSOR: | |
759 | case FBIOSCURPOS: | |
760 | case FBIOGCURPOS: | |
761 | case FBIOGCURMAX: | |
762 | ||
763 | default: | |
764 | error = ENODEV; | |
765 | break; | |
766 | } | |
767 | ||
052b6ffa | 768 | crit_exit(); |
2efb75f3 | 769 | lwkt_reltoken(&vga_token); |
984263bc MD |
770 | return error; |
771 | } |