xref: /freebsd/sys/dev/dcons/dcons.c (revision 2ff63af9b88c7413b7d71715b5532625752a248e)
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  */
38869093b1SHidetoshi Shimokawa 
39869093b1SHidetoshi Shimokawa #include <sys/param.h>
40869093b1SHidetoshi Shimokawa 
4110f39c7dSHidetoshi Shimokawa #if defined(_BOOT)
4249f159beSWill Andrews #include "dcons.h"
4310f39c7dSHidetoshi Shimokawa #include "stand.h"
445a11c2d9SHidetoshi Shimokawa #else
45869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h>
465a11c2d9SHidetoshi Shimokawa #endif
47869093b1SHidetoshi Shimokawa 
4831a58777SHidetoshi Shimokawa int
dcons_ischar(struct dcons_softc * dc)4931a58777SHidetoshi Shimokawa dcons_ischar(struct dcons_softc *dc)
50869093b1SHidetoshi Shimokawa {
5131a58777SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
5231a58777SHidetoshi Shimokawa 	struct dcons_ch *ch;
53869093b1SHidetoshi Shimokawa 
5431a58777SHidetoshi Shimokawa 	ch = &dc->i;
55869093b1SHidetoshi Shimokawa 
5631a58777SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
5731a58777SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
5831a58777SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
5931a58777SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
6031a58777SHidetoshi Shimokawa 		return (0);
61869093b1SHidetoshi Shimokawa 
6231a58777SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
6331a58777SHidetoshi Shimokawa 	/* XXX sanity check */
6431a58777SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
6531a58777SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
6631a58777SHidetoshi Shimokawa 		/* generation skipped !! */
6731a58777SHidetoshi Shimokawa 		/* XXX discard */
6831a58777SHidetoshi Shimokawa 		ch->gen = gen;
6931a58777SHidetoshi Shimokawa 		ch->pos = pos;
70869093b1SHidetoshi Shimokawa 		return (0);
71869093b1SHidetoshi Shimokawa 	}
72869093b1SHidetoshi Shimokawa 
7331a58777SHidetoshi Shimokawa 	return (1);
74869093b1SHidetoshi Shimokawa }
75869093b1SHidetoshi Shimokawa 
7631a58777SHidetoshi Shimokawa int
dcons_checkc(struct dcons_softc * dc)77869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc)
78869093b1SHidetoshi Shimokawa {
79869093b1SHidetoshi Shimokawa 	unsigned char c;
80869093b1SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
81869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
82869093b1SHidetoshi Shimokawa 
83869093b1SHidetoshi Shimokawa 	ch = &dc->i;
84869093b1SHidetoshi Shimokawa 
85869093b1SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
86869093b1SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
87869093b1SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
88869093b1SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
89869093b1SHidetoshi Shimokawa 		return (-1);
90869093b1SHidetoshi Shimokawa 
91869093b1SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
92869093b1SHidetoshi Shimokawa 	/* XXX sanity check */
93869093b1SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
94869093b1SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
95869093b1SHidetoshi Shimokawa 		/* generation skipped !! */
96869093b1SHidetoshi Shimokawa 		/* XXX discard */
97869093b1SHidetoshi Shimokawa 		ch->gen = gen;
98869093b1SHidetoshi Shimokawa 		ch->pos = pos;
99869093b1SHidetoshi Shimokawa 		return (-1);
100869093b1SHidetoshi Shimokawa 	}
101869093b1SHidetoshi Shimokawa 
102869093b1SHidetoshi Shimokawa 	c = ch->buf[ch->pos];
103869093b1SHidetoshi Shimokawa 	ch->pos ++;
104869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
105869093b1SHidetoshi Shimokawa 		ch->gen = next_gen;
106869093b1SHidetoshi Shimokawa 		ch->pos = 0;
107869093b1SHidetoshi Shimokawa 	}
108869093b1SHidetoshi Shimokawa 
109869093b1SHidetoshi Shimokawa 	return (c);
110869093b1SHidetoshi Shimokawa }
111869093b1SHidetoshi Shimokawa 
11231a58777SHidetoshi Shimokawa void
dcons_putc(struct dcons_softc * dc,int c)113869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c)
114869093b1SHidetoshi Shimokawa {
115869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
116869093b1SHidetoshi Shimokawa 
117869093b1SHidetoshi Shimokawa 	ch = &dc->o;
118869093b1SHidetoshi Shimokawa 
119869093b1SHidetoshi Shimokawa 	ch->buf[ch->pos] = c;
120869093b1SHidetoshi Shimokawa 	ch->pos ++;
121869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
122869093b1SHidetoshi Shimokawa 		ch->gen = DCONS_NEXT_GEN(ch->gen);
123869093b1SHidetoshi Shimokawa 		ch->pos = 0;
124869093b1SHidetoshi Shimokawa 	}
125869093b1SHidetoshi Shimokawa 	*ch->ptr = DCONS_MAKE_PTR(ch);
126869093b1SHidetoshi Shimokawa }
127869093b1SHidetoshi Shimokawa 
128869093b1SHidetoshi Shimokawa static int
dcons_init_port(int port,int offset,int size,struct dcons_buf * buf,struct dcons_softc * sc)12931a58777SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size, struct dcons_buf *buf,
13031a58777SHidetoshi Shimokawa     struct dcons_softc *sc)
131869093b1SHidetoshi Shimokawa {
132869093b1SHidetoshi Shimokawa 	int osize;
133869093b1SHidetoshi Shimokawa 	struct dcons_softc *dc;
134869093b1SHidetoshi Shimokawa 
135869093b1SHidetoshi Shimokawa 	dc = &sc[port];
136869093b1SHidetoshi Shimokawa 
137869093b1SHidetoshi Shimokawa 	osize = size * 3 / 4;
138869093b1SHidetoshi Shimokawa 
139869093b1SHidetoshi Shimokawa 	dc->o.size = osize;
140869093b1SHidetoshi Shimokawa 	dc->i.size = size - osize;
14131a58777SHidetoshi Shimokawa 	dc->o.buf = (char *)buf + offset;
142869093b1SHidetoshi Shimokawa 	dc->i.buf = dc->o.buf + osize;
143869093b1SHidetoshi Shimokawa 	dc->o.gen = dc->i.gen = 0;
144869093b1SHidetoshi Shimokawa 	dc->o.pos = dc->i.pos = 0;
14531a58777SHidetoshi Shimokawa 	dc->o.ptr = &buf->optr[port];
14631a58777SHidetoshi Shimokawa 	dc->i.ptr = &buf->iptr[port];
147869093b1SHidetoshi Shimokawa 	dc->brk_state = STATE0;
14831a58777SHidetoshi Shimokawa 	buf->osize[port] = htonl(osize);
14931a58777SHidetoshi Shimokawa 	buf->isize[port] = htonl(size - osize);
15031a58777SHidetoshi Shimokawa 	buf->ooffset[port] = htonl(offset);
15131a58777SHidetoshi Shimokawa 	buf->ioffset[port] = htonl(offset + osize);
15231a58777SHidetoshi Shimokawa 	buf->optr[port] = DCONS_MAKE_PTR(&dc->o);
15331a58777SHidetoshi Shimokawa 	buf->iptr[port] = DCONS_MAKE_PTR(&dc->i);
154869093b1SHidetoshi Shimokawa 
155869093b1SHidetoshi Shimokawa 	return(0);
156869093b1SHidetoshi Shimokawa }
157869093b1SHidetoshi Shimokawa 
15831a58777SHidetoshi Shimokawa int
dcons_load_buffer(struct dcons_buf * buf,int size,struct dcons_softc * sc)15931a58777SHidetoshi Shimokawa dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc)
160869093b1SHidetoshi Shimokawa {
16131a58777SHidetoshi Shimokawa 	int port, s;
16231a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
163869093b1SHidetoshi Shimokawa 
16431a58777SHidetoshi Shimokawa 	if (buf->version != htonl(DCONS_VERSION))
16531a58777SHidetoshi Shimokawa 		return (-1);
166869093b1SHidetoshi Shimokawa 
16731a58777SHidetoshi Shimokawa 	s = DCONS_HEADER_SIZE;
16831a58777SHidetoshi Shimokawa 	for (port = 0; port < DCONS_NPORT; port ++) {
16931a58777SHidetoshi Shimokawa 		dc = &sc[port];
17031a58777SHidetoshi Shimokawa 		dc->o.size = ntohl(buf->osize[port]);
17131a58777SHidetoshi Shimokawa 		dc->i.size = ntohl(buf->isize[port]);
17231a58777SHidetoshi Shimokawa 		dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]);
17331a58777SHidetoshi Shimokawa 		dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]);
17431a58777SHidetoshi Shimokawa 		dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT;
17531a58777SHidetoshi Shimokawa 		dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT;
17631a58777SHidetoshi Shimokawa 		dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK;
17731a58777SHidetoshi Shimokawa 		dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK;
17831a58777SHidetoshi Shimokawa 		dc->o.ptr = &buf->optr[port];
17931a58777SHidetoshi Shimokawa 		dc->i.ptr = &buf->iptr[port];
18031a58777SHidetoshi Shimokawa 		dc->brk_state = STATE0;
181869093b1SHidetoshi Shimokawa 
18231a58777SHidetoshi Shimokawa 		s += dc->o.size + dc->i.size;
18331a58777SHidetoshi Shimokawa 	}
184869093b1SHidetoshi Shimokawa 
18531a58777SHidetoshi Shimokawa 	/* sanity check */
18631a58777SHidetoshi Shimokawa 	if (s > size)
18731a58777SHidetoshi Shimokawa 		return (-1);
188869093b1SHidetoshi Shimokawa 
18931a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
19031a58777SHidetoshi Shimokawa 
19131a58777SHidetoshi Shimokawa 	return (0);
19231a58777SHidetoshi Shimokawa }
19331a58777SHidetoshi Shimokawa 
19431a58777SHidetoshi Shimokawa void
dcons_init(struct dcons_buf * buf,int size,struct dcons_softc * sc)19531a58777SHidetoshi Shimokawa dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc)
19631a58777SHidetoshi Shimokawa {
19731a58777SHidetoshi Shimokawa 	int size0, size1, offset;
19831a58777SHidetoshi Shimokawa 
199869093b1SHidetoshi Shimokawa 	offset = DCONS_HEADER_SIZE;
20031a58777SHidetoshi Shimokawa 	size0 = (size - offset);
20131a58777SHidetoshi Shimokawa 	size1 = size0 * 3 / 4;		/* console port buffer */
202869093b1SHidetoshi Shimokawa 
20331a58777SHidetoshi Shimokawa 	dcons_init_port(0, offset, size1, buf, sc);
20431a58777SHidetoshi Shimokawa 	offset += size1;
20531a58777SHidetoshi Shimokawa 	dcons_init_port(1, offset, size0 - size1, buf, sc);
20631a58777SHidetoshi Shimokawa 	buf->version = htonl(DCONS_VERSION);
20731a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
208869093b1SHidetoshi Shimokawa }
209