1139749Simp/*-
2136467Ssimokawa * Copyright (C) 2003,2004
3121468Ssimokawa * 	Hidetoshi Shimokawa. All rights reserved.
4121468Ssimokawa *
5121468Ssimokawa * Redistribution and use in source and binary forms, with or without
6121468Ssimokawa * modification, are permitted provided that the following conditions
7121468Ssimokawa * are met:
8121468Ssimokawa * 1. Redistributions of source code must retain the above copyright
9121468Ssimokawa *    notice, this list of conditions and the following disclaimer.
10121468Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright
11121468Ssimokawa *    notice, this list of conditions and the following disclaimer in the
12121468Ssimokawa *    documentation and/or other materials provided with the distribution.
13121468Ssimokawa * 3. All advertising materials mentioning features or use of this software
14121468Ssimokawa *    must display the following acknowledgement:
15121468Ssimokawa *
16121468Ssimokawa *	This product includes software developed by Hidetoshi Shimokawa.
17121468Ssimokawa *
18121468Ssimokawa * 4. Neither the name of the author nor the names of its contributors
19121468Ssimokawa *    may be used to endorse or promote products derived from this software
20121468Ssimokawa *    without specific prior written permission.
21121468Ssimokawa *
22121468Ssimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23121468Ssimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24121468Ssimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25121468Ssimokawa * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26121468Ssimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27121468Ssimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28121468Ssimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29121468Ssimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30121468Ssimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31121468Ssimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32121468Ssimokawa * SUCH DAMAGE.
33121468Ssimokawa *
34121468Ssimokawa * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $
35121468Ssimokawa * $FreeBSD$
36121468Ssimokawa */
37121468Ssimokawa
38121468Ssimokawa#include <sys/param.h>
39121468Ssimokawa
40136467Ssimokawa#if defined(__DragonFly__) || defined(_BOOT)
41135733Ssimokawa#include "dcons.h"
42169972Ssimokawa#if defined(_BOOT)
43169972Ssimokawa#include "stand.h"
44169972Ssimokawa#endif
45135733Ssimokawa#else
46121468Ssimokawa#include <dev/dcons/dcons.h>
47135733Ssimokawa#endif
48121468Ssimokawa
49136467Ssimokawaint
50136467Ssimokawadcons_ischar(struct dcons_softc *dc)
51121468Ssimokawa{
52136467Ssimokawa	u_int32_t ptr, pos, gen, next_gen;
53136467Ssimokawa	struct dcons_ch *ch;
54121468Ssimokawa
55136467Ssimokawa	ch = &dc->i;
56121468Ssimokawa
57136467Ssimokawa	ptr = ntohl(*ch->ptr);
58136467Ssimokawa	gen = ptr >> DCONS_GEN_SHIFT;
59136467Ssimokawa	pos = ptr & DCONS_POS_MASK;
60136467Ssimokawa	if (gen == ch->gen && pos == ch->pos)
61136467Ssimokawa		return (0);
62121468Ssimokawa
63136467Ssimokawa	next_gen = DCONS_NEXT_GEN(ch->gen);
64136467Ssimokawa	/* XXX sanity check */
65136467Ssimokawa	if ((gen != ch->gen && gen != next_gen)
66136467Ssimokawa			|| (gen == ch->gen && pos < ch->pos)) {
67136467Ssimokawa		/* generation skipped !! */
68136467Ssimokawa		/* XXX discard */
69136467Ssimokawa		ch->gen = gen;
70136467Ssimokawa		ch->pos = pos;
71136467Ssimokawa		return (0);
72121468Ssimokawa	}
73121468Ssimokawa
74136467Ssimokawa	return (1);
75121468Ssimokawa}
76121468Ssimokawa
77136467Ssimokawaint
78121468Ssimokawadcons_checkc(struct dcons_softc *dc)
79121468Ssimokawa{
80121468Ssimokawa	unsigned char c;
81121468Ssimokawa	u_int32_t ptr, pos, gen, next_gen;
82121468Ssimokawa	struct dcons_ch *ch;
83121468Ssimokawa
84121468Ssimokawa	ch = &dc->i;
85121468Ssimokawa
86121468Ssimokawa	ptr = ntohl(*ch->ptr);
87121468Ssimokawa	gen = ptr >> DCONS_GEN_SHIFT;
88121468Ssimokawa	pos = ptr & DCONS_POS_MASK;
89121468Ssimokawa	if (gen == ch->gen && pos == ch->pos)
90121468Ssimokawa		return (-1);
91121468Ssimokawa
92121468Ssimokawa	next_gen = DCONS_NEXT_GEN(ch->gen);
93121468Ssimokawa	/* XXX sanity check */
94121468Ssimokawa	if ((gen != ch->gen && gen != next_gen)
95121468Ssimokawa			|| (gen == ch->gen && pos < ch->pos)) {
96121468Ssimokawa		/* generation skipped !! */
97121468Ssimokawa		/* XXX discard */
98121468Ssimokawa		ch->gen = gen;
99121468Ssimokawa		ch->pos = pos;
100121468Ssimokawa		return (-1);
101121468Ssimokawa	}
102121468Ssimokawa
103121468Ssimokawa	c = ch->buf[ch->pos];
104121468Ssimokawa	ch->pos ++;
105121468Ssimokawa	if (ch->pos >= ch->size) {
106121468Ssimokawa		ch->gen = next_gen;
107121468Ssimokawa		ch->pos = 0;
108121468Ssimokawa	}
109121468Ssimokawa
110121468Ssimokawa	return (c);
111121468Ssimokawa}
112121468Ssimokawa
113136467Ssimokawavoid
114121468Ssimokawadcons_putc(struct dcons_softc *dc, int c)
115121468Ssimokawa{
116121468Ssimokawa	struct dcons_ch *ch;
117121468Ssimokawa
118121468Ssimokawa	ch = &dc->o;
119121468Ssimokawa
120121468Ssimokawa	ch->buf[ch->pos] = c;
121121468Ssimokawa	ch->pos ++;
122121468Ssimokawa	if (ch->pos >= ch->size) {
123121468Ssimokawa		ch->gen = DCONS_NEXT_GEN(ch->gen);
124121468Ssimokawa		ch->pos = 0;
125121468Ssimokawa	}
126121468Ssimokawa	*ch->ptr = DCONS_MAKE_PTR(ch);
127121468Ssimokawa}
128121468Ssimokawa
129121468Ssimokawastatic int
130136467Ssimokawadcons_init_port(int port, int offset, int size, struct dcons_buf *buf,
131136467Ssimokawa    struct dcons_softc *sc)
132121468Ssimokawa{
133121468Ssimokawa	int osize;
134121468Ssimokawa	struct dcons_softc *dc;
135121468Ssimokawa
136121468Ssimokawa	dc = &sc[port];
137121468Ssimokawa
138121468Ssimokawa	osize = size * 3 / 4;
139121468Ssimokawa
140121468Ssimokawa	dc->o.size = osize;
141121468Ssimokawa	dc->i.size = size - osize;
142136467Ssimokawa	dc->o.buf = (char *)buf + offset;
143121468Ssimokawa	dc->i.buf = dc->o.buf + osize;
144121468Ssimokawa	dc->o.gen = dc->i.gen = 0;
145121468Ssimokawa	dc->o.pos = dc->i.pos = 0;
146136467Ssimokawa	dc->o.ptr = &buf->optr[port];
147136467Ssimokawa	dc->i.ptr = &buf->iptr[port];
148121468Ssimokawa	dc->brk_state = STATE0;
149136467Ssimokawa	buf->osize[port] = htonl(osize);
150136467Ssimokawa	buf->isize[port] = htonl(size - osize);
151136467Ssimokawa	buf->ooffset[port] = htonl(offset);
152136467Ssimokawa	buf->ioffset[port] = htonl(offset + osize);
153136467Ssimokawa	buf->optr[port] = DCONS_MAKE_PTR(&dc->o);
154136467Ssimokawa	buf->iptr[port] = DCONS_MAKE_PTR(&dc->i);
155121468Ssimokawa
156121468Ssimokawa	return(0);
157121468Ssimokawa}
158121468Ssimokawa
159136467Ssimokawaint
160136467Ssimokawadcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc)
161121468Ssimokawa{
162136467Ssimokawa	int port, s;
163121468Ssimokawa	struct dcons_softc *dc;
164121468Ssimokawa
165136467Ssimokawa	if (buf->version != htonl(DCONS_VERSION))
166136467Ssimokawa		return (-1);
167121468Ssimokawa
168136467Ssimokawa	s = DCONS_HEADER_SIZE;
169136467Ssimokawa	for (port = 0; port < DCONS_NPORT; port ++) {
170136467Ssimokawa		dc = &sc[port];
171136467Ssimokawa		dc->o.size = ntohl(buf->osize[port]);
172136467Ssimokawa		dc->i.size = ntohl(buf->isize[port]);
173136467Ssimokawa		dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]);
174136467Ssimokawa		dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]);
175136467Ssimokawa		dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT;
176136467Ssimokawa		dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT;
177136467Ssimokawa		dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK;
178136467Ssimokawa		dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK;
179136467Ssimokawa		dc->o.ptr = &buf->optr[port];
180136467Ssimokawa		dc->i.ptr = &buf->iptr[port];
181136467Ssimokawa		dc->brk_state = STATE0;
182121468Ssimokawa
183136467Ssimokawa		s += dc->o.size + dc->i.size;
184121468Ssimokawa	}
185121468Ssimokawa
186136467Ssimokawa	/* sanity check */
187136467Ssimokawa	if (s > size)
188136467Ssimokawa		return (-1);
189121468Ssimokawa
190136467Ssimokawa	buf->magic = ntohl(DCONS_MAGIC);
191121468Ssimokawa
192136467Ssimokawa	return (0);
193121468Ssimokawa}
194121468Ssimokawa
195136467Ssimokawavoid
196136467Ssimokawadcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc)
197132092Ssimokawa{
198136467Ssimokawa	int size0, size1, offset;
199132092Ssimokawa
200136467Ssimokawa	offset = DCONS_HEADER_SIZE;
201136467Ssimokawa	size0 = (size - offset);
202136467Ssimokawa	size1 = size0 * 3 / 4;		/* console port buffer */
203132092Ssimokawa
204136467Ssimokawa	dcons_init_port(0, offset, size1, buf, sc);
205136467Ssimokawa	offset += size1;
206136467Ssimokawa	dcons_init_port(1, offset, size0 - size1, buf, sc);
207136467Ssimokawa	buf->version = htonl(DCONS_VERSION);
208136467Ssimokawa	buf->magic = ntohl(DCONS_MAGIC);
209132092Ssimokawa}
210