xref: /freebsd/sys/dev/dcons/dcons.c (revision df57947f083046d50552e99b91074927d2458708)
1098ca2bdSWarner Losh /*-
2*df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3*df57947fSPedro F. Giffuni  *
431a58777SHidetoshi Shimokawa  * Copyright (C) 2003,2004
5869093b1SHidetoshi Shimokawa  * 	Hidetoshi Shimokawa. All rights reserved.
6869093b1SHidetoshi Shimokawa  *
7869093b1SHidetoshi Shimokawa  * Redistribution and use in source and binary forms, with or without
8869093b1SHidetoshi Shimokawa  * modification, are permitted provided that the following conditions
9869093b1SHidetoshi Shimokawa  * are met:
10869093b1SHidetoshi Shimokawa  * 1. Redistributions of source code must retain the above copyright
11869093b1SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer.
12869093b1SHidetoshi Shimokawa  * 2. Redistributions in binary form must reproduce the above copyright
13869093b1SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer in the
14869093b1SHidetoshi Shimokawa  *    documentation and/or other materials provided with the distribution.
15869093b1SHidetoshi Shimokawa  * 3. All advertising materials mentioning features or use of this software
16869093b1SHidetoshi Shimokawa  *    must display the following acknowledgement:
17869093b1SHidetoshi Shimokawa  *
18869093b1SHidetoshi Shimokawa  *	This product includes software developed by Hidetoshi Shimokawa.
19869093b1SHidetoshi Shimokawa  *
20869093b1SHidetoshi Shimokawa  * 4. Neither the name of the author nor the names of its contributors
21869093b1SHidetoshi Shimokawa  *    may be used to endorse or promote products derived from this software
22869093b1SHidetoshi Shimokawa  *    without specific prior written permission.
23869093b1SHidetoshi Shimokawa  *
24869093b1SHidetoshi Shimokawa  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25869093b1SHidetoshi Shimokawa  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26869093b1SHidetoshi Shimokawa  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27869093b1SHidetoshi Shimokawa  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28869093b1SHidetoshi Shimokawa  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29869093b1SHidetoshi Shimokawa  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30869093b1SHidetoshi Shimokawa  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31869093b1SHidetoshi Shimokawa  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32869093b1SHidetoshi Shimokawa  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33869093b1SHidetoshi Shimokawa  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34869093b1SHidetoshi Shimokawa  * SUCH DAMAGE.
35869093b1SHidetoshi Shimokawa  *
36869093b1SHidetoshi Shimokawa  * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $
37869093b1SHidetoshi Shimokawa  * $FreeBSD$
38869093b1SHidetoshi Shimokawa  */
39869093b1SHidetoshi Shimokawa 
40869093b1SHidetoshi Shimokawa #include <sys/param.h>
41869093b1SHidetoshi Shimokawa 
4210f39c7dSHidetoshi Shimokawa #if defined(_BOOT)
4349f159beSWill Andrews #include "dcons.h"
4410f39c7dSHidetoshi Shimokawa #include "stand.h"
455a11c2d9SHidetoshi Shimokawa #else
46869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h>
475a11c2d9SHidetoshi Shimokawa #endif
48869093b1SHidetoshi Shimokawa 
4931a58777SHidetoshi Shimokawa int
5031a58777SHidetoshi Shimokawa dcons_ischar(struct dcons_softc *dc)
51869093b1SHidetoshi Shimokawa {
5231a58777SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
5331a58777SHidetoshi Shimokawa 	struct dcons_ch *ch;
54869093b1SHidetoshi Shimokawa 
5531a58777SHidetoshi Shimokawa 	ch = &dc->i;
56869093b1SHidetoshi Shimokawa 
5731a58777SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
5831a58777SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
5931a58777SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
6031a58777SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
6131a58777SHidetoshi Shimokawa 		return (0);
62869093b1SHidetoshi Shimokawa 
6331a58777SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
6431a58777SHidetoshi Shimokawa 	/* XXX sanity check */
6531a58777SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
6631a58777SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
6731a58777SHidetoshi Shimokawa 		/* generation skipped !! */
6831a58777SHidetoshi Shimokawa 		/* XXX discard */
6931a58777SHidetoshi Shimokawa 		ch->gen = gen;
7031a58777SHidetoshi Shimokawa 		ch->pos = pos;
71869093b1SHidetoshi Shimokawa 		return (0);
72869093b1SHidetoshi Shimokawa 	}
73869093b1SHidetoshi Shimokawa 
7431a58777SHidetoshi Shimokawa 	return (1);
75869093b1SHidetoshi Shimokawa }
76869093b1SHidetoshi Shimokawa 
7731a58777SHidetoshi Shimokawa int
78869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc)
79869093b1SHidetoshi Shimokawa {
80869093b1SHidetoshi Shimokawa 	unsigned char c;
81869093b1SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
82869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
83869093b1SHidetoshi Shimokawa 
84869093b1SHidetoshi Shimokawa 	ch = &dc->i;
85869093b1SHidetoshi Shimokawa 
86869093b1SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
87869093b1SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
88869093b1SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
89869093b1SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
90869093b1SHidetoshi Shimokawa 		return (-1);
91869093b1SHidetoshi Shimokawa 
92869093b1SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
93869093b1SHidetoshi Shimokawa 	/* XXX sanity check */
94869093b1SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
95869093b1SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
96869093b1SHidetoshi Shimokawa 		/* generation skipped !! */
97869093b1SHidetoshi Shimokawa 		/* XXX discard */
98869093b1SHidetoshi Shimokawa 		ch->gen = gen;
99869093b1SHidetoshi Shimokawa 		ch->pos = pos;
100869093b1SHidetoshi Shimokawa 		return (-1);
101869093b1SHidetoshi Shimokawa 	}
102869093b1SHidetoshi Shimokawa 
103869093b1SHidetoshi Shimokawa 	c = ch->buf[ch->pos];
104869093b1SHidetoshi Shimokawa 	ch->pos ++;
105869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
106869093b1SHidetoshi Shimokawa 		ch->gen = next_gen;
107869093b1SHidetoshi Shimokawa 		ch->pos = 0;
108869093b1SHidetoshi Shimokawa 	}
109869093b1SHidetoshi Shimokawa 
110869093b1SHidetoshi Shimokawa 	return (c);
111869093b1SHidetoshi Shimokawa }
112869093b1SHidetoshi Shimokawa 
11331a58777SHidetoshi Shimokawa void
114869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c)
115869093b1SHidetoshi Shimokawa {
116869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
117869093b1SHidetoshi Shimokawa 
118869093b1SHidetoshi Shimokawa 	ch = &dc->o;
119869093b1SHidetoshi Shimokawa 
120869093b1SHidetoshi Shimokawa 	ch->buf[ch->pos] = c;
121869093b1SHidetoshi Shimokawa 	ch->pos ++;
122869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
123869093b1SHidetoshi Shimokawa 		ch->gen = DCONS_NEXT_GEN(ch->gen);
124869093b1SHidetoshi Shimokawa 		ch->pos = 0;
125869093b1SHidetoshi Shimokawa 	}
126869093b1SHidetoshi Shimokawa 	*ch->ptr = DCONS_MAKE_PTR(ch);
127869093b1SHidetoshi Shimokawa }
128869093b1SHidetoshi Shimokawa 
129869093b1SHidetoshi Shimokawa static int
13031a58777SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size, struct dcons_buf *buf,
13131a58777SHidetoshi Shimokawa     struct dcons_softc *sc)
132869093b1SHidetoshi Shimokawa {
133869093b1SHidetoshi Shimokawa 	int osize;
134869093b1SHidetoshi Shimokawa 	struct dcons_softc *dc;
135869093b1SHidetoshi Shimokawa 
136869093b1SHidetoshi Shimokawa 	dc = &sc[port];
137869093b1SHidetoshi Shimokawa 
138869093b1SHidetoshi Shimokawa 	osize = size * 3 / 4;
139869093b1SHidetoshi Shimokawa 
140869093b1SHidetoshi Shimokawa 	dc->o.size = osize;
141869093b1SHidetoshi Shimokawa 	dc->i.size = size - osize;
14231a58777SHidetoshi Shimokawa 	dc->o.buf = (char *)buf + offset;
143869093b1SHidetoshi Shimokawa 	dc->i.buf = dc->o.buf + osize;
144869093b1SHidetoshi Shimokawa 	dc->o.gen = dc->i.gen = 0;
145869093b1SHidetoshi Shimokawa 	dc->o.pos = dc->i.pos = 0;
14631a58777SHidetoshi Shimokawa 	dc->o.ptr = &buf->optr[port];
14731a58777SHidetoshi Shimokawa 	dc->i.ptr = &buf->iptr[port];
148869093b1SHidetoshi Shimokawa 	dc->brk_state = STATE0;
14931a58777SHidetoshi Shimokawa 	buf->osize[port] = htonl(osize);
15031a58777SHidetoshi Shimokawa 	buf->isize[port] = htonl(size - osize);
15131a58777SHidetoshi Shimokawa 	buf->ooffset[port] = htonl(offset);
15231a58777SHidetoshi Shimokawa 	buf->ioffset[port] = htonl(offset + osize);
15331a58777SHidetoshi Shimokawa 	buf->optr[port] = DCONS_MAKE_PTR(&dc->o);
15431a58777SHidetoshi Shimokawa 	buf->iptr[port] = DCONS_MAKE_PTR(&dc->i);
155869093b1SHidetoshi Shimokawa 
156869093b1SHidetoshi Shimokawa 	return(0);
157869093b1SHidetoshi Shimokawa }
158869093b1SHidetoshi Shimokawa 
15931a58777SHidetoshi Shimokawa int
16031a58777SHidetoshi Shimokawa dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc)
161869093b1SHidetoshi Shimokawa {
16231a58777SHidetoshi Shimokawa 	int port, s;
16331a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
164869093b1SHidetoshi Shimokawa 
16531a58777SHidetoshi Shimokawa 	if (buf->version != htonl(DCONS_VERSION))
16631a58777SHidetoshi Shimokawa 		return (-1);
167869093b1SHidetoshi Shimokawa 
16831a58777SHidetoshi Shimokawa 	s = DCONS_HEADER_SIZE;
16931a58777SHidetoshi Shimokawa 	for (port = 0; port < DCONS_NPORT; port ++) {
17031a58777SHidetoshi Shimokawa 		dc = &sc[port];
17131a58777SHidetoshi Shimokawa 		dc->o.size = ntohl(buf->osize[port]);
17231a58777SHidetoshi Shimokawa 		dc->i.size = ntohl(buf->isize[port]);
17331a58777SHidetoshi Shimokawa 		dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]);
17431a58777SHidetoshi Shimokawa 		dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]);
17531a58777SHidetoshi Shimokawa 		dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT;
17631a58777SHidetoshi Shimokawa 		dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT;
17731a58777SHidetoshi Shimokawa 		dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK;
17831a58777SHidetoshi Shimokawa 		dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK;
17931a58777SHidetoshi Shimokawa 		dc->o.ptr = &buf->optr[port];
18031a58777SHidetoshi Shimokawa 		dc->i.ptr = &buf->iptr[port];
18131a58777SHidetoshi Shimokawa 		dc->brk_state = STATE0;
182869093b1SHidetoshi Shimokawa 
18331a58777SHidetoshi Shimokawa 		s += dc->o.size + dc->i.size;
18431a58777SHidetoshi Shimokawa 	}
185869093b1SHidetoshi Shimokawa 
18631a58777SHidetoshi Shimokawa 	/* sanity check */
18731a58777SHidetoshi Shimokawa 	if (s > size)
18831a58777SHidetoshi Shimokawa 		return (-1);
189869093b1SHidetoshi Shimokawa 
19031a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
19131a58777SHidetoshi Shimokawa 
19231a58777SHidetoshi Shimokawa 	return (0);
19331a58777SHidetoshi Shimokawa }
19431a58777SHidetoshi Shimokawa 
19531a58777SHidetoshi Shimokawa void
19631a58777SHidetoshi Shimokawa dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc)
19731a58777SHidetoshi Shimokawa {
19831a58777SHidetoshi Shimokawa 	int size0, size1, offset;
19931a58777SHidetoshi Shimokawa 
200869093b1SHidetoshi Shimokawa 	offset = DCONS_HEADER_SIZE;
20131a58777SHidetoshi Shimokawa 	size0 = (size - offset);
20231a58777SHidetoshi Shimokawa 	size1 = size0 * 3 / 4;		/* console port buffer */
203869093b1SHidetoshi Shimokawa 
20431a58777SHidetoshi Shimokawa 	dcons_init_port(0, offset, size1, buf, sc);
20531a58777SHidetoshi Shimokawa 	offset += size1;
20631a58777SHidetoshi Shimokawa 	dcons_init_port(1, offset, size0 - size1, buf, sc);
20731a58777SHidetoshi Shimokawa 	buf->version = htonl(DCONS_VERSION);
20831a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
209869093b1SHidetoshi Shimokawa }
210