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 * $FreeBSD$ 38869093b1SHidetoshi Shimokawa */ 39869093b1SHidetoshi Shimokawa 40869093b1SHidetoshi Shimokawa #include <sys/param.h> 41869093b1SHidetoshi Shimokawa 4210f39c7dSHidetoshi Shimokawa #if defined(_BOOT) 4349f159beSWill Andrews #include "dcons.h" 4410f39c7dSHidetoshi Shimokawa #include "stand.h" 455a11c2d9SHidetoshi Shimokawa #else 46869093b1SHidetoshi Shimokawa #include <dev/dcons/dcons.h> 475a11c2d9SHidetoshi Shimokawa #endif 48869093b1SHidetoshi Shimokawa 4931a58777SHidetoshi Shimokawa int 5031a58777SHidetoshi Shimokawa dcons_ischar(struct dcons_softc *dc) 51869093b1SHidetoshi Shimokawa { 5231a58777SHidetoshi Shimokawa u_int32_t ptr, pos, gen, next_gen; 5331a58777SHidetoshi Shimokawa struct dcons_ch *ch; 54869093b1SHidetoshi Shimokawa 5531a58777SHidetoshi Shimokawa ch = &dc->i; 56869093b1SHidetoshi Shimokawa 5731a58777SHidetoshi Shimokawa ptr = ntohl(*ch->ptr); 5831a58777SHidetoshi Shimokawa gen = ptr >> DCONS_GEN_SHIFT; 5931a58777SHidetoshi Shimokawa pos = ptr & DCONS_POS_MASK; 6031a58777SHidetoshi Shimokawa if (gen == ch->gen && pos == ch->pos) 6131a58777SHidetoshi Shimokawa return (0); 62869093b1SHidetoshi Shimokawa 6331a58777SHidetoshi Shimokawa next_gen = DCONS_NEXT_GEN(ch->gen); 6431a58777SHidetoshi Shimokawa /* XXX sanity check */ 6531a58777SHidetoshi Shimokawa if ((gen != ch->gen && gen != next_gen) 6631a58777SHidetoshi Shimokawa || (gen == ch->gen && pos < ch->pos)) { 6731a58777SHidetoshi Shimokawa /* generation skipped !! */ 6831a58777SHidetoshi Shimokawa /* XXX discard */ 6931a58777SHidetoshi Shimokawa ch->gen = gen; 7031a58777SHidetoshi Shimokawa ch->pos = pos; 71869093b1SHidetoshi Shimokawa return (0); 72869093b1SHidetoshi Shimokawa } 73869093b1SHidetoshi Shimokawa 7431a58777SHidetoshi Shimokawa return (1); 75869093b1SHidetoshi Shimokawa } 76869093b1SHidetoshi Shimokawa 7731a58777SHidetoshi Shimokawa int 78869093b1SHidetoshi Shimokawa dcons_checkc(struct dcons_softc *dc) 79869093b1SHidetoshi Shimokawa { 80869093b1SHidetoshi Shimokawa unsigned char c; 81869093b1SHidetoshi Shimokawa u_int32_t ptr, pos, gen, next_gen; 82869093b1SHidetoshi Shimokawa struct dcons_ch *ch; 83869093b1SHidetoshi Shimokawa 84869093b1SHidetoshi Shimokawa ch = &dc->i; 85869093b1SHidetoshi Shimokawa 86869093b1SHidetoshi Shimokawa ptr = ntohl(*ch->ptr); 87869093b1SHidetoshi Shimokawa gen = ptr >> DCONS_GEN_SHIFT; 88869093b1SHidetoshi Shimokawa pos = ptr & DCONS_POS_MASK; 89869093b1SHidetoshi Shimokawa if (gen == ch->gen && pos == ch->pos) 90869093b1SHidetoshi Shimokawa return (-1); 91869093b1SHidetoshi Shimokawa 92869093b1SHidetoshi Shimokawa next_gen = DCONS_NEXT_GEN(ch->gen); 93869093b1SHidetoshi Shimokawa /* XXX sanity check */ 94869093b1SHidetoshi Shimokawa if ((gen != ch->gen && gen != next_gen) 95869093b1SHidetoshi Shimokawa || (gen == ch->gen && pos < ch->pos)) { 96869093b1SHidetoshi Shimokawa /* generation skipped !! */ 97869093b1SHidetoshi Shimokawa /* XXX discard */ 98869093b1SHidetoshi Shimokawa ch->gen = gen; 99869093b1SHidetoshi Shimokawa ch->pos = pos; 100869093b1SHidetoshi Shimokawa return (-1); 101869093b1SHidetoshi Shimokawa } 102869093b1SHidetoshi Shimokawa 103869093b1SHidetoshi Shimokawa c = ch->buf[ch->pos]; 104869093b1SHidetoshi Shimokawa ch->pos ++; 105869093b1SHidetoshi Shimokawa if (ch->pos >= ch->size) { 106869093b1SHidetoshi Shimokawa ch->gen = next_gen; 107869093b1SHidetoshi Shimokawa ch->pos = 0; 108869093b1SHidetoshi Shimokawa } 109869093b1SHidetoshi Shimokawa 110869093b1SHidetoshi Shimokawa return (c); 111869093b1SHidetoshi Shimokawa } 112869093b1SHidetoshi Shimokawa 11331a58777SHidetoshi Shimokawa void 114869093b1SHidetoshi Shimokawa dcons_putc(struct dcons_softc *dc, int c) 115869093b1SHidetoshi Shimokawa { 116869093b1SHidetoshi Shimokawa struct dcons_ch *ch; 117869093b1SHidetoshi Shimokawa 118869093b1SHidetoshi Shimokawa ch = &dc->o; 119869093b1SHidetoshi Shimokawa 120869093b1SHidetoshi Shimokawa ch->buf[ch->pos] = c; 121869093b1SHidetoshi Shimokawa ch->pos ++; 122869093b1SHidetoshi Shimokawa if (ch->pos >= ch->size) { 123869093b1SHidetoshi Shimokawa ch->gen = DCONS_NEXT_GEN(ch->gen); 124869093b1SHidetoshi Shimokawa ch->pos = 0; 125869093b1SHidetoshi Shimokawa } 126869093b1SHidetoshi Shimokawa *ch->ptr = DCONS_MAKE_PTR(ch); 127869093b1SHidetoshi Shimokawa } 128869093b1SHidetoshi Shimokawa 129869093b1SHidetoshi Shimokawa static int 13031a58777SHidetoshi Shimokawa dcons_init_port(int port, int offset, int size, struct dcons_buf *buf, 13131a58777SHidetoshi Shimokawa struct dcons_softc *sc) 132869093b1SHidetoshi Shimokawa { 133869093b1SHidetoshi Shimokawa int osize; 134869093b1SHidetoshi Shimokawa struct dcons_softc *dc; 135869093b1SHidetoshi Shimokawa 136869093b1SHidetoshi Shimokawa dc = &sc[port]; 137869093b1SHidetoshi Shimokawa 138869093b1SHidetoshi Shimokawa osize = size * 3 / 4; 139869093b1SHidetoshi Shimokawa 140869093b1SHidetoshi Shimokawa dc->o.size = osize; 141869093b1SHidetoshi Shimokawa dc->i.size = size - osize; 14231a58777SHidetoshi Shimokawa dc->o.buf = (char *)buf + offset; 143869093b1SHidetoshi Shimokawa dc->i.buf = dc->o.buf + osize; 144869093b1SHidetoshi Shimokawa dc->o.gen = dc->i.gen = 0; 145869093b1SHidetoshi Shimokawa dc->o.pos = dc->i.pos = 0; 14631a58777SHidetoshi Shimokawa dc->o.ptr = &buf->optr[port]; 14731a58777SHidetoshi Shimokawa dc->i.ptr = &buf->iptr[port]; 148869093b1SHidetoshi Shimokawa dc->brk_state = STATE0; 14931a58777SHidetoshi Shimokawa buf->osize[port] = htonl(osize); 15031a58777SHidetoshi Shimokawa buf->isize[port] = htonl(size - osize); 15131a58777SHidetoshi Shimokawa buf->ooffset[port] = htonl(offset); 15231a58777SHidetoshi Shimokawa buf->ioffset[port] = htonl(offset + osize); 15331a58777SHidetoshi Shimokawa buf->optr[port] = DCONS_MAKE_PTR(&dc->o); 15431a58777SHidetoshi Shimokawa buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); 155869093b1SHidetoshi Shimokawa 156869093b1SHidetoshi Shimokawa return(0); 157869093b1SHidetoshi Shimokawa } 158869093b1SHidetoshi Shimokawa 15931a58777SHidetoshi Shimokawa int 16031a58777SHidetoshi Shimokawa dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc) 161869093b1SHidetoshi Shimokawa { 16231a58777SHidetoshi Shimokawa int port, s; 16331a58777SHidetoshi Shimokawa struct dcons_softc *dc; 164869093b1SHidetoshi Shimokawa 16531a58777SHidetoshi Shimokawa if (buf->version != htonl(DCONS_VERSION)) 16631a58777SHidetoshi Shimokawa return (-1); 167869093b1SHidetoshi Shimokawa 16831a58777SHidetoshi Shimokawa s = DCONS_HEADER_SIZE; 16931a58777SHidetoshi Shimokawa for (port = 0; port < DCONS_NPORT; port ++) { 17031a58777SHidetoshi Shimokawa dc = &sc[port]; 17131a58777SHidetoshi Shimokawa dc->o.size = ntohl(buf->osize[port]); 17231a58777SHidetoshi Shimokawa dc->i.size = ntohl(buf->isize[port]); 17331a58777SHidetoshi Shimokawa dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]); 17431a58777SHidetoshi Shimokawa dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]); 17531a58777SHidetoshi Shimokawa dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT; 17631a58777SHidetoshi Shimokawa dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT; 17731a58777SHidetoshi Shimokawa dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK; 17831a58777SHidetoshi Shimokawa dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK; 17931a58777SHidetoshi Shimokawa dc->o.ptr = &buf->optr[port]; 18031a58777SHidetoshi Shimokawa dc->i.ptr = &buf->iptr[port]; 18131a58777SHidetoshi Shimokawa dc->brk_state = STATE0; 182869093b1SHidetoshi Shimokawa 18331a58777SHidetoshi Shimokawa s += dc->o.size + dc->i.size; 18431a58777SHidetoshi Shimokawa } 185869093b1SHidetoshi Shimokawa 18631a58777SHidetoshi Shimokawa /* sanity check */ 18731a58777SHidetoshi Shimokawa if (s > size) 18831a58777SHidetoshi Shimokawa return (-1); 189869093b1SHidetoshi Shimokawa 19031a58777SHidetoshi Shimokawa buf->magic = ntohl(DCONS_MAGIC); 19131a58777SHidetoshi Shimokawa 19231a58777SHidetoshi Shimokawa return (0); 19331a58777SHidetoshi Shimokawa } 19431a58777SHidetoshi Shimokawa 19531a58777SHidetoshi Shimokawa void 19631a58777SHidetoshi Shimokawa dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc) 19731a58777SHidetoshi Shimokawa { 19831a58777SHidetoshi Shimokawa int size0, size1, offset; 19931a58777SHidetoshi Shimokawa 200869093b1SHidetoshi Shimokawa offset = DCONS_HEADER_SIZE; 20131a58777SHidetoshi Shimokawa size0 = (size - offset); 20231a58777SHidetoshi Shimokawa size1 = size0 * 3 / 4; /* console port buffer */ 203869093b1SHidetoshi Shimokawa 20431a58777SHidetoshi Shimokawa dcons_init_port(0, offset, size1, buf, sc); 20531a58777SHidetoshi Shimokawa offset += size1; 20631a58777SHidetoshi Shimokawa dcons_init_port(1, offset, size0 - size1, buf, sc); 20731a58777SHidetoshi Shimokawa buf->version = htonl(DCONS_VERSION); 20831a58777SHidetoshi Shimokawa buf->magic = ntohl(DCONS_MAGIC); 209869093b1SHidetoshi Shimokawa } 210