Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* Copyright 1992 by Holger Veit |
2 | * May be freely used with Bill Jolitz's port of | |
3 | * 386bsd and may be included in a 386bsd collection | |
4 | * as long as binary and source are available and reproduce the above | |
5 | * copyright. This includes special software collections which | |
6 | * are derived from 386bsd, such as the so-called NetBSD. | |
7 | * | |
8 | * You may freely modify this code and contribute improvements based | |
9 | * on this code as long as you don't claim to be the original author. | |
10 | * Commercial use of this source requires permittance of the copyright | |
11 | * holder. A general license for 386bsd will override this restriction. | |
12 | * | |
13 | * Use at your own risk. The copyright holder or any person who makes | |
14 | * this code available for the public (administrators of public archives | |
15 | * for instance) are not responsible for any harm to hardware or software | |
16 | * that might happen due to wrong application or program faults. | |
17 | * | |
18 | * @(#) $RCSfile: co_codrv1.c,v $ $Revision: 1.6 $ (Contributed to 386bsd) $Date: 93/01/23 23:14:27 $ | |
19 | * | |
20 | * This file processes the vga/kbdioctls | |
21 | * | |
22 | * History: see CO_HISTORY | |
23 | * | |
24 | */ | |
25 | static char *rcsid = "$Header: /usr/src/sys.386bsd/i386/isa/codrv/RCS/co_codrv1.c,v 1.6 93/01/23 23:14:27 root Exp Locker: root $"; | |
26 | ||
27 | #define COMPAT_CO011 | |
28 | #include "co_hdr.h" | |
29 | ||
30 | /************************************************************************** | |
31 | * | |
32 | * This file serves as a plug-in interface for IOCTL processing. | |
33 | * | |
34 | * This file has been modified to understand most of the CODRV1 and | |
35 | * CODRV2 ioctls which have been tested long in codrv-0.1.2-ALPHA. | |
36 | * For some reasons, the CODRV2 font interface will be revised | |
37 | * again. It is not integrated here. The other ioctls are available. | |
38 | * | |
39 | * This file has four public entry points: | |
40 | * | |
41 | * coioctl_init() (called by coattach, initialization) | |
42 | * consioctl(dev,cmd,addr,flag) (serves /dev/console specific things) | |
43 | * kbdioctl(dev,cmd,addr,flags) (serves /dev/kbd specific things) | |
44 | * vgaioctl(dev,cmd,addr,flags) (serves /dev/vga specific things) | |
45 | * | |
46 | * In CODRV1 these functions were available with any console device, | |
47 | * be it /dev/console, /dev/kbd, /dev/vga | |
48 | * | |
49 | * This ioctl package contains its own set of service functions, that | |
50 | * were in co_kbd.c and co_vga.c before, with the exception of the | |
51 | * keyboard overload subsystem, which is still in co_kbd.c. | |
52 | * | |
53 | * Programmers are invited to provide different interfaces, such as | |
54 | * SVR3/SVR4/SUN-OS. There will be hopefully fully runtime-replacable | |
55 | * kernel modules, which can make use of this. | |
56 | * | |
57 | ***********************************************************************/ | |
58 | ||
59 | #ifdef CODRV1 | |
60 | #ifndef MINITERM | |
61 | ||
62 | /* | |
63 | * initialize ioctl system | |
64 | */ | |
65 | void coioctl_init() | |
66 | { | |
67 | cons_capabilities.info1 |= (CONS_CODRV1|CONS_CODRV2); | |
68 | } | |
69 | ||
70 | /* | |
71 | * process /dev/console ioctls | |
72 | */ | |
73 | int consioctl(dev_t dev, int cmd, caddr_t data, int flag) | |
74 | { | |
75 | register error; | |
76 | register struct tty *tp = dev2tty(dev); | |
77 | ||
78 | if (!tp) return ENXIO; | |
79 | ||
80 | /* mandatory */ | |
81 | if (cmd==CONSGINFO) { | |
82 | *((struct consinfo*)data) = cons_capabilities; | |
83 | return 0; | |
84 | } else if (cmd==OLDCONSGINFO) { | |
85 | ((struct oldconsinfo*)data)->info1 = cons_capabilities.info1; | |
86 | return 0; | |
87 | } | |
88 | ||
89 | error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); | |
90 | if (error >= 0) | |
91 | return (error); | |
92 | error = ttioctl(tp, cmd, data, flag); | |
93 | if (error >= 0) | |
94 | return (error); | |
95 | ||
96 | /* must be executed for backward compatibility | |
97 | * must be executed *after* the tty ioctls, | |
98 | * because it shares an essential ioctl with them. | |
99 | */ | |
100 | error = kbdioctl(dev, cmd, data, flag); | |
101 | return error==0 ? 0 : ENOTTY; | |
102 | } | |
103 | ||
104 | /********************************************************************** | |
105 | * utility functions for kbdioctl | |
106 | *********************************************************************/ | |
107 | ||
108 | static struct vty *n2vty(int n) | |
109 | { | |
110 | if (n == KBD_ACTVTY) return actvty; | |
111 | if (n >= 0 && n < nvty) return &vtys[n]; | |
112 | return 0; | |
113 | } | |
114 | ||
115 | static void kioc_setlockkeys(dev_t dev,int snc) | |
116 | { | |
117 | register struct vty *vp = dev2vty(dev); | |
118 | if (!vp) { | |
119 | register int i; | |
120 | for (i=0; i<nvty; i++) { | |
121 | vp = &vtys[i]; | |
122 | vp->scroll = snc & 1; | |
123 | vp->num = (snc & 2) ? 1 : 0; | |
124 | vp->caps = (snc & 4) ? 1 : 0; | |
125 | } | |
126 | vp = actvty; | |
127 | } | |
128 | vp->scroll = snc & 1; | |
129 | vp->num = (snc & 2) ? 1 : 0; | |
130 | vp->caps = (snc & 4) ? 1 : 0; | |
131 | kbd_setleds (leds (vp)); | |
132 | } | |
133 | ||
134 | static int kioc_assignleds(dev_t dev,int param) | |
135 | { | |
136 | u_char ostate; | |
137 | struct vty *vp; | |
138 | register int i; | |
139 | ||
140 | if (param&4) { | |
141 | /* used for initialization */ | |
142 | for (i=0; i<nvty; i++) { | |
143 | vp = &vtys[i]; | |
144 | vp->altgrled = (param&3)==2; | |
145 | vp->shiftled = (param&3)==1; | |
146 | } | |
147 | } else | |
148 | { | |
149 | vp = dev2vty(dev); | |
150 | if (!vp) vp=actvty; | |
151 | vp->altgrled = param==2; | |
152 | vp->shiftled = param==1; | |
153 | } | |
154 | ||
155 | vp = actvty; | |
156 | kbd_setleds (leds (vp)); | |
157 | ostate = vp->altgrled ? 2 : vp->shiftled ? 1 : 0; | |
158 | return (ostate); | |
159 | } | |
160 | ||
161 | static int kioc_dobeep(struct kbd_bell *data) | |
162 | { | |
163 | if (data) { | |
164 | int p, d; | |
165 | ||
166 | kbd_cvtsound(data->pitch, &p, data->duration, &d); | |
167 | sysbeep (p, d); | |
168 | } else | |
169 | sysbeep (kbs.pitch, kbs.duration); | |
170 | return 0; | |
171 | } | |
172 | ||
173 | static int kioc_getbeep2(struct kbd_bell *data) | |
174 | { | |
175 | struct vty *vp; | |
176 | ||
177 | if (data->nr == KBD_DEFLT) { | |
178 | data->pitch = 1193180 / kbs.pitch; | |
179 | data->duration = kbs.duration / hz * 1000; | |
180 | return 0; | |
181 | } | |
182 | ||
183 | vp = n2vty(data->nr); | |
184 | if (!vp) return EINVAL; | |
185 | ||
186 | data->pitch = 1193180 / vp->pitch; | |
187 | data->duration = vp->duration / hz * 1000; | |
188 | return 0; | |
189 | } | |
190 | ||
191 | static int kioc_setbeep2(struct kbd_bell *data) | |
192 | { | |
193 | struct vty *vp; | |
194 | ||
195 | if (data->nr == KBD_DEFLT) { | |
196 | kbd_cvtsound(data->pitch, &kbs.pitch, | |
197 | data->duration, &kbs.duration); | |
198 | return 0; | |
199 | } | |
200 | ||
201 | vp = n2vty(data->nr); | |
202 | if (!vp) return EINVAL; | |
203 | ||
204 | kbd_cvtsound(data->pitch, &vp->pitch, data->duration, &vp->duration); | |
205 | return 0; | |
206 | } | |
207 | ||
208 | /* | |
209 | * process keyboard ioctls | |
210 | */ | |
211 | ||
212 | static int ofl = 0; | |
213 | ||
214 | int kbdioctl(dev_t dev, int cmd, caddr_t data, int flag) | |
215 | { | |
216 | int s,n,error; | |
217 | struct vty *vp = dev2vty(dev); | |
218 | ||
219 | switch (cmd) { | |
220 | /* CONSGINFO is mandatory ! */ | |
221 | case CONSGINFO: | |
222 | *((struct consinfo*)data) = cons_capabilities; | |
223 | return 0; | |
224 | case OLDCONSGINFO: | |
225 | ((struct oldconsinfo*)data)->info1 = cons_capabilities.info1; | |
226 | return 0; | |
227 | case KBDFORCEASCII: | |
228 | /* this is a relic from my youth mistakes */ | |
229 | return 0; | |
230 | case KBDCOLDRESET: | |
231 | kbd_coldreset(); | |
232 | kbd_ovlinit(); | |
233 | kbd_settpmrate(KBD_TPD500|KBD_TPM100); | |
234 | kioc_setlockkeys(dev,0); | |
235 | return 0; | |
236 | case KBDWARMRESET: | |
237 | kbd_warmreset(); | |
238 | return 0; | |
239 | case KBDGTPMAT: | |
240 | *(int *)data = kbs.tpmrate; | |
241 | return 0; | |
242 | case KBDSTPMAT: | |
243 | kbd_settpmrate(*(int *)data); | |
244 | return 0; | |
245 | case KBDGREPSW: | |
246 | *(int *)data = kbs.repeat; | |
247 | return 0; | |
248 | case KBDSREPSW: | |
249 | kbs.repeat = (*(int *)data) & 1; | |
250 | return 0; | |
251 | case KBDGLEDS: | |
252 | *(int *)data = kbs.ledstate; | |
253 | return 0; | |
254 | case KBDSLEDS: | |
255 | kbd_setleds(*(int *)data); | |
256 | return 0; | |
257 | case KBDGLOCK: | |
258 | if (!vp) vp=actvty; | |
259 | *(int *)data = vp->scroll | (vp->num<<1) | | |
260 | (vp->caps<<2) | (vp->altgrlock<<3) | | |
261 | (vp->shiftlock<<4); | |
262 | return 0; | |
263 | case KBDSLOCK: | |
264 | kioc_setlockkeys (dev,*(int *) data); | |
265 | return 0; | |
266 | case KBDSCAPSLED: /* assign CapsLock LED to AltgrLock or ShiftLock */ | |
267 | *(int *) data = kioc_assignleds (dev, *(int *)data); | |
268 | return 0; | |
269 | case KBDGCAPSLED: | |
270 | if (!vp) vp = actvty; | |
271 | *(int *) data = vp->altgrled ? 2 : | |
272 | vp->shiftled ? 1 : 0; | |
273 | return 0; | |
274 | case OLDKBDSETBEEP: | |
275 | return kbd_cvtsound(((struct kbd_sound*)data)->pitch, &kbs.pitch, | |
276 | ((struct kbd_sound*)data)->duration, &kbs.duration); | |
277 | case KBDGETBEEP: | |
278 | return kioc_getbeep2((struct kbd_bell*)data); | |
279 | case KBDSETBEEP: | |
280 | return kioc_setbeep2((struct kbd_bell*)data); | |
281 | case KBDBELL: | |
282 | case KBDSETBELL: /* compatibility */ | |
283 | return kioc_dobeep((struct kbd_bell*)data); | |
284 | case KBDGCKEY: | |
285 | return kbd_getckeydef (((Ovl_tbl *)data)->keynum, (Ovl_tbl *) data); | |
286 | case OLDKBDGCKEY: | |
287 | { | |
288 | int stat; | |
289 | Ovl_tbl ok; | |
290 | stat = kbd_getckeydef (ok.keynum, &ok); | |
291 | #if XCHAR != u_char | |
292 | ERROR! FIX ME! | |
293 | #else | |
294 | if (!stat) | |
295 | bcopy(&ok,data,sizeof(struct oldkbd_ovlkey)); | |
296 | #endif | |
297 | return stat; | |
298 | } | |
299 | case KBDSCKEY: | |
300 | return kbd_setkeydef((Ovl_tbl *)data); | |
301 | case KBDGOKEY: | |
302 | return kbd_getokeydef (((Ovl_tbl *)data)->keynum, (Ovl_tbl *) data); | |
303 | case KBDRMKEY: | |
304 | return kbd_rmkeydef (*(int *) data); | |
305 | case KBDDEFAULT: | |
306 | kbd_ovlinit(); | |
307 | return 0; | |
308 | case KBDSCLRLYR: | |
309 | kbs.a0flag = (*(int*)data & 1) != 0; | |
310 | kbs.c0flag = (*(int*)data & 2) != 0; | |
311 | kbs.m0flag = (*(int*)data & 4) != 0; /*not used yet*/ | |
312 | return 0; | |
313 | case KBDGSPECF: | |
314 | return kbd_gethotkey((struct kbd_hotkey *)data); | |
315 | case KBDSSPECF: | |
316 | return kbd_sethotkey((struct kbd_hotkey *)data); | |
317 | ||
318 | /* and now some special features which are cheap */ | |
319 | case FIONREAD: | |
320 | s = spltty(); | |
321 | n = RB_LEN(&co_buf); | |
322 | splx(s); | |
323 | *(off_t*)data = n; | |
324 | return 0; | |
325 | ||
326 | case TIOCSPGRP: | |
327 | consoftc.cs_pgid = *(int*)data; | |
328 | return 0; | |
329 | ||
330 | case TIOCGPGRP: | |
331 | *(int*)data = consoftc.cs_pgid; | |
332 | return 0; | |
333 | ||
334 | default: | |
335 | /* backward compatibility */ | |
336 | error = vgaioctl(dev, cmd, data, flag); | |
337 | if (!error) return 0; | |
338 | else return ENOTTY; | |
339 | } | |
340 | /*NOTREACHED*/ | |
341 | } | |
342 | ||
343 | /********************************************************************** | |
344 | * utility functions for vgaioctl | |
345 | *********************************************************************/ | |
346 | ||
347 | static int chklim(struct vty *vp,int x0,int x1, int y0, int y1) | |
348 | { | |
349 | if (x0 < 0 || x0 >= vp->ncol || | |
350 | y0 < 0 || y0 >= vp->nrow || | |
351 | x1 < 0 || x1 >= vp->ncol || | |
352 | y1 < 0 || y1 >= vp->nrow || | |
353 | x0 > x1 || y0 > y1) | |
354 | return 1; | |
355 | return 0; | |
356 | } | |
357 | ||
358 | static int cpyblk(u_char *from, u_char *to, int mode, | |
359 | int x0, int x1, int y0, int y1, int ncol) | |
360 | { | |
361 | register x,y,n; | |
362 | u_char *ofs,*ofs2; | |
363 | u_short *ofs1; | |
364 | ||
365 | /* copy the requested data, could be optimized */ | |
366 | ||
367 | ofs = from; | |
368 | switch (mode) { | |
369 | case VGA_ATTR: | |
370 | ofs++; | |
371 | /*FALLTHRU*/ | |
372 | ||
373 | case VGA_TEXT: | |
374 | ofs2 = ofs + y0*ncol*2; | |
375 | for (n=0, y=y0; y<=y1; y++, ofs += (ncol*2) ) { | |
376 | for (ofs2=ofs,x=x0; x<=x1; x++,n++,ofs2+=2) | |
377 | *(to+n) = *ofs2; | |
378 | } | |
379 | break; | |
380 | ||
381 | case VGA_BOTH: | |
382 | ofs1 = ((u_short*)from) + x0; | |
383 | for (y=y0; y<=y1; y++, ofs1 += ncol) | |
384 | bcopy(ofs1, to, (x1-x0+1)*2); | |
385 | break; | |
386 | ||
387 | default: | |
388 | return EINVAL; | |
389 | } | |
390 | return 0; | |
391 | } | |
392 | ||
393 | static int getsz(struct vty *vp,struct vga_block *p) | |
394 | { | |
395 | int sz; | |
396 | ||
397 | /* how much */ | |
398 | if ((p->mode & 0x03) == VGA_SCREEN) { | |
399 | p->x0 = 0; | |
400 | p->y0 = 0; | |
401 | p->x1 = vp->ncol-1; | |
402 | p->y1 = vp->nrow-1; | |
403 | sz = vp->size; | |
404 | } | |
405 | else { | |
406 | if (chklim(vp,p->x0,p->x1,p->y0,p->y1)) | |
407 | return 0; | |
408 | sz = (p->x1-p->x0+1) * (p->y1-p->y0+1); | |
409 | } | |
410 | ||
411 | if ((p->mode & 0x30) == VGA_BOTH) | |
412 | sz *= 2; | |
413 | ||
414 | return sz; | |
415 | } | |
416 | ||
417 | static int vioc_vgagetblock(struct vga_block *p) | |
418 | { | |
419 | u_char *data = 0; | |
420 | struct vty *vp; | |
421 | int sz,x0,y0,x1,y1; | |
422 | int error; | |
423 | ||
424 | /* check vty */ | |
425 | vp = n2vty(p->pagenum); | |
426 | if (!vp) return EINVAL; | |
427 | ||
428 | /* get size */ | |
429 | if (!(sz=getsz(vp, p))) return EINVAL; | |
430 | ||
431 | data = (u_char*)malloc(sz, M_IOCTLOPS, M_WAITOK); | |
432 | ||
433 | /* copy the data into buffer */ | |
434 | error = cpyblk( (u_char*)vp->Crtat, data, p->mode&0x30, | |
435 | x0, x1, y0, y1, vp->ncol); | |
436 | ||
437 | /* to user process */ | |
438 | if (!error) error = copyout(data, p->map, sz); | |
439 | ||
440 | /* clean up */ | |
441 | free(data,M_IOCTLOPS); | |
442 | return error; | |
443 | } | |
444 | ||
445 | static int vioc_vgasetblock(struct vga_block *p) | |
446 | { | |
447 | u_char *data = 0; | |
448 | struct vty *vp; | |
449 | int sz,x0,y0,x1,y1; | |
450 | int error; | |
451 | ||
452 | /* check vty */ | |
453 | vp = n2vty(p->pagenum); | |
454 | if (!vp) return EINVAL; | |
455 | ||
456 | /* get size */ | |
457 | if (!(sz=getsz(vp, p))) return EINVAL; | |
458 | ||
459 | data = (u_char*)malloc(sz, M_IOCTLOPS, M_WAITOK); | |
460 | ||
461 | error = copyin(p->map,data,sz); | |
462 | ||
463 | /* copy the requested data */ | |
464 | error = cpyblk (data, (u_char*)vp->Crtat, p->mode&0x30, | |
465 | x0, x1, y0, y1, vp->ncol); | |
466 | ||
467 | /* clean up */ | |
468 | free(data,M_IOCTLOPS); | |
469 | return error; | |
470 | } | |
471 | ||
472 | static int vioc_gettextpage(struct textpage *tp) | |
473 | { | |
474 | int i; | |
475 | u_char *p = ((u_char*)Crtat) + tp->ad; | |
476 | ||
477 | if (tp->ad > 1 || tp->pagenum > 7) return EINVAL; | |
478 | ||
479 | for (i=0; i<actvty->size; i++, p+=2) | |
480 | tp->map[i] = *p; | |
481 | return 0; | |
482 | } | |
483 | ||
484 | static int vioc_settextpage(struct textpage *tp) | |
485 | { | |
486 | int i; | |
487 | u_char *p = ((u_char*)Crtat) + tp->ad; | |
488 | ||
489 | if (tp->ad > 1 || tp->pagenum > 7) return EINVAL; | |
490 | ||
491 | for (i=0; i<actvty->size; i++,p+=2) | |
492 | *p = tp->map[i]; | |
493 | return 0; | |
494 | } | |
495 | ||
496 | static int vioc_oldgetfontchar(struct fontchar *fc) | |
497 | { | |
498 | int pg = fc->page; | |
499 | u_char *ofs = (u_char*)Crtat + pg*0x4000; | |
500 | ||
501 | if (vds.cardtype < VG_EGA || pg < 0 || pg > 7) return EINVAL; | |
502 | ||
503 | vga_enablecg(pg); | |
504 | bcopy(ofs+(fc->idx<<5),fc->cmap,VGA_FNTCSIZE); | |
505 | vga_disablecg(); | |
506 | ||
507 | return 0; | |
508 | } | |
509 | ||
510 | static int vioc_oldsetfontchar(struct fontchar *fc) | |
511 | { | |
512 | int pg = fc->page; | |
513 | u_char *ofs = (u_char*)Crtat + pg*0x4000; | |
514 | ||
515 | if (vds.cardtype < VG_EGA || pg < 0 || pg > 7) return EINVAL; | |
516 | ||
517 | vga_enablecg(pg); | |
518 | bcopy(fc->cmap,ofs+(fc->idx<<5),VGA_FNTCSIZE); | |
519 | vga_disablecg(); | |
520 | ||
521 | return 0; | |
522 | } | |
523 | ||
524 | static int vioc_miscfunctions(struct miscfcns *f) | |
525 | { | |
526 | switch(f->cmd) { | |
527 | case 1: | |
528 | vds.encoding[1] = NOFONT; | |
529 | outw(0x3c4,0x0003); /* SA=0,SB=0 */ | |
530 | break; | |
531 | case 2: | |
532 | f->u.enc[0] = vds.encoding[0]; | |
533 | f->u.enc[1] = vds.encoding[1]; | |
534 | break; | |
535 | case 3: | |
536 | vds.scrtimeout = f->u.timeout; /* seconds */ | |
537 | vga_doblanking(BLANKSTART); | |
538 | break; | |
539 | case 4: | |
540 | f->u.timeout = (vds.scrtimeout&0x3FFFFFFF) | | |
541 | ((u_long)(vds.blanking&3)<<30); | |
542 | break; | |
543 | default: | |
544 | return EINVAL; | |
545 | } | |
546 | return 0; | |
547 | } | |
548 | ||
549 | static int vioc_oldsetfontmap(struct fontmap *data) | |
550 | { | |
551 | int i,k; | |
552 | int pg = data->page; | |
553 | u_char *ofs = (u_char*)Crtat+pg*0x4000; | |
554 | ||
555 | if (vds.cardtype < VG_EGA || pg < 0 || pg > 7) return EINVAL; | |
556 | vds.encoding[pg] = data->encoding; | |
557 | ||
558 | vga_enablecg(); | |
559 | bzero(ofs,8192); | |
560 | for(i=k=0; i<(VGA_FNTCSIZE*VGA_FNTNCHARS); k+=32,i+=VGA_FNTCSIZE) { | |
561 | bcopy(&data->map[i],ofs+k,VGA_FNTCSIZE); | |
562 | } | |
563 | vga_disablecg(); | |
564 | ||
565 | /* enable SB/SBH when font 1 is loaded */ | |
566 | if (pg==1 && data->encoding != NOFONT) outw(0x3c4,0x0403); /* SA=1,SB=0 */ | |
567 | ||
568 | return 0; | |
569 | } | |
570 | ||
571 | static int vioc_oldgetfontmap(struct fontmap *data) | |
572 | { | |
573 | int i,k; | |
574 | int pg = data->page; | |
575 | u_char *ofs = (u_char*)Crtat + pg*0x4000; | |
576 | if (vds.cardtype < VG_EGA || pg < 0 || pg > 7) return EINVAL; | |
577 | ||
578 | data->encoding = vds.encoding[pg]; | |
579 | ||
580 | vga_enablecg(pg); | |
581 | for(i=k=0; i<(VGA_FNTCSIZE*VGA_FNTNCHARS); k+=32,i+=VGA_FNTCSIZE) | |
582 | bcopy(ofs+k,&data->map[i],VGA_FNTCSIZE); | |
583 | vga_disablecg(); | |
584 | ||
585 | return 0; | |
586 | } | |
587 | ||
588 | #define FSPACE 256*32 | |
589 | #define FCHUNKS 32 | |
590 | ||
591 | static int vioc_setfontmap(struct fmap *f) | |
592 | { | |
593 | u_char *ofs = (u_char*)Crtat + f->page*0x4000; | |
594 | u_char *buf; | |
595 | struct fchar *cibuf,fc[FCHUNKS]; | |
596 | int error = 0; | |
597 | int i,j,k; | |
598 | int ec; | |
599 | ||
600 | /* XXX graphics */ | |
601 | if (vds.cardtype < VG_EGA || f->page < 0 || f->page > 1 || | |
602 | f->x > 9 || f->y > 16 || f->nr > 256) return EINVAL; | |
603 | ||
604 | if (f->nr > 0) { | |
605 | vds.f89bit = vds.cardtype >= VG_EGA ? 9 : 8; | |
606 | buf = (u_char*)malloc(FSPACE, M_IOCTLOPS, M_WAITOK); | |
607 | bzero(buf, FSPACE); | |
608 | ||
609 | /* fill the buffer */ | |
610 | cibuf = f->fntmap; | |
611 | for (i = f->nr; i > 0; i -= FCHUNKS, cibuf+=FCHUNKS) { | |
612 | j = i >= FCHUNKS ? FCHUNKS : i; | |
613 | error = copyin(cibuf, fc, j*sizeof(struct fchar)); | |
614 | if (error) goto erexit; | |
615 | for (k=0; k<j; k++) { | |
616 | ec = fc[k].encoding & 0xFF; | |
617 | bcopy(fc[k].map,buf+(ec<<5),f->y); | |
618 | } | |
619 | } | |
620 | ||
621 | /* set the extension bit (this is really switched in | |
622 | * vga_disablecg() | |
623 | */ | |
624 | if (f->x < 9) | |
625 | vds.f89bit = 8; | |
626 | ||
627 | /* move the data into CG space */ | |
628 | vga_enablecg(); | |
629 | bcopy(buf, ofs, FSPACE); | |
630 | vga_disablecg(); | |
631 | } | |
632 | ||
633 | /* this is a hack, as long as XCHAR == u_char */ | |
634 | switch (f->start) { | |
635 | case 0: | |
636 | i = XLAT2PC8; break; | |
637 | case 1: | |
638 | i = NOFONT; break; | |
639 | default: | |
640 | case 2: | |
641 | i = 0; break; | |
642 | } | |
643 | vds.encoding[f->page] = (u_short)i; | |
644 | ||
645 | /* enable SB/SBH when font 1 is loaded */ | |
646 | if (f->page==1) { | |
647 | if (f->nr > 0) outw(0x3c4,0x0403); /* SA=1,SB=0 */ | |
648 | else outw(0x3c4,0x0003); | |
649 | } | |
650 | ||
651 | erexit: | |
652 | /* clean up */ | |
653 | free(buf,M_IOCTLOPS); | |
654 | ||
655 | return error; | |
656 | } | |
657 | ||
658 | static int vioc_getfontmap(struct fmap *f) | |
659 | { | |
660 | u_char *ofs = (u_char*)Crtat + f->page*0x4000; | |
661 | u_char *buf; | |
662 | struct fchar *cobuf,fc[FCHUNKS]; | |
663 | int error = 0; | |
664 | int i,j,k; | |
665 | ||
666 | /* XXX graphics */ | |
667 | if (vds.cardtype < VG_EGA || f->page < 0 || f->page > 1 || | |
668 | f->nr > 0 && (f->x > 9 || f->y > 16) || (f->nr+f->start) > 256) return EINVAL; | |
669 | ||
670 | if (f->nr > 0) { | |
671 | buf = (u_char*)malloc(FSPACE, M_IOCTLOPS, M_WAITOK); | |
672 | ||
673 | /* move the data from CG space */ | |
674 | vga_enablecg(); | |
675 | bcopy(ofs, buf, FSPACE); | |
676 | vga_disablecg(); | |
677 | ||
678 | /* fill the buffer */ | |
679 | cobuf = f->fntmap; | |
680 | for (k = i = 0; i<f->nr; i++,k++) { | |
681 | if (k==FCHUNKS) { | |
682 | error = copyout(fc,cobuf,FCHUNKS*sizeof(struct fchar)); | |
683 | if (error) goto erexit; | |
684 | k = 0; | |
685 | cobuf += FCHUNKS; | |
686 | } | |
687 | ||
688 | fc[k].encoding = i+f->start; | |
689 | bzero(fc[k].map,VGA_MAXX/8*VGA_MAXY); | |
690 | bcopy(buf+32*(i+f->start),fc[k].map,f->y); | |
691 | } | |
692 | ||
693 | /* copy the rest */ | |
694 | error = copyout(fc,cobuf,k*sizeof(struct fchar)); | |
695 | ||
696 | erexit: | |
697 | /* clean up */ | |
698 | free(buf,M_IOCTLOPS); | |
699 | } | |
700 | ||
701 | f->start = vds.encoding[f->page]; | |
702 | ||
703 | return error; | |
704 | } | |
705 | ||
706 | /* | |
707 | * execute my own vga ioctls | |
708 | */ | |
709 | /*ARGSUSED*/ | |
710 | int vgaioctl(dev_t dev, int cmd, caddr_t data, int flag) | |
711 | { | |
712 | switch(cmd) { | |
713 | /* CONSGINFO is mandatory ! */ | |
714 | case CONSGINFO: | |
715 | *((struct consinfo*)data) = cons_capabilities; | |
716 | return 0; | |
717 | case OLDCONSGINFO: | |
718 | ((struct oldconsinfo*)data)->info1 = cons_capabilities.info1; | |
719 | return 0; | |
720 | case CONSOLE_X_MODE: | |
721 | return kbd_setxserveriopl(*(int*)data); | |
722 | case VGASCURSOR: | |
723 | return vga_setcshape((struct cursorshape*)data); | |
724 | case VGAGCURSOR: | |
725 | return vga_getcshape((struct cursorshape*)data); | |
726 | case VGAGINFO: | |
727 | return vga_getvideoinfo((struct videoinfo*)data); | |
728 | case VGAGBLANK: | |
729 | *(int*)data = (vds.scrtimeout&0x3FFFFFFF) | | |
730 | ((u_long)(vds.blanking&3)<<30); | |
731 | return 0; | |
732 | case VGASBLANK: | |
733 | vds.scrtimeout = *(int*)data; /* seconds */ | |
734 | vga_doblanking(BLANKSTART); | |
735 | return 0; | |
736 | case VGAGBLOCK: | |
737 | return vioc_vgagetblock((struct vga_block*)data); | |
738 | case VGASBLOCK: | |
739 | return vioc_vgasetblock((struct vga_block*)data); | |
740 | case OLDVGASFNTMAP: | |
741 | return vioc_oldsetfontmap((struct fontmap*)data); | |
742 | case OLDVGAGFNTMAP: | |
743 | return vioc_oldgetfontmap((struct fontmap*)data); | |
744 | case VGASFONTMAP: | |
745 | return vioc_setfontmap((struct fmap*)data); | |
746 | case VGAGFONTMAP: | |
747 | return vioc_getfontmap((struct fmap*)data); | |
748 | case OLDVGAGCHAR: | |
749 | return vioc_oldgetfontchar((struct fontchar*)data); | |
750 | case OLDVGASCHAR: | |
751 | return vioc_oldsetfontchar((struct fontchar*)data); | |
752 | case VGAGPAGE: | |
753 | return vioc_gettextpage((struct textpage*)data); | |
754 | case VGASPAGE: | |
755 | return vioc_settextpage((struct textpage*)data); | |
756 | case VGAMISCFCNS: | |
757 | return vioc_miscfunctions((struct miscfcns*)data); | |
758 | case VGATAKECTRL: | |
759 | /* No op for now */ | |
760 | return 0; | |
761 | case VGAGIVECTRL: | |
762 | /* No op for now */ | |
763 | return 0; | |
764 | default: | |
765 | return ENOTTY; | |
766 | } | |
767 | /*NOTREACHED*/ | |
768 | } | |
769 | ||
770 | #endif /*!MINITERM*/ | |
771 | #endif /*CODRV1*/ |