xref: /freebsd/sys/dev/dcons/dcons.c (revision 31a58777865b45a056dd435ea8ecf426bed54985)
1869093b1SHidetoshi Shimokawa /*
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 
4031a58777SHidetoshi Shimokawa #if defined(__DragonFly__) || defined(_BOOT)
415a11c2d9SHidetoshi Shimokawa #include "dcons.h"
425a11c2d9SHidetoshi Shimokawa #else
43869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h>
445a11c2d9SHidetoshi Shimokawa #endif
45869093b1SHidetoshi Shimokawa 
4631a58777SHidetoshi Shimokawa int
4731a58777SHidetoshi Shimokawa dcons_ischar(struct dcons_softc *dc)
48869093b1SHidetoshi Shimokawa {
4931a58777SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
5031a58777SHidetoshi Shimokawa 	struct dcons_ch *ch;
51869093b1SHidetoshi Shimokawa 
5231a58777SHidetoshi Shimokawa 	ch = &dc->i;
53869093b1SHidetoshi Shimokawa 
5431a58777SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
5531a58777SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
5631a58777SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
5731a58777SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
5831a58777SHidetoshi Shimokawa 		return (0);
59869093b1SHidetoshi Shimokawa 
6031a58777SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
6131a58777SHidetoshi Shimokawa 	/* XXX sanity check */
6231a58777SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
6331a58777SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
6431a58777SHidetoshi Shimokawa 		/* generation skipped !! */
6531a58777SHidetoshi Shimokawa 		/* XXX discard */
6631a58777SHidetoshi Shimokawa 		ch->gen = gen;
6731a58777SHidetoshi Shimokawa 		ch->pos = pos;
68869093b1SHidetoshi Shimokawa 		return (0);
69869093b1SHidetoshi Shimokawa 	}
70869093b1SHidetoshi Shimokawa 
7131a58777SHidetoshi Shimokawa 	return (1);
72869093b1SHidetoshi Shimokawa }
73869093b1SHidetoshi Shimokawa 
7431a58777SHidetoshi Shimokawa int
75869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc)
76869093b1SHidetoshi Shimokawa {
77869093b1SHidetoshi Shimokawa 	unsigned char c;
78869093b1SHidetoshi Shimokawa 	u_int32_t ptr, pos, gen, next_gen;
79869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
80869093b1SHidetoshi Shimokawa 
81869093b1SHidetoshi Shimokawa 	ch = &dc->i;
82869093b1SHidetoshi Shimokawa 
83869093b1SHidetoshi Shimokawa 	ptr = ntohl(*ch->ptr);
84869093b1SHidetoshi Shimokawa 	gen = ptr >> DCONS_GEN_SHIFT;
85869093b1SHidetoshi Shimokawa 	pos = ptr & DCONS_POS_MASK;
86869093b1SHidetoshi Shimokawa 	if (gen == ch->gen && pos == ch->pos)
87869093b1SHidetoshi Shimokawa 		return (-1);
88869093b1SHidetoshi Shimokawa 
89869093b1SHidetoshi Shimokawa 	next_gen = DCONS_NEXT_GEN(ch->gen);
90869093b1SHidetoshi Shimokawa 	/* XXX sanity check */
91869093b1SHidetoshi Shimokawa 	if ((gen != ch->gen && gen != next_gen)
92869093b1SHidetoshi Shimokawa 			|| (gen == ch->gen && pos < ch->pos)) {
93869093b1SHidetoshi Shimokawa 		/* generation skipped !! */
94869093b1SHidetoshi Shimokawa 		/* XXX discard */
95869093b1SHidetoshi Shimokawa 		ch->gen = gen;
96869093b1SHidetoshi Shimokawa 		ch->pos = pos;
97869093b1SHidetoshi Shimokawa 		return (-1);
98869093b1SHidetoshi Shimokawa 	}
99869093b1SHidetoshi Shimokawa 
100869093b1SHidetoshi Shimokawa 	c = ch->buf[ch->pos];
101869093b1SHidetoshi Shimokawa 	ch->pos ++;
102869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
103869093b1SHidetoshi Shimokawa 		ch->gen = next_gen;
104869093b1SHidetoshi Shimokawa 		ch->pos = 0;
105869093b1SHidetoshi Shimokawa 	}
106869093b1SHidetoshi Shimokawa 
107869093b1SHidetoshi Shimokawa 	return (c);
108869093b1SHidetoshi Shimokawa }
109869093b1SHidetoshi Shimokawa 
11031a58777SHidetoshi Shimokawa void
111869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c)
112869093b1SHidetoshi Shimokawa {
113869093b1SHidetoshi Shimokawa 	struct dcons_ch *ch;
114869093b1SHidetoshi Shimokawa 
115869093b1SHidetoshi Shimokawa 	ch = &dc->o;
116869093b1SHidetoshi Shimokawa 
117869093b1SHidetoshi Shimokawa 	ch->buf[ch->pos] = c;
118869093b1SHidetoshi Shimokawa 	ch->pos ++;
119869093b1SHidetoshi Shimokawa 	if (ch->pos >= ch->size) {
120869093b1SHidetoshi Shimokawa 		ch->gen = DCONS_NEXT_GEN(ch->gen);
121869093b1SHidetoshi Shimokawa 		ch->pos = 0;
122869093b1SHidetoshi Shimokawa 	}
123869093b1SHidetoshi Shimokawa 	*ch->ptr = DCONS_MAKE_PTR(ch);
124869093b1SHidetoshi Shimokawa }
125869093b1SHidetoshi Shimokawa 
126869093b1SHidetoshi Shimokawa static int
12731a58777SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size, struct dcons_buf *buf,
12831a58777SHidetoshi Shimokawa     struct dcons_softc *sc)
129869093b1SHidetoshi Shimokawa {
130869093b1SHidetoshi Shimokawa 	int osize;
131869093b1SHidetoshi Shimokawa 	struct dcons_softc *dc;
132869093b1SHidetoshi Shimokawa 
133869093b1SHidetoshi Shimokawa 	dc = &sc[port];
134869093b1SHidetoshi Shimokawa 
135869093b1SHidetoshi Shimokawa 	osize = size * 3 / 4;
136869093b1SHidetoshi Shimokawa 
137869093b1SHidetoshi Shimokawa 	dc->o.size = osize;
138869093b1SHidetoshi Shimokawa 	dc->i.size = size - osize;
13931a58777SHidetoshi Shimokawa 	dc->o.buf = (char *)buf + offset;
140869093b1SHidetoshi Shimokawa 	dc->i.buf = dc->o.buf + osize;
141869093b1SHidetoshi Shimokawa 	dc->o.gen = dc->i.gen = 0;
142869093b1SHidetoshi Shimokawa 	dc->o.pos = dc->i.pos = 0;
14331a58777SHidetoshi Shimokawa 	dc->o.ptr = &buf->optr[port];
14431a58777SHidetoshi Shimokawa 	dc->i.ptr = &buf->iptr[port];
145869093b1SHidetoshi Shimokawa 	dc->brk_state = STATE0;
14631a58777SHidetoshi Shimokawa 	buf->osize[port] = htonl(osize);
14731a58777SHidetoshi Shimokawa 	buf->isize[port] = htonl(size - osize);
14831a58777SHidetoshi Shimokawa 	buf->ooffset[port] = htonl(offset);
14931a58777SHidetoshi Shimokawa 	buf->ioffset[port] = htonl(offset + osize);
15031a58777SHidetoshi Shimokawa 	buf->optr[port] = DCONS_MAKE_PTR(&dc->o);
15131a58777SHidetoshi Shimokawa 	buf->iptr[port] = DCONS_MAKE_PTR(&dc->i);
152869093b1SHidetoshi Shimokawa 
153869093b1SHidetoshi Shimokawa 	return(0);
154869093b1SHidetoshi Shimokawa }
155869093b1SHidetoshi Shimokawa 
15631a58777SHidetoshi Shimokawa int
15731a58777SHidetoshi Shimokawa dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc)
158869093b1SHidetoshi Shimokawa {
15931a58777SHidetoshi Shimokawa 	int port, s;
16031a58777SHidetoshi Shimokawa 	struct dcons_softc *dc;
161869093b1SHidetoshi Shimokawa 
16231a58777SHidetoshi Shimokawa 	if (buf->version != htonl(DCONS_VERSION))
16331a58777SHidetoshi Shimokawa 		return (-1);
164869093b1SHidetoshi Shimokawa 
16531a58777SHidetoshi Shimokawa 	s = DCONS_HEADER_SIZE;
16631a58777SHidetoshi Shimokawa 	for (port = 0; port < DCONS_NPORT; port ++) {
16731a58777SHidetoshi Shimokawa 		dc = &sc[port];
16831a58777SHidetoshi Shimokawa 		dc->o.size = ntohl(buf->osize[port]);
16931a58777SHidetoshi Shimokawa 		dc->i.size = ntohl(buf->isize[port]);
17031a58777SHidetoshi Shimokawa 		dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]);
17131a58777SHidetoshi Shimokawa 		dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]);
17231a58777SHidetoshi Shimokawa 		dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT;
17331a58777SHidetoshi Shimokawa 		dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT;
17431a58777SHidetoshi Shimokawa 		dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK;
17531a58777SHidetoshi Shimokawa 		dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK;
17631a58777SHidetoshi Shimokawa 		dc->o.ptr = &buf->optr[port];
17731a58777SHidetoshi Shimokawa 		dc->i.ptr = &buf->iptr[port];
17831a58777SHidetoshi Shimokawa 		dc->brk_state = STATE0;
179869093b1SHidetoshi Shimokawa 
18031a58777SHidetoshi Shimokawa 		s += dc->o.size + dc->i.size;
18131a58777SHidetoshi Shimokawa 	}
182869093b1SHidetoshi Shimokawa 
18331a58777SHidetoshi Shimokawa 	/* sanity check */
18431a58777SHidetoshi Shimokawa 	if (s > size)
18531a58777SHidetoshi Shimokawa 		return (-1);
186869093b1SHidetoshi Shimokawa 
18731a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
18831a58777SHidetoshi Shimokawa 
18931a58777SHidetoshi Shimokawa 	return (0);
19031a58777SHidetoshi Shimokawa }
19131a58777SHidetoshi Shimokawa 
19231a58777SHidetoshi Shimokawa void
19331a58777SHidetoshi Shimokawa dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc)
19431a58777SHidetoshi Shimokawa {
19531a58777SHidetoshi Shimokawa 	int size0, size1, offset;
19631a58777SHidetoshi Shimokawa 
197869093b1SHidetoshi Shimokawa 	offset = DCONS_HEADER_SIZE;
19831a58777SHidetoshi Shimokawa 	size0 = (size - offset);
19931a58777SHidetoshi Shimokawa 	size1 = size0 * 3 / 4;		/* console port buffer */
200869093b1SHidetoshi Shimokawa 
20131a58777SHidetoshi Shimokawa 	dcons_init_port(0, offset, size1, buf, sc);
20231a58777SHidetoshi Shimokawa 	offset += size1;
20331a58777SHidetoshi Shimokawa 	dcons_init_port(1, offset, size0 - size1, buf, sc);
20431a58777SHidetoshi Shimokawa 	buf->version = htonl(DCONS_VERSION);
20531a58777SHidetoshi Shimokawa 	buf->magic = ntohl(DCONS_MAGIC);
206869093b1SHidetoshi Shimokawa }
207