xref: /freebsd/sys/dev/dcons/dcons.c (revision 49f159beefdb052e182816178db93c83abbfb649)
1098ca2bdSWarner Losh /*-
231a58777SHidetoshi Shimokawa  * Copyright (C) 2003,2004
3869093b1SHidetoshi Shimokawa  * 	Hidetoshi Shimokawa. All rights reserved.
4869093b1SHidetoshi Shimokawa  *
5869093b1SHidetoshi Shimokawa  * Redistribution and use in source and binary forms, with or without
6869093b1SHidetoshi Shimokawa  * modification, are permitted provided that the following conditions
7869093b1SHidetoshi Shimokawa  * are met:
8869093b1SHidetoshi Shimokawa  * 1. Redistributions of source code must retain the above copyright
9869093b1SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer.
10869093b1SHidetoshi Shimokawa  * 2. Redistributions in binary form must reproduce the above copyright
11869093b1SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer in the
12869093b1SHidetoshi Shimokawa  *    documentation and/or other materials provided with the distribution.
13869093b1SHidetoshi Shimokawa  * 3. All advertising materials mentioning features or use of this software
14869093b1SHidetoshi Shimokawa  *    must display the following acknowledgement:
15869093b1SHidetoshi Shimokawa  *
16869093b1SHidetoshi Shimokawa  *	This product includes software developed by Hidetoshi Shimokawa.
17869093b1SHidetoshi Shimokawa  *
18869093b1SHidetoshi Shimokawa  * 4. Neither the name of the author nor the names of its contributors
19869093b1SHidetoshi Shimokawa  *    may be used to endorse or promote products derived from this software
20869093b1SHidetoshi Shimokawa  *    without specific prior written permission.
21869093b1SHidetoshi Shimokawa  *
22869093b1SHidetoshi Shimokawa  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23869093b1SHidetoshi Shimokawa  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24869093b1SHidetoshi Shimokawa  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25869093b1SHidetoshi Shimokawa  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26869093b1SHidetoshi Shimokawa  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27869093b1SHidetoshi Shimokawa  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28869093b1SHidetoshi Shimokawa  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29869093b1SHidetoshi Shimokawa  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30869093b1SHidetoshi Shimokawa  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31869093b1SHidetoshi Shimokawa  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32869093b1SHidetoshi Shimokawa  * SUCH DAMAGE.
33869093b1SHidetoshi Shimokawa  *
34869093b1SHidetoshi Shimokawa  * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $
35869093b1SHidetoshi Shimokawa  * $FreeBSD$
36869093b1SHidetoshi Shimokawa  */
37869093b1SHidetoshi Shimokawa 
38869093b1SHidetoshi Shimokawa #include <sys/param.h>
39869093b1SHidetoshi Shimokawa 
4010f39c7dSHidetoshi Shimokawa #if defined(_BOOT)
41*49f159beSWill Andrews #include "dcons.h"
4210f39c7dSHidetoshi Shimokawa #include "stand.h"
435a11c2d9SHidetoshi Shimokawa #else
44869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h>
455a11c2d9SHidetoshi Shimokawa #endif
46869093b1SHidetoshi Shimokawa 
4731a58777SHidetoshi Shimokawa int
4831a58777SHidetoshi Shimokawa dcons_ischar(struct dcons_softc *dc)
49869093b1SHidetoshi Shimokawa {
5031a58777SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
5131a58777SHidetoshi Shimokawa 	struct dcons_ch *ch;
52869093b1SHidetoshi Shimokawa 
5331a58777SHidetoshi Shimokawa 	ch = &dc->i;
54869093b1SHidetoshi Shimokawa 
5531a58777SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
5631a58777SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
5731a58777SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
5831a58777SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
5931a58777SHidetoshi Shimokawa 		return (0);
60869093b1SHidetoshi Shimokawa 
6131a58777SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
6231a58777SHidetoshi Shimokawa 	/* XXX sanity check */
6331a58777SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
6431a58777SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
6531a58777SHidetoshi Shimokawa 		/* generation skipped !! */
6631a58777SHidetoshi Shimokawa 		/* XXX discard */
6731a58777SHidetoshi Shimokawa 		ch->gen = gen;
6831a58777SHidetoshi Shimokawa 		ch->pos = pos;
69869093b1SHidetoshi Shimokawa 		return (0);
70869093b1SHidetoshi Shimokawa 	}
71869093b1SHidetoshi Shimokawa 
7231a58777SHidetoshi Shimokawa 	return (1);
73869093b1SHidetoshi Shimokawa }
74869093b1SHidetoshi Shimokawa 
7531a58777SHidetoshi Shimokawa int
76869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc)
77869093b1SHidetoshi Shimokawa {
78869093b1SHidetoshi Shimokawa 	unsigned char c;
79869093b1SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
80869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
81869093b1SHidetoshi Shimokawa 
82869093b1SHidetoshi Shimokawa 	ch = &dc->i;
83869093b1SHidetoshi Shimokawa 
84869093b1SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
85869093b1SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
86869093b1SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
87869093b1SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
88869093b1SHidetoshi Shimokawa 		return (-1);
89869093b1SHidetoshi Shimokawa 
90869093b1SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
91869093b1SHidetoshi Shimokawa 	/* XXX sanity check */
92869093b1SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
93869093b1SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
94869093b1SHidetoshi Shimokawa 		/* generation skipped !! */
95869093b1SHidetoshi Shimokawa 		/* XXX discard */
96869093b1SHidetoshi Shimokawa 		ch->gen = gen;
97869093b1SHidetoshi Shimokawa 		ch->pos = pos;
98869093b1SHidetoshi Shimokawa 		return (-1);
99869093b1SHidetoshi Shimokawa 	}
100869093b1SHidetoshi Shimokawa 
101869093b1SHidetoshi Shimokawa 	c = ch->buf[ch->pos];
102869093b1SHidetoshi Shimokawa 	ch->pos ++;
103869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
104869093b1SHidetoshi Shimokawa 		ch->gen = next_gen;
105869093b1SHidetoshi Shimokawa 		ch->pos = 0;
106869093b1SHidetoshi Shimokawa 	}
107869093b1SHidetoshi Shimokawa 
108869093b1SHidetoshi Shimokawa 	return (c);
109869093b1SHidetoshi Shimokawa }
110869093b1SHidetoshi Shimokawa 
11131a58777SHidetoshi Shimokawa void
112869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c)
113869093b1SHidetoshi Shimokawa {
114869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
115869093b1SHidetoshi Shimokawa 
116869093b1SHidetoshi Shimokawa 	ch = &dc->o;
117869093b1SHidetoshi Shimokawa 
118869093b1SHidetoshi Shimokawa 	ch->buf[ch->pos] = c;
119869093b1SHidetoshi Shimokawa 	ch->pos ++;
120869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
121869093b1SHidetoshi Shimokawa 		ch->gen = DCONS_NEXT_GEN(ch->gen);
122869093b1SHidetoshi Shimokawa 		ch->pos = 0;
123869093b1SHidetoshi Shimokawa 	}
124869093b1SHidetoshi Shimokawa 	*ch->ptr = DCONS_MAKE_PTR(ch);
125869093b1SHidetoshi Shimokawa }
126869093b1SHidetoshi Shimokawa 
127869093b1SHidetoshi Shimokawa static int
12831a58777SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size, struct dcons_buf *buf,
12931a58777SHidetoshi Shimokawa     struct dcons_softc *sc)
130869093b1SHidetoshi Shimokawa {
131869093b1SHidetoshi Shimokawa 	int osize;
132869093b1SHidetoshi Shimokawa 	struct dcons_softc *dc;
133869093b1SHidetoshi Shimokawa 
134869093b1SHidetoshi Shimokawa 	dc = &sc[port];
135869093b1SHidetoshi Shimokawa 
136869093b1SHidetoshi Shimokawa 	osize = size * 3 / 4;
137869093b1SHidetoshi Shimokawa 
138869093b1SHidetoshi Shimokawa 	dc->o.size = osize;
139869093b1SHidetoshi Shimokawa 	dc->i.size = size - osize;
14031a58777SHidetoshi Shimokawa 	dc->o.buf = (char *)buf + offset;
141869093b1SHidetoshi Shimokawa 	dc->i.buf = dc->o.buf + osize;
142869093b1SHidetoshi Shimokawa 	dc->o.gen = dc->i.gen = 0;
143869093b1SHidetoshi Shimokawa 	dc->o.pos = dc->i.pos = 0;
14431a58777SHidetoshi Shimokawa 	dc->o.ptr = &buf->optr[port];
14531a58777SHidetoshi Shimokawa 	dc->i.ptr = &buf->iptr[port];
146869093b1SHidetoshi Shimokawa 	dc->brk_state = STATE0;
14731a58777SHidetoshi Shimokawa 	buf->osize[port] = htonl(osize);
14831a58777SHidetoshi Shimokawa 	buf->isize[port] = htonl(size - osize);
14931a58777SHidetoshi Shimokawa 	buf->ooffset[port] = htonl(offset);
15031a58777SHidetoshi Shimokawa 	buf->ioffset[port] = htonl(offset + osize);
15131a58777SHidetoshi Shimokawa 	buf->optr[port] = DCONS_MAKE_PTR(&dc->o);
15231a58777SHidetoshi Shimokawa 	buf->iptr[port] = DCONS_MAKE_PTR(&dc->i);
153869093b1SHidetoshi Shimokawa 
154869093b1SHidetoshi Shimokawa 	return(0);
155869093b1SHidetoshi Shimokawa }
156869093b1SHidetoshi Shimokawa 
15731a58777SHidetoshi Shimokawa int
15831a58777SHidetoshi Shimokawa dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc)
159869093b1SHidetoshi Shimokawa {
16031a58777SHidetoshi Shimokawa 	int port, s;
16131a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
162869093b1SHidetoshi Shimokawa 
16331a58777SHidetoshi Shimokawa 	if (buf->version != htonl(DCONS_VERSION))
16431a58777SHidetoshi Shimokawa 		return (-1);
165869093b1SHidetoshi Shimokawa 
16631a58777SHidetoshi Shimokawa 	s = DCONS_HEADER_SIZE;
16731a58777SHidetoshi Shimokawa 	for (port = 0; port < DCONS_NPORT; port ++) {
16831a58777SHidetoshi Shimokawa 		dc = &sc[port];
16931a58777SHidetoshi Shimokawa 		dc->o.size = ntohl(buf->osize[port]);
17031a58777SHidetoshi Shimokawa 		dc->i.size = ntohl(buf->isize[port]);
17131a58777SHidetoshi Shimokawa 		dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]);
17231a58777SHidetoshi Shimokawa 		dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]);
17331a58777SHidetoshi Shimokawa 		dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT;
17431a58777SHidetoshi Shimokawa 		dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT;
17531a58777SHidetoshi Shimokawa 		dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK;
17631a58777SHidetoshi Shimokawa 		dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK;
17731a58777SHidetoshi Shimokawa 		dc->o.ptr = &buf->optr[port];
17831a58777SHidetoshi Shimokawa 		dc->i.ptr = &buf->iptr[port];
17931a58777SHidetoshi Shimokawa 		dc->brk_state = STATE0;
180869093b1SHidetoshi Shimokawa 
18131a58777SHidetoshi Shimokawa 		s += dc->o.size + dc->i.size;
18231a58777SHidetoshi Shimokawa 	}
183869093b1SHidetoshi Shimokawa 
18431a58777SHidetoshi Shimokawa 	/* sanity check */
18531a58777SHidetoshi Shimokawa 	if (s > size)
18631a58777SHidetoshi Shimokawa 		return (-1);
187869093b1SHidetoshi Shimokawa 
18831a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
18931a58777SHidetoshi Shimokawa 
19031a58777SHidetoshi Shimokawa 	return (0);
19131a58777SHidetoshi Shimokawa }
19231a58777SHidetoshi Shimokawa 
19331a58777SHidetoshi Shimokawa void
19431a58777SHidetoshi Shimokawa dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc)
19531a58777SHidetoshi Shimokawa {
19631a58777SHidetoshi Shimokawa 	int size0, size1, offset;
19731a58777SHidetoshi Shimokawa 
198869093b1SHidetoshi Shimokawa 	offset = DCONS_HEADER_SIZE;
19931a58777SHidetoshi Shimokawa 	size0 = (size - offset);
20031a58777SHidetoshi Shimokawa 	size1 = size0 * 3 / 4;		/* console port buffer */
201869093b1SHidetoshi Shimokawa 
20231a58777SHidetoshi Shimokawa 	dcons_init_port(0, offset, size1, buf, sc);
20331a58777SHidetoshi Shimokawa 	offset += size1;
20431a58777SHidetoshi Shimokawa 	dcons_init_port(1, offset, size0 - size1, buf, sc);
20531a58777SHidetoshi Shimokawa 	buf->version = htonl(DCONS_VERSION);
20631a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
207869093b1SHidetoshi Shimokawa }
208