1 // Console input and output.
2 // Input is from the keyboard or serial port.
3 // Output is written to the screen and serial port.
16 static void consputc(int);
18 static int panicked
= 0;
26 printint(int xx
, int base
, int sign
)
28 static char digits
[] = "0123456789abcdef";
33 if(sign
&& (sign
= xx
< 0))
40 buf
[i
++] = digits
[x
% base
];
41 }while((x
/= base
) != 0);
50 // Print to the console. only understands %d, %x, %p, %s.
52 cprintf(char *fmt
, ...)
54 int i
, c
, state
, locking
;
58 locking
= cons
.locking
;
62 argp
= (uint
*)(void*)(&fmt
+ 1);
64 for(i
= 0; (c
= fmt
[i
] & 0xff) != 0; i
++){
74 printint(*argp
++, 10, 1);
78 printint(*argp
++, 16, 0);
81 if((s
= (char*)*argp
++) == 0)
90 // Print unknown % sequence to draw attention.
109 cprintf("cpu%d: panic: ", cpu
->id
);
112 getcallerpcs(&s
, pcs
);
114 cprintf(" %p", pcs
[i
]);
115 panicked
= 1; // freeze other CPU
120 #define BACKSPACE 0x100
121 #define CRTPORT 0x3d4
122 static ushort
*crt
= (ushort
*)0xb8000; // CGA memory
129 // Cursor position: col + 80*row.
131 pos
= inb(CRTPORT
+1) << 8;
133 pos
|= inb(CRTPORT
+1);
137 else if(c
== BACKSPACE
){
140 crt
[pos
++] = (c
&0xff) | 0x0700; // black on white
142 if((pos
/80) >= 24){ // Scroll up.
143 memmove(crt
, crt
+80, sizeof(crt
[0])*23*80);
145 memset(crt
+pos
, 0, sizeof(crt
[0])*(24*80 - pos
));
149 outb(CRTPORT
+1, pos
>>8);
151 outb(CRTPORT
+1, pos
);
152 crt
[pos
] = ' ' | 0x0700;
165 uartputc('\b'); uartputc(' '); uartputc('\b');
171 #define INPUT_BUF 128
173 struct spinlock lock
;
175 uint r
; // Read index
176 uint w
; // Write index
177 uint e
; // Edit index
180 #define C(x) ((x)-'@') // Control-x
183 consoleintr(int (*getc
)(void))
187 acquire(&input
.lock
);
188 while((c
= getc()) >= 0){
190 case C('P'): // Process listing.
193 case C('U'): // Kill line.
194 while(input
.e
!= input
.w
&&
195 input
.buf
[(input
.e
-1) % INPUT_BUF
] != '\n'){
200 case C('H'): case '\x7f': // Backspace
201 if(input
.e
!= input
.w
){
207 if(c
!= 0 && input
.e
-input
.r
< INPUT_BUF
){
208 c
= (c
== '\r') ? '\n' : c
;
209 input
.buf
[input
.e
++ % INPUT_BUF
] = c
;
211 if(c
== '\n' || c
== C('D') || input
.e
== input
.r
+INPUT_BUF
){
219 release(&input
.lock
);
223 consoleread(struct inode
*ip
, char *dst
, int n
)
230 acquire(&input
.lock
);
232 while(input
.r
== input
.w
){
234 release(&input
.lock
);
238 sleep(&input
.r
, &input
.lock
);
240 c
= input
.buf
[input
.r
++ % INPUT_BUF
];
241 if(c
== C('D')){ // EOF
243 // Save ^D for next time, to make sure
244 // caller gets a 0-byte result.
254 release(&input
.lock
);
261 consolewrite(struct inode
*ip
, char *buf
, int n
)
267 for(i
= 0; i
< n
; i
++)
268 consputc(buf
[i
] & 0xff);
278 initlock(&cons
.lock
, "console");
279 initlock(&input
.lock
, "input");
281 devsw
[CONSOLE
].write
= consolewrite
;
282 devsw
[CONSOLE
].read
= consoleread
;
286 ioapicenable(IRQ_KBD
, 0);