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