148187Skato/*- 248516Skato * Copyright (c) 1999 FreeBSD(98) Porting Team. 348516Skato * All rights reserved. 448516Skato * 548516Skato * Redistribution and use in source and binary forms, with or without 648516Skato * modification, are permitted provided that the following conditions 748516Skato * are met: 848516Skato * 1. Redistributions of source code must retain the above copyright 948516Skato * notice, this list of conditions and the following disclaimer as 1048516Skato * the first lines of this file unmodified. 1148516Skato * 2. Redistributions in binary form must reproduce the above copyright 1248516Skato * notice, this list of conditions and the following disclaimer in the 1348516Skato * documentation and/or other materials provided with the distribution. 1448516Skato * 1548516Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1648516Skato * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1748516Skato * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1848516Skato * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1948516Skato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2048516Skato * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2148516Skato * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2248516Skato * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2348516Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2448516Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2548516Skato * 2650477Speter * $FreeBSD$ 2748187Skato */ 2848187Skato 2948187Skato#include "opt_syscons.h" 3048187Skato 3148187Skato#include <sys/param.h> 3248187Skato#include <sys/systm.h> 3348187Skato#include <sys/malloc.h> 3466870Skato#include <sys/consio.h> 3566870Skato#include <sys/fbio.h> 3648187Skato 3748187Skato#include <machine/md_var.h> 3848187Skato 3948187Skato#include <dev/fb/fbreg.h> 4048187Skato#include <dev/syscons/syscons.h> 4148187Skato 4280371Snyan#define ATTR_OFFSET_FB 0x2000 4380371Snyan#define attr_offset(vtb) ((vtb)->vtb_size*sizeof(u_int16_t)) 4448187Skato 4580371Snyan#define vtb_pointer(vtb, at) \ 4680371Snyan ((vtb)->vtb_buffer + sizeof(u_int16_t)*(at)) 4780371Snyan 4848187Skato#define vtb_wrap(vtb, at, offset) \ 4948187Skato (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size) 5048187Skato 5180371Snyanstatic u_int8_t ibmpc_to_pc98[256] = { 5280371Snyan 0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1, 5380371Snyan 0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9, 5480371Snyan 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 5580371Snyan 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 5680371Snyan 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 5780371Snyan 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 5880371Snyan 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 5980371Snyan 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 6080371Snyan 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 6180371Snyan 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 6280371Snyan 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 6380371Snyan 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 6480371Snyan 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 6580371Snyan 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 6680371Snyan 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 6780371Snyan 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 6848187Skato 6980371Snyan 0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3, 7080371Snyan 0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb, 7180371Snyan 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 7280371Snyan 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 7380371Snyan 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 7480371Snyan 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 7580371Snyan 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 7680371Snyan 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 7780371Snyan 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 7880371Snyan 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 7980371Snyan 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 8080371Snyan 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 8180371Snyan 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 8280371Snyan 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 8380371Snyan 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 8480371Snyan 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 8580371Snyan}; 8680371Snyan#define at2pc98(attr) ((attr) | ibmpc_to_pc98[(unsigned)(attr) >> 8]) 8748187Skato 8848187Skatovoid 8948187Skatosc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait) 9048187Skato{ 9148187Skato vtb->vtb_flags = 0; 9248187Skato vtb->vtb_type = type; 9348187Skato vtb->vtb_cols = cols; 9448187Skato vtb->vtb_rows = rows; 9548187Skato vtb->vtb_size = cols*rows; 96102265Snyan vtb->vtb_buffer = 0; 9748187Skato vtb->vtb_tail = 0; 9848187Skato 9948187Skato switch (type) { 10048187Skato case VTB_MEMORY: 10148187Skato case VTB_RINGBUFFER: 10248187Skato if ((buf == NULL) && (cols*rows != 0)) { 10348187Skato vtb->vtb_buffer = 10480371Snyan (vm_offset_t)malloc(cols*rows*sizeof(u_int16_t)*2, 10580371Snyan M_DEVBUF, 106111119Simp ((wait) ? M_WAITOK : M_NOWAIT) | M_ZERO); 107102265Snyan if (vtb->vtb_buffer != 0) { 10879702Snyan vtb->vtb_flags |= VTB_ALLOCED; 10948187Skato } 11048187Skato } else { 11148187Skato vtb->vtb_buffer = (vm_offset_t)buf; 11248187Skato } 11348187Skato vtb->vtb_flags |= VTB_VALID; 11448187Skato break; 11548187Skato case VTB_FRAMEBUFFER: 11648187Skato vtb->vtb_buffer = (vm_offset_t)buf; 11748187Skato vtb->vtb_flags |= VTB_VALID; 11848187Skato break; 11948187Skato default: 12048187Skato break; 12148187Skato } 12248187Skato} 12348187Skato 12448187Skatovoid 12548187Skatosc_vtb_destroy(sc_vtb_t *vtb) 12648187Skato{ 12748187Skato vm_offset_t p; 12848187Skato 12948187Skato vtb->vtb_cols = 0; 13048187Skato vtb->vtb_rows = 0; 13148187Skato vtb->vtb_size = 0; 13248187Skato vtb->vtb_tail = 0; 13348187Skato 13448187Skato p = vtb->vtb_buffer; 135102265Snyan vtb->vtb_buffer = 0; 13648187Skato switch (vtb->vtb_type) { 13748187Skato case VTB_MEMORY: 13848187Skato case VTB_RINGBUFFER: 139102265Snyan if ((vtb->vtb_flags & VTB_ALLOCED) && (p != 0)) 14048187Skato free((void *)p, M_DEVBUF); 14148187Skato break; 14248187Skato default: 14348187Skato break; 14448187Skato } 14579702Snyan vtb->vtb_flags = 0; 14648187Skato vtb->vtb_type = VTB_INVALID; 14748187Skato} 14848187Skato 14948187Skatosize_t 15048187Skatosc_vtb_size(int cols, int rows) 15148187Skato{ 15248187Skato return (size_t)(cols*rows*sizeof(u_int16_t)*2); 15348187Skato} 15448187Skato 15548187Skatoint 15648187Skatosc_vtb_getc(sc_vtb_t *vtb, int at) 15748187Skato{ 15880371Snyan vm_offset_t p = vtb_pointer(vtb, at); 15980371Snyan 16048187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) 16180371Snyan return (readw(p) & 0x00ff); 16248187Skato else 16380371Snyan return (*(u_int16_t *)p & 0x00ff); 16448187Skato} 16548187Skato 16648187Skatoint 16748187Skatosc_vtb_geta(sc_vtb_t *vtb, int at) 16848187Skato{ 16980371Snyan vm_offset_t p = vtb_pointer(vtb, at); 17080371Snyan 17148187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) 17287886Snyan return (readw(p + ATTR_OFFSET_FB) & 0xff00); 17348187Skato else 17487886Snyan return (*(u_int16_t *)(p + attr_offset(vtb)) & 0xff00); 17548187Skato} 17648187Skato 177228471Sedstatic inline void 17880371Snyanvtb_putc(sc_vtb_t *vtb, vm_offset_t p, int c, int a) 17948187Skato{ 18048187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 18180371Snyan writew(p, c); 18280371Snyan writew(p + ATTR_OFFSET_FB, at2pc98(a)); 18348187Skato } else { 18480371Snyan *(u_int16_t *)p = c; 18580371Snyan *(u_int16_t *)(p + attr_offset(vtb)) = at2pc98(a); 18648187Skato } 18748187Skato} 18848187Skato 18980371Snyanvoid 19080371Snyansc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a) 19180371Snyan{ 19280371Snyan vtb_putc(vtb, vtb_pointer(vtb, at), c, a); 19380371Snyan} 19480371Snyan 19548187Skatovm_offset_t 19648187Skatosc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a) 19748187Skato{ 19880371Snyan vtb_putc(vtb, p, c, a); 19948187Skato return (p + sizeof(u_int16_t)); 20048187Skato} 20148187Skato 20248187Skatovm_offset_t 20348187Skatosc_vtb_pointer(sc_vtb_t *vtb, int at) 20448187Skato{ 20580371Snyan return (vtb_pointer(vtb, at)); 20648187Skato} 20748187Skato 20848187Skatoint 20948187Skatosc_vtb_pos(sc_vtb_t *vtb, int pos, int offset) 21048187Skato{ 21148187Skato return ((pos + offset + vtb->vtb_size)%vtb->vtb_size); 21248187Skato} 21348187Skato 21448187Skatovoid 21548187Skatosc_vtb_clear(sc_vtb_t *vtb, int c, int attr) 21648187Skato{ 21780371Snyan vm_offset_t p = vtb_pointer(vtb, 0); 21880371Snyan 21948187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 22080371Snyan fillw_io(c, p, vtb->vtb_size); 22180371Snyan fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, vtb->vtb_size); 22248187Skato } else { 22380371Snyan fillw(c, (void *)p, vtb->vtb_size); 22480371Snyan fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)), 22580371Snyan vtb->vtb_size); 22648187Skato } 22748187Skato} 22848187Skato 22948187Skatovoid 23048187Skatosc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count) 23148187Skato{ 23280371Snyan vm_offset_t p1, p2; 23380371Snyan 23480371Snyan p1 = vtb_pointer(vtb1, from); 23580371Snyan p2 = vtb_pointer(vtb2, to); 23648187Skato if (vtb2->vtb_type == VTB_FRAMEBUFFER) { 23780371Snyan bcopy_toio(p1, p2, count*sizeof(u_int16_t)); 23880371Snyan bcopy_toio(p1 + attr_offset(vtb1), 23980371Snyan p2 + ATTR_OFFSET_FB, 24048187Skato count*sizeof(u_int16_t)); 24148187Skato } else if (vtb1->vtb_type == VTB_FRAMEBUFFER) { 24280371Snyan bcopy_fromio(p1, p2, count*sizeof(u_int16_t)); 24380371Snyan bcopy_fromio(p1 + ATTR_OFFSET_FB, 24480371Snyan p2 + attr_offset(vtb2), 24548187Skato count*sizeof(u_int16_t)); 24648187Skato } else { 24780371Snyan bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t)); 24880371Snyan bcopy((void *)(p1 + attr_offset(vtb1)), 24980371Snyan (void *)(p2 + attr_offset(vtb2)), 25048187Skato count*sizeof(u_int16_t)); 25148187Skato } 25248187Skato} 25348187Skato 25448187Skatovoid 25548187Skatosc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count) 25648187Skato{ 25748187Skato int len; 25880371Snyan vm_offset_t p1, p2; 25948187Skato 26048187Skato if (vtb2->vtb_type != VTB_RINGBUFFER) 26148187Skato return; 26248187Skato 26348187Skato while (count > 0) { 26480371Snyan p1 = vtb_pointer(vtb1, from); 26580371Snyan p2 = vtb_pointer(vtb2, vtb2->vtb_tail); 26648187Skato len = imin(count, vtb2->vtb_size - vtb2->vtb_tail); 26748187Skato if (vtb1->vtb_type == VTB_FRAMEBUFFER) { 26880371Snyan bcopy_fromio(p1, p2, len*sizeof(u_int16_t)); 26980371Snyan bcopy_fromio(p1 + ATTR_OFFSET_FB, 27080371Snyan p2 + attr_offset(vtb2), 27148187Skato len*sizeof(u_int16_t)); 27248187Skato } else { 27380371Snyan bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t)); 27480371Snyan bcopy((void *)(p1 + attr_offset(vtb1)), 27580371Snyan (void *)(p2 + attr_offset(vtb2)), 27648187Skato len*sizeof(u_int16_t)); 27748187Skato } 27848187Skato from += len; 27948187Skato count -= len; 28048187Skato vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len); 28148187Skato } 28248187Skato} 28348187Skato 28448187Skatovoid 28548187Skatosc_vtb_seek(sc_vtb_t *vtb, int pos) 28648187Skato{ 28748187Skato vtb->vtb_tail = pos%vtb->vtb_size; 28848187Skato} 28948187Skato 29048187Skatovoid 29148187Skatosc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr) 29248187Skato{ 29380371Snyan vm_offset_t p; 29480371Snyan 29548187Skato if (at + count > vtb->vtb_size) 29648187Skato count = vtb->vtb_size - at; 29780371Snyan p = vtb_pointer(vtb, at); 29848187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 29980371Snyan fillw_io(c, p, count); 30080371Snyan fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, count); 30148187Skato } else { 30280371Snyan fillw(c, (void *)p, count); 30380371Snyan fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)), count); 30448187Skato } 30548187Skato} 30648187Skato 30748187Skatovoid 30848190Skatosc_vtb_move(sc_vtb_t *vtb, int from, int to, int count) 30948190Skato{ 31080371Snyan vm_offset_t p1, p2; 31180371Snyan 31248190Skato if (from + count > vtb->vtb_size) 31348190Skato count = vtb->vtb_size - from; 31448190Skato if (to + count > vtb->vtb_size) 31548190Skato count = vtb->vtb_size - to; 31648190Skato if (count <= 0) 31748190Skato return; 31880371Snyan 31980371Snyan p1 = vtb_pointer(vtb, from); 32080371Snyan p2 = vtb_pointer(vtb, to); 32148190Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 32280371Snyan bcopy_io(p1, p2, count*sizeof(u_int16_t)); 32380371Snyan bcopy_io(p1 + ATTR_OFFSET_FB, 32480371Snyan p2 + ATTR_OFFSET_FB, count*sizeof(u_int16_t)); 32548190Skato } else { 32680371Snyan bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t)); 32780371Snyan bcopy((void *)(p1 + attr_offset(vtb)), 32880371Snyan (void *)(p2 + attr_offset(vtb)), count*sizeof(u_int16_t)); 32948190Skato } 33048190Skato} 33148190Skato 33248190Skatovoid 33348187Skatosc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr) 33448187Skato{ 33548187Skato int len; 33680371Snyan vm_offset_t p1, p2; 33748187Skato 33848187Skato if (at + count > vtb->vtb_size) 33948187Skato count = vtb->vtb_size - at; 34048187Skato len = vtb->vtb_size - at - count; 34148187Skato if (len > 0) { 34280371Snyan p1 = vtb_pointer(vtb, at + count); 34380371Snyan p2 = vtb_pointer(vtb, at); 34448187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 34580371Snyan bcopy_io(p1, p2, len*sizeof(u_int16_t)); 34680371Snyan bcopy_io(p1 + ATTR_OFFSET_FB, 34780371Snyan p2 + ATTR_OFFSET_FB, 34848187Skato len*sizeof(u_int16_t)); 34948187Skato } else { 35080371Snyan bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t)); 35180371Snyan bcopy((void *)(p1 + attr_offset(vtb)), 35280371Snyan (void *)(p2 + attr_offset(vtb)), 35348187Skato len*sizeof(u_int16_t)); 35448187Skato } 35548187Skato } 35680371Snyan p1 = vtb_pointer(vtb, at + len); 35748187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 35880371Snyan fillw_io(c, p1, vtb->vtb_size - at - len); 35980371Snyan fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB, 36048187Skato vtb->vtb_size - at - len); 36148187Skato } else { 36280371Snyan fillw(c, (void *)p1, vtb->vtb_size - at - len); 36380371Snyan fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)), 36448187Skato vtb->vtb_size - at - len); 36548187Skato } 36648187Skato} 36748187Skato 36848187Skatovoid 36948187Skatosc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr) 37048187Skato{ 37180371Snyan vm_offset_t p1, p2; 37280371Snyan 37380371Snyan p1 = vtb_pointer(vtb, at); 37448187Skato if (at + count > vtb->vtb_size) { 37548187Skato count = vtb->vtb_size - at; 37648187Skato } else { 37780371Snyan p2 = vtb_pointer(vtb, at + count); 37848187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 37980371Snyan bcopy_io(p1, p2, 38048187Skato (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 38180371Snyan bcopy_io(p1 + ATTR_OFFSET_FB, 38280371Snyan p2 + ATTR_OFFSET_FB, 38348187Skato (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 38448187Skato } else { 38580371Snyan bcopy((void *)p1, (void *)p2, 38648187Skato (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 38780371Snyan bcopy((void *)(p1 + attr_offset(vtb)), 38880371Snyan (void *)(p2 + attr_offset(vtb)), 38948187Skato (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 39048187Skato } 39148187Skato } 39248187Skato if (vtb->vtb_type == VTB_FRAMEBUFFER) { 39380371Snyan fillw_io(c, p1, count); 39480371Snyan fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB, count); 39548187Skato } else { 39680371Snyan fillw(c, (void *)p1, count); 39780371Snyan fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)), count); 39848187Skato } 39948187Skato} 400