blob: 3d5361366ef69fcee78ea99a4af89c1508ff08c8 [file] [log] [blame]
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05001// Raw screen writing code.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4//
5// This file may be distributed under the terms of the GNU GPLv3 license.
6
7#include <stdarg.h> // va_list
8
9#include "farptr.h" // GET_VAR
Kevin O'Connor567e4e32008-04-05 11:37:51 -040010#include "util.h" // printf
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050011#include "biosvar.h" // struct bregs
12
13static void
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050014screenc(u8 c)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050015{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050016 struct bregs br;
17 memset(&br, 0, sizeof(br));
18 br.ah = 0x0e;
19 br.al = c;
20 call16_int(0x10, &br);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050021}
22
Kevin O'Connorc38e4802008-03-15 11:07:50 -040023// XXX - move PORT_DEBUG to standard place?
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050024#define PORT_DEBUG 0x403
25
26// Write a charcter to the framebuffer.
27static void
28putc(u16 action, char c)
29{
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050030 outb(c, PORT_DEBUG);
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050031 if (action) {
32 if (c == '\n')
33 screenc('\r');
34 screenc(c);
35 }
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050036}
37
38// Write a string to the framebuffer.
39static void
40puts(u16 action, const char *s)
41{
42 for (; *s; s++)
43 putc(action, *s);
44}
45
46// Write a string to the framebuffer.
47static void
48puts_cs(u16 action, const char *s)
49{
50 for (;; s++) {
Kevin O'Connor41d28102008-03-30 23:22:39 -040051 char c = GET_VAR(CS, *(u8*)s);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050052 if (!c)
53 break;
54 putc(action, c);
55 }
56}
57
58// Write an unsigned integer to the screen.
59static void
60putuint(u16 action, u32 val)
61{
62 char buf[12];
63 char *d = &buf[sizeof(buf) - 1];
64 *d-- = '\0';
65 for (;;) {
Kevin O'Connor4b60c002008-02-25 22:29:55 -050066 *d = (val % 10) + '0';
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050067 val /= 10;
68 if (!val)
69 break;
70 d--;
71 }
72 puts(action, d);
73}
74
75// Write a single digit hex character to the screen.
76static inline void
77putsinglehex(u16 action, u32 val)
78{
79 if (val <= 9)
80 val = '0' + val;
81 else
82 val = 'a' + val - 10;
83 putc(action, val);
84}
85
86// Write an integer in hexadecimal to the screen.
87static void
88puthex(u16 action, u32 val)
89{
90 putsinglehex(action, (val >> 28) & 0xf);
91 putsinglehex(action, (val >> 24) & 0xf);
92 putsinglehex(action, (val >> 20) & 0xf);
93 putsinglehex(action, (val >> 16) & 0xf);
94 putsinglehex(action, (val >> 12) & 0xf);
95 putsinglehex(action, (val >> 8) & 0xf);
96 putsinglehex(action, (val >> 4) & 0xf);
97 putsinglehex(action, (val >> 0) & 0xf);
98}
99
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500100static inline int
101isdigit(u8 c)
102{
103 return c - '0' < 10;
104}
105
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400106static void
107bvprintf(u16 action, const char *fmt, va_list args)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500108{
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500109 const char *s = fmt;
110 for (;; s++) {
Kevin O'Connor41d28102008-03-30 23:22:39 -0400111 char c = GET_VAR(CS, *(u8*)s);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500112 if (!c)
113 break;
114 if (c != '%') {
115 putc(action, c);
116 continue;
117 }
118 const char *n = s+1;
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500119 for (;;) {
Kevin O'Connor41d28102008-03-30 23:22:39 -0400120 c = GET_VAR(CS, *(u8*)n);
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500121 if (!isdigit(c))
122 break;
123 n++;
124 }
Kevin O'Connora9096f42008-03-08 15:40:43 -0500125 if (c == 'l') {
126 // Ignore long format indicator
127 n++;
Kevin O'Connor41d28102008-03-30 23:22:39 -0400128 c = GET_VAR(CS, *(u8*)n);
Kevin O'Connora9096f42008-03-08 15:40:43 -0500129 }
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500130 s32 val;
131 const char *sarg;
132 switch (c) {
133 case '%':
134 putc(action, '%');
135 break;
136 case 'd':
137 val = va_arg(args, s32);
138 if (val < 0) {
139 putc(action, '-');
140 val = -val;
141 }
142 putuint(action, val);
143 break;
144 case 'u':
145 val = va_arg(args, s32);
146 putuint(action, val);
147 break;
Kevin O'Connorf06f03a2008-03-29 12:44:32 -0400148 case 'p':
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500149 case 'x':
150 val = va_arg(args, s32);
151 puthex(action, val);
152 break;
Kevin O'Connor12dade52008-03-01 13:35:17 -0500153 case 'c':
154 val = va_arg(args, int);
155 putc(action, val);
156 break;
Kevin O'Connore0113c92008-04-05 15:51:12 -0400157 case '.':
158 // Hack to support "%.s" - meaning string on stack.
159 if (GET_VAR(CS, *(u8*)(n+1)) != 's')
160 break;
161 n++;
162 sarg = va_arg(args, const char *);
163 puts(action, sarg);
164 break;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500165 case 's':
166 sarg = va_arg(args, const char *);
167 puts_cs(action, sarg);
168 break;
169 default:
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500170 putc(action, '%');
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500171 n = s;
172 }
173 s = n;
174 }
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400175}
176
177void
178BX_PANIC(const char *fmt, ...)
179{
180 va_list args;
181 va_start(args, fmt);
182 bvprintf(0, fmt, args);
183 va_end(args);
184
185 // XXX - use PANIC PORT.
186 irq_disable();
187 for (;;)
188 hlt();
189}
190
191void
192BX_INFO(const char *fmt, ...)
193{
194 va_list args;
195 va_start(args, fmt);
196 bvprintf(0, fmt, args);
197 va_end(args);
198}
199
200void
201printf(const char *fmt, ...)
202{
203 va_list args;
204 va_start(args, fmt);
205 bvprintf(1, fmt, args);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500206 va_end(args);
207}
208
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500209static void
210dump_regs(const char *fname, const char *type, struct bregs *regs)
211{
212 if (!regs) {
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400213 BX_INFO("%s %s: NULL\n", type, fname);
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500214 return;
215 }
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400216 BX_INFO("%s %s: a=%x b=%x c=%x d=%x si=%x di=%x\n"
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500217 , type, fname, regs->eax, regs->ebx, regs->ecx, regs->edx
218 , regs->esi, regs->edi);
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400219 BX_INFO(" ds=%x es=%x ip=%x cs=%x f=%x r=%p\n"
Kevin O'Connorf06f03a2008-03-29 12:44:32 -0400220 , regs->ds, regs->es, regs->ip, regs->cs, regs->flags, regs);
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500221}
222
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500223void
Kevin O'Connored128492008-03-11 11:14:59 -0400224__debug_isr(const char *fname)
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500225{
226 puts_cs(0, fname);
227 putc(0, '\n');
228}
229
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500230// Function called on handler startup.
231void
232__debug_enter(const char *fname, struct bregs *regs)
233{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500234 // XXX - implement run time suppression test
235 dump_regs(fname, "enter", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500236}
237
238void
Kevin O'Connor6c781222008-03-09 12:19:23 -0400239__debug_fail(const char *fname, struct bregs *regs)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500240{
Kevin O'Connor6c781222008-03-09 12:19:23 -0400241 dump_regs(fname, "fail", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500242}
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500243
244void
245__debug_stub(const char *fname, struct bregs *regs)
246{
247 dump_regs(fname, "stub", regs);
248}