ite_sti.c revision 1.5 1 /* $NetBSD: ite_sti.c,v 1.5 2025/05/27 18:02:58 tsutsui Exp $ */
2 /* $OpenBSD: ite_sti.c,v 1.2 2011/08/18 20:02:58 miod Exp $ */
3 /*
4 * Copyright (c) 2006, 2011, Miodrag Vallat
5 * Copyright (c) 2000-2003 Michael Shalayeff
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifdef ITECONSOLE
31 #include <sys/param.h>
32
33 #include <lib/libsa/stand.h>
34
35 #include <hp300/stand/common/samachdep.h>
36 #include <hp300/stand/common/itevar.h>
37
38 #include <hp300/dev/sti_diovar.h>
39 #include <hp300/dev/dioreg.h>
40 #include <hp300/dev/sgcreg.h>
41 #include <dev/ic/stireg.h>
42
43 /*
44 * sti-specific data not available in the ite_data structure.
45 * Since we will only configure one sti display, it is ok to use a global.
46 */
47 static struct {
48 uint32_t codeptr[STI_CODECNT];
49 uint8_t *code;
50 uint32_t fontbase;
51 u_int firstchar, lastchar;
52 struct sti_cfg cfg;
53 struct sti_ecfg ecfg;
54 } sti;
55
56 #define parseshort1(addr, ofs) \
57 (((addr)[(ofs) + 3] << 8) | ((addr)[(ofs) + 7]))
58 #define parseword1(addr, ofs) \
59 (((addr)[(ofs) + 3] << 24) | ((addr)[(ofs) + 7] << 16) | \
60 ((addr)[(ofs) + 11] << 8) | ((addr)[(ofs) + 15]))
61
62 static void sti_do_cursor(struct ite_data *);
63 static void sti_fontinfo(struct ite_data *);
64 static void sti_init(int);
65 static void sti_inqcfg(struct sti_inqconfout *);
66 static void sti_iteinit_common(struct ite_data *);
67
68 /* kinda similar to sti_dio_probe() */
69 int
70 sti_dio_probe(struct ite_data *ip)
71 {
72 int scode = ip->scode;
73 uint8_t *id_reg;
74
75 id_reg = (uint8_t *)sctoaddr(scode);
76 if (id_reg[DIOII_SIZEOFF] < STI_DIO_SIZE - 1)
77 return ENODEV;
78
79 id_reg = (uint8_t *)sctoaddr(scode + STI_DIO_SCODE_OFFSET);
80 if (id_reg[3] != STI_DEVTYPE1)
81 return ENODEV;
82
83 return 0;
84 }
85
86 void
87 sti_iteinit_dio(struct ite_data *ip)
88 {
89
90 ip->fbbase = (uint8_t *)sctoaddr(ip->scode + STI_DIO_SCODE_OFFSET);
91 sti_iteinit_common(ip);
92 }
93
94 void
95 sti_iteinit_sgc(struct ite_data *ip)
96 {
97
98 ip->fbbase = (uint8_t *)IIOV(SGC_BASE + (ip->scode * SGC_DEVSIZE));
99 sti_iteinit_common(ip);
100 }
101
102 /*
103 * Initialize the sti device for ite's needs.
104 * We don't bother to check for failures since
105 * - we are in tight space already
106 * - since romputchar() does not work with sti devices, there is no way we
107 * can report errors (although we could switch to serial...)
108 */
109 static void
110 sti_iteinit_common(struct ite_data *ip)
111 {
112 int i;
113 size_t codesize, memsize;
114 uint8_t *va, *code;
115 u_int addr, eaddr, reglist, tmp;
116 struct sti_inqconfout cfg;
117 struct sti_einqconfout ecfg;
118
119 memset(&sti, 0, sizeof sti);
120 va = (uint8_t *)ip->fbbase;
121
122 /*
123 * Read the microcode.
124 */
125
126 for (i = 0; i < STI_CODECNT; i++)
127 sti.codeptr[i] =
128 parseword1(va, (STI_CODEBASE_M68K << 2) + i * 0x10);
129
130 for (i = STI_END; sti.codeptr[i] == 0; i--)
131 continue;
132 codesize = sti.codeptr[i] - sti.codeptr[STI_BEGIN];
133 codesize = (codesize + 3) / 4;
134
135 sti.code = (uint8_t *)alloc(codesize);
136 code = sti.code;
137 addr = (u_int)va + sti.codeptr[STI_BEGIN];
138 eaddr = addr + codesize * 4;
139 for (; addr < eaddr; addr += 4)
140 *code++ = *(uint8_t *)addr;
141
142 for (i = STI_CODECNT - 1; i != 0; i--)
143 if (sti.codeptr[i] != 0) {
144 sti.codeptr[i] -= sti.codeptr[0];
145 sti.codeptr[i] /= 4;
146 }
147
148 sti.codeptr[0] = 0;
149 for (i = STI_END; sti.codeptr[i] == 0; i--);
150 sti.codeptr[i] = 0;
151
152 /*
153 * Read the regions list.
154 */
155
156 reglist = parseword1(va, 0x60);
157 for (i = 0; i < STI_REGION_MAX; i++) {
158 tmp = parseword1(va, (reglist & ~3) + i * 0x10);
159 sti.cfg.regions[i] = (u_int)va + ((tmp >> 18) << 12);
160 if (tmp & 0x4000)
161 break;
162 }
163
164 /*
165 * Allocate scratch memory for the microcode if it needs it.
166 */
167
168 sti.cfg.ext_cfg = &sti.ecfg;
169 memsize = parseword1(va, 0xa0);
170 if (memsize != 0)
171 sti.ecfg.addr = alloc(memsize);
172
173 /*
174 * Initialize the display, and get geometry information.
175 */
176
177 sti_init(0);
178
179 memset(&cfg, 0, sizeof cfg);
180 memset(&ecfg, 0, sizeof ecfg);
181 cfg.ext = &ecfg;
182 sti_inqcfg(&cfg);
183
184 if (cfg.owidth == cfg.width && cfg.oheight == cfg.height) {
185 sti.cfg.oscr_width = cfg.owidth = cfg.fbwidth - cfg.width;
186 sti.cfg.oscr_height = cfg.oheight = cfg.fbheight - cfg.height;
187 }
188
189 ip->dheight = cfg.height;
190 ip->dwidth = cfg.width;
191 ip->fbheight = cfg.fbheight;
192 ip->fbwidth = cfg.fbwidth;
193
194 /*
195 * Get ready for ite operation!
196 */
197
198 sti_init(1);
199 sti_fontinfo(ip);
200 sti_clear(ip, 0, 0, ip->rows, ip->cols); /* necessary? */
201 }
202
203 void
204 sti_putc(struct ite_data *ip, int c, int dy, int dx)
205 {
206 sti_unpmv_t unpmv;
207 struct {
208 struct sti_unpmvflags flags;
209 struct sti_unpmvin in;
210 struct sti_unpmvout out;
211 } a;
212
213 memset(&a, 0, sizeof a);
214 a.flags.flags = STI_UNPMVF_WAIT;
215 a.in.bg_colour = STI_COLOUR_BLACK;
216 a.in.fg_colour = STI_COLOUR_WHITE;
217 a.in.x = dx * ip->ftwidth;
218 a.in.y = dy * ip->ftheight;
219 a.in.font_addr = (uint32_t *)((uint8_t *)ip->fbbase + sti.fontbase);
220 a.in.index = c;
221
222 unpmv = (sti_unpmv_t)(sti.code + sti.codeptr[STI_FONT_UNPMV]);
223 (*unpmv)(&a.flags, &a.in, &a.out, &sti.cfg);
224 }
225
226 void
227 sti_cursor(struct ite_data *ip, int flag)
228 {
229 switch (flag) {
230 case MOVE_CURSOR:
231 sti_do_cursor(ip);
232 /* FALLTHROUGH */
233 case DRAW_CURSOR:
234 ip->cursorx = ip->curx;
235 ip->cursory = ip->cury;
236 /* FALLTHROUGH */
237 default:
238 sti_do_cursor(ip);
239 break;
240 }
241 }
242
243 static void
244 sti_do_cursor(struct ite_data *ip)
245 {
246 sti_blkmv_t blkmv;
247 struct {
248 struct sti_blkmvflags flags;
249 struct sti_blkmvin in;
250 struct sti_blkmvout out;
251 } a;
252
253 memset(&a, 0, sizeof a);
254 a.flags.flags = STI_BLKMVF_WAIT | STI_BLKMVF_COLR;
255 a.in.fg_colour = STI_COLOUR_BLACK;
256 a.in.bg_colour = STI_COLOUR_WHITE;
257 a.in.dstx = a.in.srcx = ip->cursorx * ip->ftwidth;
258 a.in.dsty = a.in.srcy = ip->cursory * ip->ftheight;
259 a.in.width = ip->ftwidth;
260 a.in.height = ip->ftheight;
261
262 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
263 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
264 }
265
266 void
267 sti_clear(struct ite_data *ip, int sy, int sx, int h, int w)
268 {
269 sti_blkmv_t blkmv;
270 struct {
271 struct sti_blkmvflags flags;
272 struct sti_blkmvin in;
273 struct sti_blkmvout out;
274 } a;
275
276 memset(&a, 0, sizeof a);
277 a.flags.flags = STI_BLKMVF_WAIT | STI_BLKMVF_CLR;
278 a.in.bg_colour = STI_COLOUR_BLACK;
279 a.in.dstx = a.in.srcx = sx * ip->ftwidth;
280 a.in.dsty = a.in.srcy = sy * ip->ftheight;
281 a.in.width = w * ip->ftwidth;
282 a.in.height = h * ip->ftheight;
283
284 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
285 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
286 }
287
288 void
289 sti_scroll(struct ite_data *ip)
290 {
291 sti_blkmv_t blkmv;
292 struct {
293 struct sti_blkmvflags flags;
294 struct sti_blkmvin in;
295 struct sti_blkmvout out;
296 } a;
297
298 sti_do_cursor(ip);
299
300 memset(&a, 0, sizeof a);
301 a.flags.flags = STI_BLKMVF_WAIT;
302 a.in.bg_colour = STI_COLOUR_BLACK;
303 a.in.fg_colour = STI_COLOUR_WHITE;
304 a.in.dstx = a.in.srcx = 0;
305 a.in.dsty = 0;
306 a.in.srcy = ip->ftheight;
307 a.in.width = ip->dwidth;
308 a.in.height = (ip->rows - 1) * ip->ftheight;
309
310 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
311 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
312 }
313
314 static void
315 sti_fontinfo(struct ite_data *ip)
316 {
317 uint32_t fontbase;
318 volatile uint8_t *fbbase = ip->fbbase;
319
320 fontbase = sti.fontbase = parseword1(fbbase, 0x30) & ~3;
321 ip->ftwidth = (uint8_t)fbbase[fontbase + 0x13];
322 ip->ftheight = (uint8_t)fbbase[fontbase + 0x17];
323 ip->rows = ip->dheight / ip->ftheight;
324 ip->cols = ip->dwidth / ip->ftwidth;
325 }
326
327 static void
328 sti_init(int full)
329 {
330 sti_init_t init;
331 struct {
332 struct sti_initflags flags;
333 struct sti_initin in;
334 struct sti_initout out;
335 } a;
336
337 memset(&a, 0, sizeof a);
338 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET;
339 if (full)
340 a.flags.flags |= STI_INITF_TEXT | STI_INITF_PBET |
341 STI_INITF_PBETI | STI_INITF_ICMT;
342 a.in.text_planes = 1;
343
344 init = (sti_init_t)(sti.code + sti.codeptr[STI_INIT_GRAPH]);
345 (*init)(&a.flags, &a.in, &a.out, &sti.cfg);
346 }
347
348 static void
349 sti_inqcfg(struct sti_inqconfout *ico)
350 {
351 sti_inqconf_t inqconf;
352 struct {
353 struct sti_inqconfflags flags;
354 struct sti_inqconfin in;
355 } a;
356
357 memset(&a, 0, sizeof a);
358 a.flags.flags = STI_INQCONFF_WAIT;
359
360 inqconf = (sti_inqconf_t)(sti.code + sti.codeptr[STI_INQ_CONF]);
361 (*inqconf)(&a.flags, &a.in, ico, &sti.cfg);
362 }
363
364 #endif
365