From owner-svn-src-user@FreeBSD.ORG Tue Oct 22 14:45:35 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id D92E3BB0; Tue, 22 Oct 2013 14:45:35 +0000 (UTC) (envelope-from ray@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B6F812FE2; Tue, 22 Oct 2013 14:45:35 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9MEjZxW050981; Tue, 22 Oct 2013 14:45:35 GMT (envelope-from ray@svn.freebsd.org) Received: (from ray@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9MEjZrP050980; Tue, 22 Oct 2013 14:45:35 GMT (envelope-from ray@svn.freebsd.org) Message-Id: <201310221445.r9MEjZrP050980@svn.freebsd.org> From: Aleksandr Rybalko Date: Tue, 22 Oct 2013 14:45:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256905 - user/ed/newcons/sys/dev/fb X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Oct 2013 14:45:35 -0000 Author: ray Date: Tue Oct 22 14:45:35 2013 New Revision: 256905 URL: http://svnweb.freebsd.org/changeset/base/256905 Log: Add generic/simple framebuffer. Sponsored by: The FreeBSD Foundation Added: user/ed/newcons/sys/dev/fb/fbd.c (contents, props changed) Added: user/ed/newcons/sys/dev/fb/fbd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ed/newcons/sys/dev/fb/fbd.c Tue Oct 22 14:45:35 2013 (r256905) @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Aleksandr Rybalko under sponsorship from the + * FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* Generic framebuffer */ +/* TODO unlink from VT(9) */ +/* TODO done normal /dev/fb methods */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(fb_list_head_t, fb_list_entry) fb_list_head = + LIST_HEAD_INITIALIZER(fb_list_head); +struct fb_list_entry { + struct fb_info *fb_info; + struct cdev *fb_si; + LIST_ENTRY(fb_list_entry) fb_list; +}; + +static void fbd_evh_init(void *); +/* SI_ORDER_SECOND, just after EVENTHANDLERs initialized. */ +SYSINIT(fbd_evh_init, SI_SUB_CONFIGURE, SI_ORDER_SECOND, fbd_evh_init, NULL); + +static d_open_t fb_open; +static d_close_t fb_close; +static d_read_t fb_read; +static d_write_t fb_write; +static d_ioctl_t fb_ioctl; +static d_mmap_t fb_mmap; + +static struct cdevsw fb_cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDGIANT, + .d_open = fb_open, + .d_close = fb_close, + .d_read = fb_read, + .d_write = fb_write, + .d_ioctl = fb_ioctl, + .d_mmap = fb_mmap, + .d_name = "fb", +}; + +static int framebuffer_dev_unit = 0; + +static int +fb_open(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + + return (0); +} + +static int +fb_close(struct cdev *dev, int fflag, int devtype, struct thread *td) +{ + + return (0); +} + +static int +fb_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, + struct thread *td) +{ + + return (0); +} + +static int +fb_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + + return (0); /* XXX nothing to read, yet */ +} + +static int +fb_write(struct cdev *dev, struct uio *uio, int ioflag) +{ + + return (0); /* XXX nothing written */ +} + +static int +fb_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, + vm_memattr_t *memattr) +{ + struct fb_info *info; + + info = dev->si_drv1; + if (offset < info->fb_size) { + *paddr = info->fb_pbase + offset; + return (0); + } + return (EINVAL); +} + + +static void +vt_fb_mem_wr1(struct fb_info *sc, uint32_t o, uint8_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + *(uint8_t *)(sc->fb_vbase + o) = v; +} + +static void +vt_fb_mem_wr2(struct fb_info *sc, uint32_t o, uint16_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + *(uint16_t *)(sc->fb_vbase + o) = v; +} + +static void +vt_fb_mem_wr4(struct fb_info *sc, uint32_t o, uint32_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + *(uint32_t *)(sc->fb_vbase + o) = v; +} + +static void +vt_fb_indir_wr1(struct fb_info *sc, uint32_t o, uint8_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + sc->fb_write(sc->fb_priv, o, &v, 1); +} + +static void +vt_fb_indir_wr2(struct fb_info *sc, uint32_t o, uint16_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + sc->fb_write(sc->fb_priv, o, &v, 2); +} + +static void +vt_fb_indir_wr4(struct fb_info *sc, uint32_t o, uint32_t v) +{ + + KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o)); + sc->fb_write(sc->fb_priv, o, &v, 4); +} + +static int +fb_probe(struct fb_info *info) +{ + + if (info->fb_size == 0) + return (ENXIO); + + if (info->fb_write != NULL) { + if (info->fb_write == NULL) { + return (EINVAL); + } + info->fb_flags |= FB_FLAG_NOMMAP; + info->wr1 = &vt_fb_indir_wr1; + info->wr2 = &vt_fb_indir_wr2; + info->wr4 = &vt_fb_indir_wr4; + } else if (info->fb_vbase != 0) { + if (info->fb_pbase == 0) + info->fb_flags |= FB_FLAG_NOMMAP; + info->wr1 = &vt_fb_mem_wr1; + info->wr2 = &vt_fb_mem_wr2; + info->wr4 = &vt_fb_mem_wr4; + } else + return (ENXIO); + + return (0); +} + + +static int +fb_init(struct fb_list_entry *entry, int unit) +{ + struct fb_info *info; + + info = entry->fb_info; + entry->fb_si = make_dev(&fb_cdevsw, unit, UID_ROOT, GID_WHEEL, + 0600, "fb%d", unit); + entry->fb_si->si_drv1 = info; + + return (0); +} + +int +fbd_list() +{ + struct fb_list_entry *entry; + + if (LIST_EMPTY(&fb_list_head)) + return (ENOENT); + + LIST_FOREACH(entry, &fb_list_head, fb_list) { + printf("FB %s @%p\n", entry->fb_info->fb_name, + (void *)entry->fb_info->fb_pbase); + } + + return (0); +} + +static struct fb_list_entry * +fbd_find(struct fb_info* info) +{ + struct fb_list_entry *entry, *tmp; + + LIST_FOREACH_SAFE(entry, &fb_list_head, fb_list, tmp) { + if (entry->fb_info == info) { + return (entry); + } + } + + return (NULL); +} + +int +fbd_register(struct fb_info* info) +{ + struct fb_list_entry *entry; + int err, first; + + first = 0; + if (LIST_EMPTY(&fb_list_head)) + first++; + + entry = fbd_find(info); + if (entry != NULL) { + /* XXX Update framebuffer params */ + return (0); + } + + err = fb_probe(info); + if (err) + return (err); + + entry = malloc(sizeof(struct fb_list_entry), M_DEVBUF, M_WAITOK|M_ZERO); + entry->fb_info = info; + + LIST_INSERT_HEAD(&fb_list_head, entry, fb_list); + + err = fb_init(entry, framebuffer_dev_unit++); + if (err) + return (err); + + if (first) + vt_fb_attach(info); + + return (0); +} + +int +fbd_unregister(struct fb_info* info) +{ + struct fb_list_entry *entry, *tmp; + + LIST_FOREACH_SAFE(entry, &fb_list_head, fb_list, tmp) { + if (entry->fb_info == info) { + LIST_REMOVE(entry, fb_list); + free(entry, M_DEVBUF); + return (0); + } + } + + return (ENOENT); +} + +static void +register_fb_wrap(void *arg, void *ptr) +{ + + fbd_register((struct fb_info *)ptr); +} + +static void +unregister_fb_wrap(void *arg, void *ptr) +{ + + fbd_unregister((struct fb_info *)ptr); +} + +static void +fbd_evh_init(void *ctx) +{ + + EVENTHANDLER_REGISTER(register_framebuffer, register_fb_wrap, NULL, + EVENTHANDLER_PRI_ANY); + EVENTHANDLER_REGISTER(unregister_framebuffer, unregister_fb_wrap, NULL, + EVENTHANDLER_PRI_ANY); +}