blob: e22b15999a548b405329274171914f68122a9e37 [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
10#include "util.h" // bprintf
11#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++) {
51 char c = GET_VAR(CS, (u8)*s);
52 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'Connorf076a3e2008-02-25 22:25:15 -0500106void
107bprintf(u16 action, const char *fmt, ...)
108{
109 va_list args;
110 va_start(args, fmt);
111 const char *s = fmt;
112 for (;; s++) {
113 char c = GET_VAR(CS, (u8)*s);
114 if (!c)
115 break;
116 if (c != '%') {
117 putc(action, c);
118 continue;
119 }
120 const char *n = s+1;
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500121 for (;;) {
122 c = GET_VAR(CS, (u8)*n);
123 if (!isdigit(c))
124 break;
125 n++;
126 }
Kevin O'Connora9096f42008-03-08 15:40:43 -0500127 if (c == 'l') {
128 // Ignore long format indicator
129 n++;
130 c = GET_VAR(CS, (u8)*n);
131 }
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500132 s32 val;
133 const char *sarg;
134 switch (c) {
135 case '%':
136 putc(action, '%');
137 break;
138 case 'd':
139 val = va_arg(args, s32);
140 if (val < 0) {
141 putc(action, '-');
142 val = -val;
143 }
144 putuint(action, val);
145 break;
146 case 'u':
147 val = va_arg(args, s32);
148 putuint(action, val);
149 break;
150 case 'x':
151 val = va_arg(args, s32);
152 puthex(action, val);
153 break;
Kevin O'Connor12dade52008-03-01 13:35:17 -0500154 case 'c':
155 val = va_arg(args, int);
156 putc(action, val);
157 break;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500158 case 's':
159 sarg = va_arg(args, const char *);
160 puts_cs(action, sarg);
161 break;
162 default:
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500163 putc(action, '%');
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500164 n = s;
165 }
166 s = n;
167 }
168 va_end(args);
169}
170
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500171static void
172dump_regs(const char *fname, const char *type, struct bregs *regs)
173{
174 if (!regs) {
175 bprintf(0, "%s %s: NULL\n", type, fname);
176 return;
177 }
178 bprintf(0, "%s %s: a=%x b=%x c=%x d=%x si=%x di=%x\n"
179 , type, fname, regs->eax, regs->ebx, regs->ecx, regs->edx
180 , regs->esi, regs->edi);
Kevin O'Connor1d019512008-03-11 21:21:47 -0400181 bprintf(0, " ds=%x es=%x ip=%x cs=%x f=%x\n"
182 , regs->ds, regs->es
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500183 , regs->ip, regs->cs, regs->flags);
184}
185
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500186void
Kevin O'Connored128492008-03-11 11:14:59 -0400187__debug_isr(const char *fname)
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500188{
189 puts_cs(0, fname);
190 putc(0, '\n');
191}
192
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500193// Function called on handler startup.
194void
195__debug_enter(const char *fname, struct bregs *regs)
196{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500197 // XXX - implement run time suppression test
198 dump_regs(fname, "enter", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500199}
200
201void
Kevin O'Connor6c781222008-03-09 12:19:23 -0400202__debug_fail(const char *fname, struct bregs *regs)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500203{
Kevin O'Connor6c781222008-03-09 12:19:23 -0400204 dump_regs(fname, "fail", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500205}
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500206
207void
208__debug_stub(const char *fname, struct bregs *regs)
209{
210 dump_regs(fname, "stub", regs);
211}