kernel: Use hashdestroy() to free hash tables allocated with hashinit().
[dragonfly.git] / usr.bin / doscmd / int10.c
1 /*
2  * Copyright (c) 1992, 1993, 1996
3  *      Berkeley Software Design, Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Berkeley Software
16  *      Design, Inc.
17  *
18  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      BSDI int10.c,v 2.3 1996/04/08 19:32:40 bostic Exp
31  *
32  * $FreeBSD: src/usr.bin/doscmd/int10.c,v 1.3.2.2 2002/04/25 11:04:51 tg Exp $
33  * $DragonFly: src/usr.bin/doscmd/int10.c,v 1.2 2003/06/17 04:29:26 dillon Exp $
34  */
35
36 #include <unistd.h>
37
38 #include "doscmd.h"
39 #include "mouse.h"
40 #include "tty.h"
41 #include "video.h"
42
43 static int cursoremu = 1;
44
45 void
46 int10(regcontext_t *REGS)
47 {
48         char *addr;
49         int i, j;
50         int saved_row, saved_col;
51
52         /*
53          * Any call to the video BIOS is enough to reset the poll
54          * count on the keyboard.
55          */
56         reset_poll();
57
58         switch (R_AH) {
59         case 0x00:              /* Set display mode */
60                 if (!xmode)
61                         goto unsupported;
62                 init_mode(R_AL);
63                 break;
64         case 0x01:              /* Define cursor */
65         {
66                 int start, end;
67                 
68                 start = R_CH;
69                 end = R_CL;
70                 if (cursoremu == 0)
71                         goto out;
72                 /* Cursor emulation */
73                 if (start <= 3 && end <= 3)
74                         goto out;
75                 if (start + 2 >= end) {
76                         /* underline cursor */
77                         start = CharHeight - 3;
78                         end = CharHeight - 2;
79                         goto out;
80                 }
81                 if (start <= 2 || end < start) {
82                         /* block cursor */
83                         start = 0;
84                         end = CharHeight - 2;
85                         goto out;
86                 }
87                 if (start > CharHeight / 2) {
88                         /* half block cursor */
89                         start = CharHeight / 2;
90                         end = 0;
91                 }
92  out:           CursStart = start;
93                 CursEnd = end;
94                 break;
95         }
96         case 0x02:              /* Position cursor */
97                 if (!xmode)
98                         goto unsupported;
99                 tty_move(R_DH, R_DL);
100                 break;
101         case 0x03:              /* Read cursor position */
102                 if (!xmode)
103                         goto unsupported;
104                 tty_report(&i, &j);
105                 R_DH = i;
106                 R_DL = j;
107                 R_CH = CursStart;
108                 R_CL = CursEnd;
109                 break;
110         case 0x05:
111                 debug(D_VIDEO, "Select current display page %d\n", R_AL);
112                 break;
113         case 0x06:              /* initialize window/scroll text upward */
114                 if (!xmode)
115                         goto unsupported;
116                 if (R_AL == 0)          /* clear screen */
117                         R_AL = DpyRows + 1;
118                 tty_scroll(R_CH, R_CL,
119                     R_DH, R_DL,
120                     R_AL, R_BH << 8);
121                 break;
122         case 0x07:              /* initialize window/scroll text downward */
123                 if (!xmode)
124                         goto unsupported;
125                 if (R_AL == 0)          /* clear screen */
126                         R_AL = DpyRows + 1;
127                 tty_rscroll(R_CH, R_CL,
128                     R_DH, R_DL,
129                     R_AL, R_BH << 8);
130                 break;
131         case 0x08:              /* read character/attribute */
132                 if (!xmode)
133                         goto unsupported;
134                 i = tty_char(-1, -1);
135                 R_AX = i;
136                 break;
137         case 0x09:              /* write character/attribute */
138                 if (!xmode)
139                         goto unsupported;
140                 tty_rwrite(R_CX, R_AL, R_BL << 8);
141                 break;
142         case 0x0a:              /* write character */
143                 if (!xmode)
144                         goto unsupported;
145                 debug(D_HALF, "Int 10:0a: Write char: %02x\n", R_AL);
146                 tty_rwrite(R_CX, R_AL, -1);
147                 break;
148         case 0x0b:              /* set border color */
149                 if (!xmode)
150                         goto unsupported;
151                 video_setborder(R_BL);
152                 break;
153         case 0x0c:              /* write graphics pixel */
154                 debug(D_VIDEO, "Write graphics pixel at %d, %d\n", R_CX, R_DX);
155                 break;
156         case 0x0d:              /* read graphics pixel */
157                 debug(D_VIDEO, "Read graphics pixel at %d, %d\n", R_CX, R_DX);
158                 break;
159         case 0x0e:              /* write character */
160                 tty_write(R_AL, -1);
161                 break;
162         case 0x0f:              /* get current video mode */
163                 R_AH = DpyCols;         /* number of columns */
164                 R_AL = VideoMode;       /* active mode */
165                 R_BH = 0;/*ActivePage *//* display page */
166                 break;
167         case 0x10:
168                 if (!xmode)
169                         goto unsupported;
170                 switch (R_AL) {
171                 case 0x00:              /* Set single palette register */
172                         palette[R_BL] = R_BH;
173                         update_pixels();
174                         break;
175                 case 0x01:              /* Set overscan register */
176                         VGA_ATC[ATC_OverscanColor] = R_BH;
177                         break;
178                 case 0x02:              /* Set all palette registers */
179                         addr = (char *)MAKEPTR(R_ES, R_DX);
180                         for (i = 0; i < 16; i++)
181                                 palette[i] = *addr++;
182                         VGA_ATC[ATC_OverscanColor] = *addr;
183                         update_pixels();
184                         break;
185                 case 0x03:              /* Enable/Disable blinking mode */
186                         video_blink((R_BL & 1) ? 1 : 0);
187                         break;
188                 case 0x07:              /* Get individual palette register */
189                         R_BH = palette[R_BL];
190                         break;
191                 case 0x08:              /* Read overscan register */
192                         R_BH = VGA_ATC[ATC_OverscanColor];
193                         break;
194                 case 0x09:              /* Read all palette registers */
195                         addr = (char *)MAKEPTR(R_ES, R_DX);
196                         for (i = 0; i < 16; i++)
197                                 *addr++ = palette[i];
198                         *addr = VGA_ATC[ATC_OverscanColor];
199                         break;
200                 case 0x10:              /* Set individual DAC register */
201                         dac_rgb[R_BX].red   = R_DH & 0x3f;
202                         dac_rgb[R_BX].green = R_CH & 0x3f;
203                         dac_rgb[R_BX].blue  = R_CL & 0x3f;
204                         update_pixels();
205                         break;
206                 case 0x12:              /* Set block of DAC registers */
207                         addr = (char *)MAKEPTR(R_ES, R_DX);
208                         for (i = R_BX; i < R_BX + R_CX; i++) {
209                                 dac_rgb[i].red   = *addr++;
210                                 dac_rgb[i].green = *addr++;
211                                 dac_rgb[i].blue  = *addr++;
212                         }
213                         update_pixels();
214                         break;
215                 case 0x13:              /* Select video DAC color page */
216                         switch (R_BL) {
217                         case 0:
218                                 VGA_ATC[ATC_ModeCtrl] |= (R_BH & 0x01) << 7;
219                                 break;
220                         case 1:
221                                 VGA_ATC[ATC_ColorSelect] = R_BH & 0x0f;
222                                 break;
223                         default:
224                                 debug(D_VIDEO, "INT 10 10:13 "
225                                     "Bad value for BL: 0x%02x\n", R_BL);
226                                 break;
227                         }
228                 case 0x15:              /* Read individual DAC register */
229                         R_DH = dac_rgb[R_BX].red;
230                         R_CH = dac_rgb[R_BX].green;
231                         R_CL = dac_rgb[R_BX].blue;
232                         break;
233                 case 0x17:              /* Read block of DAC registers */
234                         addr = (char *)MAKEPTR(R_ES, R_DX);
235                         for (i = R_BX; i < R_BX + R_CX; i++) {
236                                 *addr++ = dac_rgb[i].red;
237                                 *addr++ = dac_rgb[i].green;
238                                 *addr++ = dac_rgb[i].blue;
239                         }
240                         break;
241                 case 0x18:              /* Set PEL mask */
242                         debug(D_HALF,
243                             "INT 10 10:18 Set PEL mask (%02x)\n", R_BL);
244                         break;
245                 case 0x19:              /* Read PEL mask */
246                         debug(D_HALF, "INT 10 10:19 Read PEL mask\n");
247                         break;
248                 case 0x1a:              /* Get video dac color-page state */
249                         R_BH = (VGA_ATC[ATC_ModeCtrl] & 0x80) >> 7;
250                         R_BL = VGA_ATC[ATC_ColorSelect];
251                         break;
252                 case 0x1b:              /* Perform gray-scale summing */
253                         debug(D_HALF, "Perform gray-scale summing\n");
254                         break;
255                 default:
256                         unknown_int3(0x10, 0x10, R_AL, REGS);
257                         break;
258                 }
259                 break;
260         case 0x11:
261                 switch (R_AL) {
262                 case 0x00:      /* Text-mode chargen: load user-specified
263                                    patterns */
264                         debug(D_VIDEO, "Tried to load user defined font.\n");
265                         break;
266                 case 0x01:      /* Text-mode chargen: load ROM monochrome
267                                    patterns */
268                         debug(D_VIDEO, "Tried to load 8x14 font.\n");
269                         break;
270                 case 0x02:      /* Text-mode chargen: load ROM 8x8 double-dot
271                                    patterns */
272                         debug(D_VIDEO, "Tried to load 8x8 font.\n");
273                         break;
274                 case 0x03:      /* Text-mode chargen: set block specifier */
275                         debug(D_VIDEO, "Tried to activate character set\n");
276                         break;
277                 case 0x04:      /* Text-mode chargen: load ROM 8x16 character
278                                    set */
279                         debug(D_VIDEO, "Tried to load 8x16 font.\n");
280                         break;
281                 case 0x10:      /* Text-mode chargen: load and activate
282                                    user-specified patterns */
283                         debug(D_VIDEO,
284                             "Tried to load and activate user defined font\n");
285                         break;
286                 case 0x11:      /* Text-mode chargen: load and activate ROM
287                                    monochrome patterns */
288                         debug(D_VIDEO,
289                             "Tried to load and activate 8x14 font.\n");
290                         break;
291                 case 0x12:      /* Text-mode chargen: load and activate ROM
292                                    8x8 double-dot patterns */
293                         debug(D_VIDEO,
294                             "Tried to load and activate 8x8 font.\n");
295                         break;
296                 case 0x14:      /* Text-mode chargen: load and activate ROM
297                                    8x16 character set */
298                         debug(D_VIDEO,
299                             "Tried to load and activate 8x16 font.\n");
300                         break;
301                 case 0x20:      /* Graph-mode chargen: set user 8x8 graphics
302                                    characters */
303                         debug(D_VIDEO, "Load second half of 8x8 char set\n");
304                         break;
305                 case 0x21:      /* Graph-mode chargen: set user graphics
306                                    characters */
307                         debug(D_VIDEO, "Install user defined char set\n");
308                         break;
309                 case 0x22:      /* Graph-mode chargen: set ROM 8x14 graphics
310                                    chars */
311                         debug(D_VIDEO, "Install 8x14 char set\n");
312                         break;
313                 case 0x23:      /* Graph-mode chargen: set ROM 8x8 double-dot
314                                    chars */
315                         debug(D_VIDEO, "Install 8x8 char set\n");
316                         break;
317                 case 0x24:      /* Graph-mode chargen: load 8x16 graphics
318                                    chars */
319                         debug(D_VIDEO, "Install 8x16 char set\n");
320                         break;
321                 case 0x30:      /* Get font information */
322                         debug(D_VIDEO,
323                             "INT 10 11:30 Request font address %02x\n", R_BH);
324                         R_CX = CharHeight;
325                         R_DL = DpyRows;
326                         switch(R_BH) {
327                         case 0:
328                                 PUTVEC(R_ES, R_BP, ivec[0x1f]);
329                                 break;
330                         case 1:
331                                 PUTVEC(R_ES, R_BP, ivec[0x43]);
332                                 break;
333                         case 2:
334                         case 3:
335                         case 4:
336                         case 5:
337                         case 6:
338                         case 7:
339                                 R_ES = 0;
340                                 R_BP = 0;
341                                 break;
342                         default:
343                                 unknown_int4(0x10, 0x11, 0x30, R_BH, REGS);
344                                 break;
345                         }
346                         break;
347                 default:
348                         unknown_int3(0x10, 0x11, R_AL, REGS);
349                         break;
350                 }
351                 break;
352         case 0x12:              /* Alternate function select */
353                 if (!xmode)
354                         goto unsupported;
355                 switch (R_BL) {
356                 case 0x10:      /* Read EGA/VGA config */
357                         R_BH = NumColors > 1 ? 0 : 1;   /* Color */
358                         R_BL = 3;                       /* 256 K */
359                         break;
360                 case 0x34:      /* Cursor emulation */
361                         if (R_AL == 0)
362                                 cursoremu = 1;
363                         else
364                                 cursoremu = 0;
365                         R_AL = 0x12;
366                         break;
367                 default:
368                         if (vflag)
369                                 dump_regs(REGS);
370                         unknown_int3(0x10, 0x12, R_BL, REGS);
371                         break;
372                 }
373                 break;
374         case 0x13: /* write character string */
375                 if (!xmode)
376                         goto unsupported;
377                 addr = (char *)MAKEPTR(R_ES, R_BP);
378                 switch (R_AL & 0x03) {
379                 case 0:
380                         tty_report(&saved_row, &saved_col);
381                         tty_move(R_DH, R_DL);
382                         for (i = 0; i < R_CX; ++i)
383                                 tty_write(*addr++, R_BL << 8);
384                         tty_move(saved_row, saved_col);
385                         break;
386                 case 1:
387                         tty_move(R_DH, R_DL);
388                         for (i = 0; i < R_CX; ++i)
389                                 tty_write(*addr++, R_BL << 8);
390                         break;
391                 case 2:
392                         tty_report(&saved_row, &saved_col);
393                         tty_move(R_DH, R_DL);
394                         for (i = 0; i < R_CX; ++i) {
395                                 tty_write(addr[0], addr[1]);
396                                 addr += 2;
397                         }
398                         tty_move(saved_row, saved_col);
399                         break;
400                 case 3:
401                         tty_move(R_DH, R_DL);
402                         for (i = 0; i < R_CX; ++i) {
403                                 tty_write(addr[0], addr[1]);
404                                 addr += 2;
405                         }
406                         break;
407                 }
408                 break;
409         case 0x1a:
410                 if (!xmode)
411                         goto unsupported;
412                 R_AL = 0x1a;            /* I am VGA */
413                 R_BL = 8;               /* Color VGA */
414                 R_BH = 0;               /* No other card */
415                 break;
416         case 0x1b:      /* Video Functionality/State information */
417                 if (R_BX == 0) {
418                         addr = (char *)MAKEPTR(R_ES, R_DI);
419                         memcpy(addr, vga_status, 64);
420                         R_AL = 0x1b;
421                 }
422                 break;
423         case 0x1c:      /* Save/Restore video state */
424                 debug(D_VIDEO, "VGA: Save/restore video state\n");
425                 R_AL = 0;
426                 break;
427         case 0x30:      /* Locate 3270PC configuration table */
428                 R_CX = 0;
429                 R_DX = 0;
430                 break;
431         case 0x4f:      /* get VESA information */
432                 R_AH = 0x01;            /* no VESA support */
433                 break;
434         case 0x6f:
435                 switch (R_AL) {
436                 case 0x00:      /* HP-Vectra or Video7 installation check */
437                         R_BX = 0;               /* nope, none of that */
438                         break;
439                 default:
440                         unknown_int3(0x10, 0x6f, R_AL, REGS);
441                         break;
442                 }
443                 break;
444         case 0xef:
445         case 0xfe:      /* Get video buffer */
446                 break;
447         case 0xfa:      /* Interrogate mouse driver */
448                 if (xmode)
449                         PUTPTR(R_ES, R_BX, (long)mouse_area);
450                 break;
451         case 0xff:      /* Update real screen from video buffer */
452                 /* XXX - we should allow secondary buffer here and then
453                          update it as the user requests. */
454                 break;
455         unsupported:
456                 if (vflag)
457                         dump_regs(REGS);
458                 fatal("int10 function 0x%02x:%02x only available in X mode\n",
459                     R_AH, R_AL);
460         default:
461                 if (vflag)
462                         dump_regs(REGS);
463                 unknown_int3(0x10, R_AH, R_AL, REGS);
464                 break;
465         }
466 }