X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Fserial.c;fp=geekos%2Fsrc%2Fgeekos%2Fserial.c;h=c698dbbeb3d529055e20ab29737fb054adb0af22;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/serial.c b/geekos/src/geekos/serial.c new file mode 100644 index 0000000..c698dbb --- /dev/null +++ b/geekos/src/geekos/serial.c @@ -0,0 +1,223 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Peter Dinda + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Peter Dinda + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include +#include + + + + +unsigned short serial_io_addr = 0; +uint_t serial_print_level; + +static void Serial_Interrupt_Handler(struct Interrupt_State * state) { + char rcv_byte; + char irq_id; + + Begin_IRQ(state); + + irq_id = In_Byte(serial_io_addr + 2); + + + if ((irq_id & 0x04) != 0) { + rcv_byte = In_Byte(serial_io_addr + 0); + + if (rcv_byte == 'k') { + SerialPrint("Restarting Machine\r\n"); + machine_real_restart(); + } else if (rcv_byte=='d') { + SerialPrint("Dumping Machine State\n"); + Dump_Interrupt_State(state); + DumpIDT(); + DumpGDT(); + } + +#if 0 + SerialPrint("Unreserved serial byte: %d (%c)\r\n", rcv_byte, rcv_byte); +#endif + } + End_IRQ(state); +} + + + +void InitSerialAddr(unsigned short io_addr) { + serial_io_addr = io_addr; + + Print("Initializing Polled Serial Output on COM1 - 115200 N81 noflow\n"); + // io_adr = 0x3F8; /* 3F8=COM1, 2F8=COM2, 3E8=COM3, 2E8=COM4 */ + Out_Byte(io_addr + 3, 0x80); + // 115200 /* 115200 / 12 = 9600 baud */ + Out_Byte(io_addr + 0, 1); + Out_Byte(io_addr + 1, 0); + /* 8N1 */ + Out_Byte(io_addr + 3, 0x03); + /* all interrupts disabled */ + // Out_Byte(io_addr + 1, 0); + Out_Byte(io_addr + 1, 0x01); + /* turn off FIFO, if any */ + Out_Byte(io_addr + 2, 0); + /* loopback off, interrupts (Out2) off, Out1/RTS/DTR off */ + // Out_Byte(io_addr + 4, 0); + // enable interrupts (bit 3) + Out_Byte(io_addr + 4, 0x08); +} + + + + +void SerialPutChar(unsigned char c) { + + // static unsigned short io_adr; + if (serial_io_addr==0) { + return; + } + + + if (c=='\n') { + /* wait for transmitter ready */ + while((In_Byte(serial_io_addr + 5) & 0x40) == 0) { + } + /* send char */ + Out_Byte(serial_io_addr + 0, '\r'); + /* wait for transmitter ready */ + } + while((In_Byte(serial_io_addr + 5) & 0x40) == 0) { + } + /* send char */ + Out_Byte(serial_io_addr + 0, c); +} + + + +void SerialPutLineN(char * line, int len) { + int i; + for (i = 0; i < len && line[i] != 0; i++) { + SerialPutChar(line[i]); + } +} + + +void SerialPutLine(char * line) { + int i; + for (i = 0; line[i]!= 0; i++) { + SerialPutChar(line[i]); + } +} + + +void SerialPrintHex(unsigned char x) +{ + unsigned char z; + + z = (x>>4) & 0xf ; + SerialPrint("%x", z); + z = x & 0xf; + SerialPrint("%x", z); +} + +void SerialMemDump(unsigned char *start, int n) +{ + int i, j; + + for (i=0;i=32) && (start[j]<=126)) ? start[j] : '.'); + } + SerialPrint("\n"); + } +} + + +static struct Output_Sink serial_output_sink; +static void Serial_Emit(struct Output_Sink * o, int ch) { + SerialPutChar((unsigned char)ch); +} +static void Serial_Finish(struct Output_Sink * o) { return; } + + +static void __inline__ SerialPrintInternal(const char * format, va_list ap) { + Format_Output(&serial_output_sink, format, ap); +} + + +void SerialPrint(const char * format, ...) { + va_list args; + bool iflag = Begin_Int_Atomic(); + + va_start(args, format); + SerialPrintInternal(format, args); + va_end(args); + + End_Int_Atomic(iflag); +} + +void SerialPrintList(const char * format, va_list ap) { + bool iflag = Begin_Int_Atomic(); + SerialPrintInternal(format, ap); + End_Int_Atomic(iflag); + +} + + + + +void SerialPrintLevel(int level, const char * format, ...) { + if (level > serial_print_level) { + va_list args; + bool iflag = Begin_Int_Atomic(); + + va_start(args, format); + SerialPrintInternal(format, args); + va_end(args); + + End_Int_Atomic(iflag); + } +} + + + + +void Init_Serial() { + + serial_print_level = SERIAL_PRINT_DEBUG_LEVEL; + + Print("Initialzing Serial\n"); + + serial_output_sink.Emit = &Serial_Emit; + serial_output_sink.Finish = &Serial_Finish; + + Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler); + Enable_IRQ(COM1_IRQ); + InitSerialAddr(DEFAULT_SERIAL_ADDR); +}