xref: /netbsd-src/sys/arch/amiga/stand/bootblock/boot/console.c (revision 9e8889070d75d7738340c42b1c9731ac4433c481)
1 /* $NetBSD: console.c,v 1.16 2023/03/25 20:14:26 abs Exp $ */
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Ignatios Souvatzis.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Bootblock support routines for Intuition console support.
34  */
35 
36 #include <sys/types.h>
37 
38 #include <lib/libsa/stand.h>
39 #include "samachdep.h"
40 
41 #include "amigatypes.h"
42 #include "amigagraph.h"
43 #include "amigaio.h"
44 #include "libstubs.h"
45 
46 const u_int32_t screentags[] = {
47 	SA_Type, CUSTOMSCREEN,
48 	SA_DisplayID, 0x8000,
49 	SA_ShowTitle, 0,
50 	SA_Quiet, 1,
51 	0
52 };
53 
54 u_int32_t windowtags[] = {
55 	WA_CustomScreen, 0L,
56 	WA_Borderless, 1L,
57 	WA_Backdrop, 1L,
58 	WA_Activate, 1L,
59 	0
60 };
61 
62 struct Console {
63 	int magic;
64 	struct AmigaIO *cnior;
65 	struct TimerIO *tmior;
66 	struct MsgPort *cnmp;
67 	struct Screen *s;
68 	struct Window *w;
69 } *ConsoleBase;
70 static struct Console myConsole;
71 
72 u_int16_t timelimit;
73 
74 #ifdef SERCONSOLE
75 static int use_serconsole;
76 extern char default_command[];
77 
78 static void
conspreinit(void)79 conspreinit(void)
80 {
81 	char *p = default_command;
82 	char c;
83 
84 	/*
85 	 * preparse the default command to check for -C option
86 	 * that selects the serial console
87 	 */
88 	while ((c = *p)) {
89 		while (c == ' ')
90 			c = *++p;
91 		if (c == '-') {
92 			while ((c = *++p) && c != ' ') {
93 				switch (c) {
94 				case 'C':
95 					use_serconsole = 1;
96 					break;
97 				}
98 			}
99 		} else {
100 			while ((c = *++p) && c != ' ')
101 				;
102 		}
103 	}
104 }
105 #endif
106 
107 int
consinit(void * consptr)108 consinit(void *consptr) {
109 	struct Console *mc;
110 
111 	if (consptr != NULL) {
112 		/* Check magic? */
113 		mc = consptr;		/* Use existing console */
114 		goto done;
115 	}
116 
117 	mc = &myConsole;
118 	IntuitionBase = OpenLibrary("intuition.library", 36L);
119 	if (IntuitionBase == 0)
120 		goto err;
121 
122 	mc->s = OpenScreenTagList(0, screentags);
123 	if (!mc->s)
124 		goto err;
125 
126 	windowtags[1] = (u_int32_t)mc->s;
127 	mc->w = OpenWindowTagList(0, windowtags);
128 	if (!mc->w)
129 		goto err;
130 
131 	mc->cnmp = CreateMsgPort();
132 
133 	if (!mc->cnmp)
134 		goto err;
135 
136 	mc->cnior = (struct AmigaIO *)CreateIORequest(mc->cnmp, sizeof(struct AmigaIO));
137 	if (!mc->cnior)
138 		goto err;
139 
140 	mc->cnior->buf = (void *)mc->w;
141 	mc->cnior->length = 136; /* sizeof(struct Window) */
142 	if (OpenDevice("console.device", 0, mc->cnior, 0)) {
143 		/* Kickstart 3.2 decided not to initialize console.device
144                 before bootstrap, so we have to do it ourselves. */
145 		void *res = FindResident("console.device");
146 		if (!res)
147 			goto err;
148 
149 		if (!InitResident(res, 0))
150 			goto err;
151 
152 		if (OpenDevice("console.device", 0, mc->cnior, 0))
153 			goto err;
154 	}
155 
156 	mc->tmior = (struct TimerIO *)CreateIORequest(mc->cnmp, sizeof(struct TimerIO));
157 	if (!mc->tmior)
158 		goto err;
159 
160 	if (OpenDevice("timer.device", 0, (struct AmigaIO*)mc->tmior, 0))
161 		goto err;
162 
163 done:
164 
165 #ifdef SERCONSOLE
166 	conspreinit();
167 	if (use_serconsole)
168 		RawIOInit();
169 #endif
170 
171 	ConsoleBase = mc;
172 	return 0;
173 
174 err:
175 #ifdef notyet
176 	if (mc->tmior)
177 		DeleteIORequest(mc->tmior);
178 
179 	if (mc->cnior)
180 		DeleteIORequest(mc->cnior);
181 
182 	if (mc->cnmp)
183 		DeleteMsgPort(mc->cnmp);
184 
185 	if (mc->w)
186 		CloseWindow(mc->w);
187 
188 	if (mc->s)
189 		CloseScreen(mc->s);
190 	if (IntuitionBase)
191 		CloseLibrary(IntuitionBase);
192 #endif
193 
194 	return 1;
195 }
196 
197 #ifdef _PRIMARY_BOOT
198 int
consclose(void)199 consclose(void)
200 {
201 	struct Console *mc = ConsoleBase;
202 
203 	if (mc == NULL)
204 		return 0;
205 	if (mc->tmior) {
206 		CloseDevice((struct AmigaIO *)mc->tmior);
207 		DeleteIORequest(mc->tmior);
208 	}
209 
210 	if (mc->cnior) {
211 		CloseDevice(mc->cnior);
212 		DeleteIORequest(mc->cnior);
213 	}
214 
215 	if (mc->cnmp)
216 		DeleteMsgPort(mc->cnmp);
217 
218 	if (mc->w)
219 		CloseWindow(mc->w);
220 
221 	if (mc->s)
222 		CloseScreen(mc->s);
223 	if (IntuitionBase)
224 		CloseLibrary(IntuitionBase);
225 	ConsoleBase = NULL;
226 	return 0;
227 }
228 #endif
229 
230 void
putchar(int c)231 putchar(int c)
232 {
233 	struct Console *mc = ConsoleBase;
234 	char buf = c;
235 
236 	mc->cnior->length = 1;
237 	mc->cnior->buf = &buf;
238 	mc->cnior->cmd = Cmd_Wr;
239 
240 #ifdef SERCONSOLE
241 	if (use_serconsole)
242 		RawPutChar((int32_t)c);
243 #endif
244 
245 	(void)DoIO(mc->cnior);
246 }
247 
248 void
puts(char * s)249 puts(char *s)
250 {
251 	struct Console *mc = ConsoleBase;
252 
253 	mc->cnior->length = -1;
254 	mc->cnior->buf = s;
255 	mc->cnior->cmd = Cmd_Wr;
256 
257 #ifdef SERCONSOLE
258 	if (use_serconsole) {
259 		while (*s)
260 			RawPutChar(*s++);
261 	}
262 #endif
263 
264 	(void)DoIO(mc->cnior);
265 }
266 
267 int
getchar(void)268 getchar(void)
269 {
270 	struct AmigaIO *ior;
271 	char c = '\n';
272 	struct Console *mc = ConsoleBase;
273 	unsigned long ticks;
274 #ifdef SERCONSOLE
275 	int32_t r;
276 #endif
277 
278 	mc->cnior->length = 1;
279 	mc->cnior->buf = &c;
280 	mc->cnior->cmd = Cmd_Rd;
281 
282 	SendIO(mc->cnior);
283 
284 	ticks = 10 * timelimit;
285 	do {
286 		if (timelimit == 0)
287 			ticks = 2;
288 
289 		mc->tmior->cmd = Cmd_Addtimereq;
290 		mc->tmior->secs = 0;
291 		mc->tmior->usec = 100000;
292 		SendIO((struct AmigaIO *)mc->tmior);
293 
294 		ior = WaitPort(mc->cnmp);
295 		if (ior == mc->cnior) {
296 			AbortIO((struct AmigaIO *)mc->tmior);
297 			ticks = 1;
298 		} else /* if (ior == mc->tmior) */ {
299 #ifdef SERCONSOLE
300 			if (use_serconsole) {
301 				r = RawMayGetChar();
302 				if (r != -1) {
303 					c = r;
304 					ticks = 1;
305 				}
306 			}
307 #endif
308 			if (ticks == 1)
309 				AbortIO((struct AmigaIO *)mc->cnior);
310 		}
311 		WaitIO((struct AmigaIO *)mc->tmior);
312 
313 		--ticks;
314 	} while (ticks != 0);
315 	timelimit = 0;
316 
317 	(void)WaitIO(mc->cnior);
318 	return c;
319 }
320