1/*-
2 * Copyright (c) 2015 Martin Lucina.  All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
14 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <hw/types.h>
27#include <hw/kernel.h>
28#include <bmk-core/printf.h>
29
30#include <arch/x86/cons.h>
31#include <arch/x86/tsc.h>
32
33static uint16_t combase = 0;
34
35void
36serialcons_init(uint16_t combase_init, int speed)
37{
38	uint16_t divisor = 115200 / speed;
39
40	combase = combase_init;
41	outb(combase + COM_IER, 0x00);
42	outb(combase + COM_LCTL, 0x80);
43	outb(combase + COM_DLBL, divisor & 0xff);
44	outb(combase + COM_DLBH, divisor >> 8);
45	outb(combase + COM_LCTL, 0x03);
46	outb(combase + COM_FIFO, 0xc7);
47	outb(combase + 4, 0x0b); /* modem control register: set DTR/RTS/OUT2 */
48	inb(combase);     /* clear recevier port */
49	inb(combase + 5); /* clear line status port */
50	inb(combase + 6); /* clear modem status port */
51	outb(combase + COM_IER, 0x01);
52	// drain
53    while ((inb(combase + 5) & 1) != 0) {
54        inb(combase);
55    }
56
57}
58char reset_buffer[] = "reset";
59int pos = 0;
60uint64_t cpucount = 0;
61uint64_t cpucount2 = 0;
62extern uint64_t ccount;
63unsigned char getDebugChar(void);
64unsigned char getDebugChar(void)
65{
66    char c = 0;
67
68    while ((inb(combase + 5) & 1) == 0);
69
70    while ((inb(combase + 5) & 1) != 0) {
71        c = inb(combase);
72        if (c == reset_buffer[pos]) {
73            pos++;
74            if (pos == 5) {
75                outb(0x64, 0xFE);
76            }
77        } else {
78            pos = 0;
79        }
80		if (c == 'a') {
81			cpucount = rdtsc_pure();
82			ccount = 0;
83		}
84
85		if (c == 'b') {
86			cpucount2 = rdtsc_pure();
87			bmk_printf("tot: %ld\n idle: %ld\n", cpucount2 - cpucount, ccount);
88
89		}
90    }
91	if (c == '\r')
92		c = '\n';
93    return c;
94}
95
96void
97serialcons_putc(int c)
98{
99
100	if (!combase)
101		return;
102	if (c == '\n')
103		serialcons_putc('\r');
104
105	/*
106	 * Write a single character at a time, while the output FIFO has space.
107	 */
108	while ((inb(combase + COM_LSR) & 0x20) == 0)
109		;
110	outb(combase + COM_DATA, c);
111}
112