comconsole.c revision 120118
118334Speter/*
2169689Skan * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
390075Sobrien *
418334Speter * Redistribution and use in source and binary forms, with or without
590075Sobrien * modification, are permitted provided that the following conditions
618334Speter * are met:
790075Sobrien * 1. Redistributions of source code must retain the above copyright
890075Sobrien *    notice, this list of conditions and the following disclaimer.
990075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1090075Sobrien *    notice, this list of conditions and the following disclaimer in the
1118334Speter *    documentation and/or other materials provided with the distribution.
1290075Sobrien *
1390075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1490075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1590075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1618334Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1718334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1890075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2118334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2290075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2390075Sobrien * SUCH DAMAGE.
2418334Speter */
2550397Sobrien
2652284Sobrien#include <sys/cdefs.h>
2752284Sobrien__FBSDID("$FreeBSD: head/sys/boot/pc98/libpc98/comconsole.c 120118 2003-09-16 11:24:23Z bde $");
2890075Sobrien
29117395Skan#include <stand.h>
30169689Skan#include <bootstrap.h>
31169689Skan#include <machine/cpufunc.h>
32169689Skan#include <dev/ic/ns16550.h>
3318334Speter#include "libi386.h"
3490075Sobrien
3590075Sobrien#define COMC_FMT	0x3		/* 8N1 */
36169689Skan#define COMC_TXWAIT	0x40000		/* transmit timeout */
3790075Sobrien#define COMC_BPS(x)	(115200 / (x))	/* speed to DLAB divisor */
3890075Sobrien
3918334Speter#ifndef	COMPORT
40169689Skan#ifdef PC98
41169689Skan#define COMPORT		0x238
42169689Skan#else
43169689Skan#define COMPORT		0x3f8
44169689Skan#endif
45169689Skan#endif
4690075Sobrien#ifndef	COMSPEED
47169689Skan#define COMSPEED	9600
4890075Sobrien#endif
4950397Sobrien
5050397Sobrienstatic void	comc_probe(struct console *cp);
5118334Speterstatic int	comc_init(int arg);
5250397Sobrienstatic void	comc_putchar(int c);
5350397Sobrienstatic int	comc_getchar(void);
5418334Speterstatic int	comc_ischar(void);
5590075Sobrien
5690075Sobrienstatic int	comc_started;
5790075Sobrien
5850397Sobrienstruct console comconsole = {
59169689Skan    "comconsole",
6018334Speter    "serial port",
6150397Sobrien    0,
62169689Skan    comc_probe,
6318334Speter    comc_init,
6450397Sobrien    comc_putchar,
65169689Skan    comc_getchar,
6618334Speter    comc_ischar
6790075Sobrien};
68169689Skan
6990075Sobrienstatic void
7050397Sobriencomc_probe(struct console *cp)
7150397Sobrien{
72169689Skan    /* XXX check the BIOS equipment list? */
7318334Speter    cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT);
7450397Sobrien}
7550397Sobrien
7650397Sobrienstatic int
7750397Sobriencomc_init(int arg)
7850397Sobrien{
7950397Sobrien    if (comc_started && arg == 0)
8050397Sobrien	return 0;
8150397Sobrien    comc_started = 1;
8250397Sobrien
8350397Sobrien    outb(COMPORT + com_cfcr, CFCR_DLAB | COMC_FMT);
84132718Skan    outb(COMPORT + com_dlbl, COMC_BPS(COMSPEED) & 0xff);
8550397Sobrien    outb(COMPORT + com_dlbh, COMC_BPS(COMSPEED) >> 8);
8650397Sobrien    outb(COMPORT + com_cfcr, COMC_FMT);
8750397Sobrien    outb(COMPORT + com_mcr, MCR_RTS | MCR_DTR);
8890075Sobrien
8950397Sobrien    do
9050397Sobrien        inb(COMPORT + com_data);
91169689Skan    while (inb(COMPORT + com_lsr) & LSR_RXRDY);
92169689Skan
9350397Sobrien    return(0);
9490075Sobrien}
95169689Skan
96169689Skanstatic void
9750397Sobriencomc_putchar(int c)
9850397Sobrien{
9950397Sobrien    int wait;
10090075Sobrien
101169689Skan    for (wait = COMC_TXWAIT; wait > 0; wait--)
102169689Skan        if (inb(COMPORT + com_lsr) & LSR_TXRDY) {
10350397Sobrien	    outb(COMPORT + com_data, (u_char)c);
10450397Sobrien	    break;
10550397Sobrien	}
10690075Sobrien}
107169689Skan
108169689Skanstatic int
10950397Sobriencomc_getchar(void)
110132718Skan{
111132718Skan    return(comc_ischar() ? inb(COMPORT + com_data) : -1);
112132718Skan}
113132718Skan
114132718Skanstatic int
11590075Sobriencomc_ischar(void)
11690075Sobrien{
11752284Sobrien    return(inb(COMPORT + com_lsr) & LSR_RXRDY);
118169689Skan}
119169689Skan