1 // Console input and output.
2 // Input is from the keyboard or serial port.
3 // Output is written to the screen and serial port.
12 #include "memlayout.h"
17 static void consputc(int);
19 static int panicked
= 0;
27 printint(int xx
, int base
, int sign
)
29 static char digits
[] = "0123456789abcdef";
34 if(sign
&& (sign
= xx
< 0))
41 buf
[i
++] = digits
[x
% base
];
42 }while((x
/= base
) != 0);
52 // Print to the console. only understands %d, %x, %p, %s.
54 cprintf(char *fmt
, ...)
60 locking
= cons
.locking
;
67 argp
= (uint
*)(void*)(&fmt
+ 1);
68 for(i
= 0; (c
= fmt
[i
] & 0xff) != 0; i
++){
78 printint(*argp
++, 10, 1);
82 printint(*argp
++, 16, 0);
85 if((s
= (char*)*argp
++) == 0)
94 // Print unknown % sequence to draw attention.
113 cprintf("cpu%d: panic: ", cpu
->id
);
116 getcallerpcs(&s
, pcs
);
118 cprintf(" %p", pcs
[i
]);
119 panicked
= 1; // freeze other CPU
125 #define BACKSPACE 0x100
126 #define CRTPORT 0x3d4
127 static ushort
*crt
= (ushort
*)P2V(0xb8000); // CGA memory
134 // Cursor position: col + 80*row.
136 pos
= inb(CRTPORT
+1) << 8;
138 pos
|= inb(CRTPORT
+1);
142 else if(c
== BACKSPACE
){
145 crt
[pos
++] = (c
&0xff) | 0x0700; // black on white
147 if((pos
/80) >= 24){ // Scroll up.
148 memmove(crt
, crt
+80, sizeof(crt
[0])*23*80);
150 memset(crt
+pos
, 0, sizeof(crt
[0])*(24*80 - pos
));
154 outb(CRTPORT
+1, pos
>>8);
156 outb(CRTPORT
+1, pos
);
157 crt
[pos
] = ' ' | 0x0700;
170 uartputc('\b'); uartputc(' '); uartputc('\b');
176 #define INPUT_BUF 128
178 struct spinlock lock
;
180 uint r
; // Read index
181 uint w
; // Write index
182 uint e
; // Edit index
185 #define C(x) ((x)-'@') // Control-x
188 consoleintr(int (*getc
)(void))
192 acquire(&input
.lock
);
193 while((c
= getc()) >= 0){
195 case C('P'): // Process listing.
198 case C('U'): // Kill line.
199 while(input
.e
!= input
.w
&&
200 input
.buf
[(input
.e
-1) % INPUT_BUF
] != '\n'){
205 case C('H'): case '\x7f': // Backspace
206 if(input
.e
!= input
.w
){
212 if(c
!= 0 && input
.e
-input
.r
< INPUT_BUF
){
213 c
= (c
== '\r') ? '\n' : c
;
214 input
.buf
[input
.e
++ % INPUT_BUF
] = c
;
216 if(c
== '\n' || c
== C('D') || input
.e
== input
.r
+INPUT_BUF
){
224 release(&input
.lock
);
228 consoleread(struct inode
*ip
, char *dst
, int n
)
235 acquire(&input
.lock
);
237 while(input
.r
== input
.w
){
239 release(&input
.lock
);
243 sleep(&input
.r
, &input
.lock
);
245 c
= input
.buf
[input
.r
++ % INPUT_BUF
];
246 if(c
== C('D')){ // EOF
248 // Save ^D for next time, to make sure
249 // caller gets a 0-byte result.
259 release(&input
.lock
);
266 consolewrite(struct inode
*ip
, char *buf
, int n
)
272 for(i
= 0; i
< n
; i
++)
273 consputc(buf
[i
] & 0xff);
283 initlock(&cons
.lock
, "console");
284 initlock(&input
.lock
, "input");
286 devsw
[CONSOLE
].write
= consolewrite
;
287 devsw
[CONSOLE
].read
= consoleread
;
291 ioapicenable(IRQ_KBD
, 0);