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