ite_sti.c revision 1.2.6.1 1 /* $NetBSD: ite_sti.c,v 1.2.6.1 2025/08/02 05:55:39 perseant 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 case ERASE_CURSOR:
238 default:
239 sti_do_cursor(ip);
240 break;
241 }
242 }
243
244 static void
245 sti_do_cursor(struct ite_data *ip)
246 {
247 sti_blkmv_t blkmv;
248 struct {
249 struct sti_blkmvflags flags;
250 struct sti_blkmvin in;
251 struct sti_blkmvout out;
252 } a;
253
254 memset(&a, 0, sizeof a);
255 a.flags.flags = STI_BLKMVF_WAIT | STI_BLKMVF_COLR;
256 a.in.fg_colour = STI_COLOUR_BLACK;
257 a.in.bg_colour = STI_COLOUR_WHITE;
258 a.in.dstx = a.in.srcx = ip->cursorx * ip->ftwidth;
259 a.in.dsty = a.in.srcy = ip->cursory * ip->ftheight;
260 a.in.width = ip->ftwidth;
261 a.in.height = ip->ftheight;
262
263 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
264 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
265 }
266
267 void
268 sti_clear(struct ite_data *ip, int sy, int sx, int h, int w)
269 {
270 sti_blkmv_t blkmv;
271 struct {
272 struct sti_blkmvflags flags;
273 struct sti_blkmvin in;
274 struct sti_blkmvout out;
275 } a;
276
277 memset(&a, 0, sizeof a);
278 a.flags.flags = STI_BLKMVF_WAIT | STI_BLKMVF_CLR;
279 a.in.bg_colour = STI_COLOUR_BLACK;
280 a.in.dstx = a.in.srcx = sx * ip->ftwidth;
281 a.in.dsty = a.in.srcy = sy * ip->ftheight;
282 a.in.width = w * ip->ftwidth;
283 a.in.height = h * ip->ftheight;
284
285 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
286 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
287 }
288
289 void
290 sti_scroll(struct ite_data *ip)
291 {
292 sti_blkmv_t blkmv;
293 struct {
294 struct sti_blkmvflags flags;
295 struct sti_blkmvin in;
296 struct sti_blkmvout out;
297 } a;
298
299 memset(&a, 0, sizeof a);
300 a.flags.flags = STI_BLKMVF_WAIT;
301 a.in.bg_colour = STI_COLOUR_BLACK;
302 a.in.fg_colour = STI_COLOUR_WHITE;
303 a.in.dstx = a.in.srcx = 0;
304 a.in.dsty = 0;
305 a.in.srcy = ip->ftheight;
306 a.in.width = ip->dwidth;
307 a.in.height = (ip->rows - 1) * ip->ftheight;
308
309 blkmv = (sti_blkmv_t)(sti.code + sti.codeptr[STI_BLOCK_MOVE]);
310 (*blkmv)(&a.flags, &a.in, &a.out, &sti.cfg);
311 }
312
313 static void
314 sti_fontinfo(struct ite_data *ip)
315 {
316 uint32_t fontbase;
317 volatile uint8_t *fbbase = ip->fbbase;
318
319 fontbase = sti.fontbase = parseword1(fbbase, 0x30) & ~3;
320 ip->ftwidth = (uint8_t)fbbase[fontbase + 0x13];
321 ip->ftheight = (uint8_t)fbbase[fontbase + 0x17];
322 ip->rows = ip->dheight / ip->ftheight;
323 ip->cols = ip->dwidth / ip->ftwidth;
324 }
325
326 static void
327 sti_init(int full)
328 {
329 sti_init_t init;
330 struct {
331 struct sti_initflags flags;
332 struct sti_initin in;
333 struct sti_initout out;
334 } a;
335
336 memset(&a, 0, sizeof a);
337 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET;
338 if (full)
339 a.flags.flags |= STI_INITF_TEXT | STI_INITF_PBET |
340 STI_INITF_PBETI | STI_INITF_ICMT;
341 a.in.text_planes = 1;
342
343 init = (sti_init_t)(sti.code + sti.codeptr[STI_INIT_GRAPH]);
344 (*init)(&a.flags, &a.in, &a.out, &sti.cfg);
345 }
346
347 static void
348 sti_inqcfg(struct sti_inqconfout *ico)
349 {
350 sti_inqconf_t inqconf;
351 struct {
352 struct sti_inqconfflags flags;
353 struct sti_inqconfin in;
354 } a;
355
356 memset(&a, 0, sizeof a);
357 a.flags.flags = STI_INQCONFF_WAIT;
358
359 inqconf = (sti_inqconf_t)(sti.code + sti.codeptr[STI_INQ_CONF]);
360 (*inqconf)(&a.flags, &a.in, ico, &sti.cfg);
361 }
362
363 #endif
364