1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer as 10 * the first lines of this file unmodified. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include "opt_syscons.h" 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/malloc.h> 34 35 #include <machine/console.h> 36 #include <machine/md_var.h> 37 #include <machine/bus.h> 38 39 #include <dev/fb/fbreg.h> 40 #include <dev/syscons/syscons.h> 41 42 #define vtb_wrap(vtb, at, offset) \ 43 (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size) 44 45 void 46 sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait) 47 { 48 vtb->vtb_flags = 0; 49 vtb->vtb_type = type; 50 vtb->vtb_cols = cols; 51 vtb->vtb_rows = rows; 52 vtb->vtb_size = cols*rows; 53 vtb->vtb_buffer = NULL; 54 vtb->vtb_tail = 0; 55 56 switch (type) { 57 case VTB_MEMORY: 58 case VTB_RINGBUFFER: 59 if ((buf == NULL) && (cols*rows != 0)) { 60 vtb->vtb_buffer = 61 (vm_offset_t)malloc(cols*rows*sizeof(u_int16_t), 62 M_DEVBUF, 63 (wait) ? M_WAITOK : M_NOWAIT); 64 if (vtb->vtb_buffer != NULL) 65 bzero((void *)sc_vtb_pointer(vtb, 0), 66 cols*rows*sizeof(u_int16_t)); 67 } else { 68 vtb->vtb_buffer = (vm_offset_t)buf; 69 } 70 vtb->vtb_flags |= VTB_VALID; 71 break; 72 case VTB_FRAMEBUFFER: 73 vtb->vtb_buffer = (vm_offset_t)buf; 74 vtb->vtb_flags |= VTB_VALID; 75 break; 76 default: 77 break; 78 } 79 } 80 81 void 82 sc_vtb_destroy(sc_vtb_t *vtb) 83 { 84 vm_offset_t p; 85 86 vtb->vtb_flags = 0; 87 vtb->vtb_cols = 0; 88 vtb->vtb_rows = 0; 89 vtb->vtb_size = 0; 90 vtb->vtb_tail = 0; 91 92 p = vtb->vtb_buffer; 93 vtb->vtb_buffer = NULL; 94 switch (vtb->vtb_type) { 95 case VTB_MEMORY: 96 case VTB_RINGBUFFER: 97 if (p != NULL) 98 free((void *)p, M_DEVBUF); 99 break; 100 default: 101 break; 102 } 103 vtb->vtb_type = VTB_INVALID; 104 } 105 106 size_t 107 sc_vtb_size(int cols, int rows) 108 { 109 return (size_t)(cols*rows*sizeof(u_int16_t)); 110 } 111 112 int 113 sc_vtb_getc(sc_vtb_t *vtb, int at) 114 { 115 if (vtb->vtb_type == VTB_FRAMEBUFFER) 116 return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff); 117 else 118 return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff); 119 } 120 121 int 122 sc_vtb_geta(sc_vtb_t *vtb, int at) 123 { 124 if (vtb->vtb_type == VTB_FRAMEBUFFER) 125 return (readw(sc_vtb_pointer(vtb, at)) & 0xff00); 126 else 127 return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0xff00); 128 } 129 130 void 131 sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a) 132 { 133 if (vtb->vtb_type == VTB_FRAMEBUFFER) 134 writew(sc_vtb_pointer(vtb, at), a | c); 135 else 136 *(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c; 137 } 138 139 vm_offset_t 140 sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a) 141 { 142 if (vtb->vtb_type == VTB_FRAMEBUFFER) 143 writew(p, a | c); 144 else 145 *(u_int16_t *)p = a | c; 146 return (p + sizeof(u_int16_t)); 147 } 148 149 vm_offset_t 150 sc_vtb_pointer(sc_vtb_t *vtb, int at) 151 { 152 return (vtb->vtb_buffer + sizeof(u_int16_t)*(at)); 153 } 154 155 int 156 sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset) 157 { 158 return ((pos + offset + vtb->vtb_size)%vtb->vtb_size); 159 } 160 161 void 162 sc_vtb_clear(sc_vtb_t *vtb, int c, int attr) 163 { 164 if (vtb->vtb_type == VTB_FRAMEBUFFER) 165 fillw_io(attr | c, sc_vtb_pointer(vtb, 0), vtb->vtb_size); 166 else 167 fillw(attr | c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size); 168 } 169 170 void 171 sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count) 172 { 173 /* XXX if both are VTB_VRAMEBUFFER... */ 174 if (vtb2->vtb_type == VTB_FRAMEBUFFER) { 175 bcopy_toio(sc_vtb_pointer(vtb1, from), 176 sc_vtb_pointer(vtb2, to), 177 count*sizeof(u_int16_t)); 178 } else if (vtb1->vtb_type == VTB_FRAMEBUFFER) { 179 bcopy_fromio(sc_vtb_pointer(vtb1, from), 180 sc_vtb_pointer(vtb2, to), 181 count*sizeof(u_int16_t)); 182 } else { 183 bcopy((void *)sc_vtb_pointer(vtb1, from), 184 (void *)sc_vtb_pointer(vtb2, to), 185 count*sizeof(u_int16_t)); 186 } 187 } 188 189 void 190 sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count) 191 { 192 int len; 193 194 if (vtb2->vtb_type != VTB_RINGBUFFER) 195 return; 196 197 while (count > 0) { 198 len = imin(count, vtb2->vtb_size - vtb2->vtb_tail); 199 if (vtb1->vtb_type == VTB_FRAMEBUFFER) { 200 bcopy_fromio(sc_vtb_pointer(vtb1, from), 201 sc_vtb_pointer(vtb2, vtb2->vtb_tail), 202 len*sizeof(u_int16_t)); 203 } else { 204 bcopy((void *)sc_vtb_pointer(vtb1, from), 205 (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail), 206 len*sizeof(u_int16_t)); 207 } 208 from += len; 209 count -= len; 210 vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len); 211 } 212 } 213 214 void 215 sc_vtb_seek(sc_vtb_t *vtb, int pos) 216 { 217 vtb->vtb_tail = pos%vtb->vtb_size; 218 } 219 220 void 221 sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr) 222 { 223 if (at + count > vtb->vtb_size) 224 count = vtb->vtb_size - at; 225 if (vtb->vtb_type == VTB_FRAMEBUFFER) 226 fillw_io(attr | c, sc_vtb_pointer(vtb, at), count); 227 else 228 fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count); 229 } 230 231 void 232 sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count) 233 { 234 if (from + count > vtb->vtb_size) 235 count = vtb->vtb_size - from; 236 if (to + count > vtb->vtb_size) 237 count = vtb->vtb_size - to; 238 if (count <= 0) 239 return; 240 if (vtb->vtb_type == VTB_FRAMEBUFFER) { 241 bcopy_io(sc_vtb_pointer(vtb, from), 242 sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t)); 243 } else { 244 bcopy((void *)sc_vtb_pointer(vtb, from), 245 (void *)sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t)); 246 } 247 } 248 249 void 250 sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr) 251 { 252 int len; 253 254 if (at + count > vtb->vtb_size) 255 count = vtb->vtb_size - at; 256 len = vtb->vtb_size - at - count; 257 if (len > 0) { 258 if (vtb->vtb_type == VTB_FRAMEBUFFER) { 259 bcopy_io(sc_vtb_pointer(vtb, at + count), 260 sc_vtb_pointer(vtb, at), 261 len*sizeof(u_int16_t)); 262 } else { 263 bcopy((void *)sc_vtb_pointer(vtb, at + count), 264 (void *)sc_vtb_pointer(vtb, at), 265 len*sizeof(u_int16_t)); 266 } 267 } 268 if (vtb->vtb_type == VTB_FRAMEBUFFER) 269 fillw_io(attr | c, sc_vtb_pointer(vtb, at + len), 270 vtb->vtb_size - at - len); 271 else 272 fillw(attr | c, (void *)sc_vtb_pointer(vtb, at + len), 273 vtb->vtb_size - at - len); 274 } 275 276 void 277 sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr) 278 { 279 if (at + count > vtb->vtb_size) { 280 count = vtb->vtb_size - at; 281 } else { 282 if (vtb->vtb_type == VTB_FRAMEBUFFER) { 283 bcopy_io(sc_vtb_pointer(vtb, at), 284 sc_vtb_pointer(vtb, at + count), 285 (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 286 } else { 287 bcopy((void *)sc_vtb_pointer(vtb, at), 288 (void *)sc_vtb_pointer(vtb, at + count), 289 (vtb->vtb_size - at - count)*sizeof(u_int16_t)); 290 } 291 } 292 if (vtb->vtb_type == VTB_FRAMEBUFFER) 293 fillw_io(attr | c, sc_vtb_pointer(vtb, at), count); 294 else 295 fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count); 296 } 297