Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/* $NetBSD: ofw_consinit.c,v 1.27 2022/12/06 01:14:36 macallan Exp $ */

/*-
 * Copyright (c) 2007 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Tim Rightnour
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ofw_consinit.c,v 1.27 2022/12/06 01:14:36 macallan Exp $");

#include "adb.h"
#include "adbkbd.h"
#include "akbd.h"
#include "isa.h"
#include "ofb.h"
#include "pckbc.h"
#include "ukbd.h"
#include "wsdisplay.h"
#include "zsc.h"
#include "zstty.h"

#include <sys/param.h>
#include <sys/buf.h>
#include <sys/tty.h>

#include <prop/proplib.h>

#include <machine/autoconf.h>
#include <machine/trap.h>
#include <sys/bus.h>

#include <powerpc/ofw_cons.h>
#include <powerpc/ofw_machdep.h>

#include <dev/cons.h>
#include <dev/ofw/openfirm.h>

#include <dev/wscons/wsksymvar.h>
#include <dev/wscons/wscons_callbacks.h>

#if NZSC > 0
#include <machine/z8530var.h>
#endif

#if (NADB > 0)
#include <macppc/dev/adbvar.h>
#endif

#if (NUKBD > 0)
#include <dev/usb/ukbdvar.h>
struct usb_kbd_ihandles {
	struct usb_kbd_ihandles *next;
	int ihandle;
};
#endif

#if (NZSTTY > 0)
#include <dev/ic/z8530reg.h>
extern struct consdev consdev_zs;
#endif

#if (NPCKBC > 0)
#include <dev/isa/isareg.h>
#include <dev/ic/i8042reg.h>
#include <dev/ic/pckbcvar.h>
#endif

extern int console_node;

int ofkbd_ihandle = -1;

static void ofwoea_cnprobe_keyboard(void);

/*#define OFDEBUG*/

#ifdef OFDEBUG

#define OFPRINTF ofprint
#else
#define OFPRINTF while(0) printf
#endif

bool ofwoea_use_serial_console;
static struct consdev *selected_serial_consdev;

static int (*selected_keyboard)(void);

/* XXX Gross. */
#if NPCKBC > 0
static int
ofwoea_pckbd_cnattach(void)
{
	return pckbc_cnattach(&genppc_isa_io_space_tag, IO_KBD, KBCMDP,
	    PCKBC_KBD_SLOT, 0);
}
#endif

void
ofwoea_cnprobe(void)
{
	char name[32];

	OFPRINTF("console node: %08x\n", console_node);

	if (console_node == -1)
		return;

	memset(name, 0, sizeof(name));
	if (OF_getprop(console_node, "device_type", name, sizeof(name)) == -1)
		return;

	OFPRINTF("console type: %s\n", name);

	if (strcmp(name, "serial") == 0) {
		ofwoea_use_serial_console = true;
#ifdef PMAC_G5
		/* The MMU hasn't been initialized yet, use failsafe for now */
		extern struct consdev failsafe_cons;
		selected_serial_consdev = &failsafe_cons;
		aprint_verbose("Early G5 console selected "
		    "(keeping OF console for now)\n");
		return;
#endif /* PMAC_G5 */

#if (NZSTTY > 0) && !defined(MAMBO)
		OF_getprop(console_node, "name", name, sizeof(name));
		if (strcmp(name, "ch-a") == 0 || strcmp(name, "ch-b") == 0) {
			selected_serial_consdev = &consdev_zs;
		}
		return;
#endif /* NZTTY */

		/* fallback to OFW boot console (already set) */
		return;
	}

	/*
	 * We're going to use a display console.  Probe for the keyboard
	 * we'll use.
	 */
	ofwoea_cnprobe_keyboard();
}

/*
 * XXX This routine is a complete disaster, filled with platform-specific
 * XXX stuff.  Fix, plz.
 */
static void
ofwoea_cnprobe_keyboard(void)
{
	extern int ofw_stdin;

	int node, kstdin = ofw_stdin;
	char name[16];
#if (NAKBD > 0) || (NADBKBD > 0)
	int akbd;
#endif
#if NUKBD > 0
	struct usb_kbd_ihandles *ukbds;
	int ukbd;
#endif

	/*
	 * We must determine which keyboard type we have.
	 */
	node = OF_instance_to_package(kstdin);
	memset(name, 0, sizeof(name));
	OF_getprop(node, "name", name, sizeof(name));
	if (strcmp(name, "keyboard") != 0) {
		ofprint("WARNING: stdin is not a keyboard: %s\n", name);
		return;
	}

	memset(name, 0, sizeof(name));
	OF_getprop(OF_parent(node), "name", name, sizeof(name));
#if NAKBD > 0
	if (strcmp(name, "adb") == 0) {
		ofprint("console keyboard type: ADB\n");
		selected_keyboard = akbd_cnattach;
		goto kbd_found;
	}
#endif
#if NADBKBD > 0
	if (strcmp(name, "adb") == 0) {
		ofprint("console keyboard type: ADB\n");
		selected_keyboard = adbkbd_cnattach;
		goto kbd_found;
	}
#endif
#if NPCKBC > 0
	if (strcmp(name, "isa") == 0) {
		ofprint("console keyboard type: PC Keyboard\n");
		selected_keyboard = ofwoea_pckbd_cnattach;
		goto kbd_found;
	}
#endif

	/*
	 * It is not obviously an ADB/PC keyboard. Could be USB,
	 * or ADB on some firmware versions (e.g.: iBook G4)
	 * This is not enough, we have a few more problems:
	 *
	 *	(1) The stupid Macintosh firmware uses a
	 *	    `psuedo-hid' (no typo) or `pseudo-hid',
	 *	    which apparently merges all keyboards
	 *	    input into a single input stream.
	 *	    Because of this, we can't actually
	 *	    determine which controller or keyboard
	 *	    is really the console keyboard!
	 *
	 *	(2) Even if we could, the keyboard can be USB,
	 *	    and this requires a lot of the kernel to
	 *	    be running in order for it to work.
	 *
	 *      (3) If the keyboard is behind isa, we don't have enough
	 * 	    kernel setup to use it yet, so punt to the ofroutines.
	 *
	 * So, what we do is this:
	 *
	 *	(1) First check for OpenFirmware implementation
	 *	    that will not let us distinguish between
	 *	    USB and ADB. In that situation, try attaching
	 *	    anything as we can, and hope things get better
	 *	    at autoconfiguration time.
	 *
	 *	(2) Assume the keyboard is USB.
	 *	    Tell the ukbd driver that it is the console.
	 *	    At autoconfiguration time, it will attach the
	 *	    first USB keyboard instance as the console
	 *	    keyboard.
	 *
	 *	(3) Until then, so that we have _something_, we
	 *	    use the OpenFirmware I/O facilities to read
	 *	    the keyboard.
	 */

	/*
	 * stdin is /pseudo-hid/keyboard.  There is no
	 * `adb-kbd-ihandle or `usb-kbd-ihandles methods
	 * available. Try attaching as ADB.
	 * But only if ADB support is actually present.
	 *
	 * XXX This must be called before pmap_bootstrap().
	 */
	if (strcmp(name, "pseudo-hid") == 0) {
		int adb_node;

		adb_node = OF_finddevice("/pci/mac-io/via-pmu/adb");
		if (adb_node > 0) {
			ofprint("ADB support found\n");
#if NAKBD > 0
			selected_keyboard = akbd_cnattach;
#endif
#if NADBKBD > 0
			selected_keyboard = adbkbd_cnattach;
#endif
		} else {
			/* must be USB */
			ofprint("No ADB support present, assuming USB "
			       "keyboard\n");
#if NUKBD > 0
			selected_keyboard = ukbd_cnattach;
#endif
		}
		goto kbd_found;
	}

	/*
	 * stdin is /psuedo-hid/keyboard.  Test `adb-kbd-ihandle and
	 * `usb-kbd-ihandles to figure out the real keyboard(s).
	 *
	 * XXX This must be called before pmap_bootstrap().
	 */

#if NUKBD > 0
	if (OF_call_method("`usb-kbd-ihandles", kstdin, 0, 1, &ukbds) >= 0 &&
	    ukbds != NULL && ukbds->ihandle != 0 &&
	    OF_instance_to_package(ukbds->ihandle) != -1) {
		ofprint("usb-kbd-ihandles matches\n");
		ofprint("console keyboard type: USB\n");
		selected_keyboard = ukbd_cnattach;
		goto kbd_found;
	}
	/* Try old method name. */
	if (OF_call_method("`usb-kbd-ihandle", kstdin, 0, 1, &ukbd) >= 0 &&
	    ukbd != 0 &&
	    OF_instance_to_package(ukbd) != -1) {
		ofprint("usb-kbd-ihandle matches\n");
		ofprint("console keyboard type: USB\n");
		kstdin = ukbd;
		selected_keyboard = ukbd_cnattach;
		goto kbd_found;
	}
#endif

#if (NAKBD > 0) || (NADBKBD > 0)
	if (OF_call_method("`adb-kbd-ihandle", kstdin, 0, 1, &akbd) >= 0 &&
	    akbd != 0 &&
	    OF_instance_to_package(akbd) != -1) {
		ofprint("adb-kbd-ihandle matches\n");
		ofprint("console keyboard type: ADB\n");
		kstdin = akbd;
#if NAKBD > 0
		selected_keyboard = akbd_cnattach;
#endif
#if NADBKBD > 0
		selected_keyboard = adbkbd_cnattach;
#endif
		goto kbd_found;
	}
#endif

#if NUKBD > 0
	/*
	 * XXX Old firmware does not have `usb-kbd-ihandles method.  Assume
	 * XXX USB keyboard anyway.
	 */
	ofprint("defaulting to USB...");
	ofprint("console keyboard type: USB\n");
	selected_keyboard = ukbd_cnattach;
	goto kbd_found;
#endif

	/*
	 * No keyboard is found.  Just return.
	 */
	ofprint("no console keyboard\n");
	return;

kbd_found:
	ofkbd_ihandle = kstdin;
}

/*
 * Bootstrap console keyboard routines, using OpenFirmware I/O.
 */
int
ofkbd_cngetc(dev_t dev)
{
	u_char c = '\0';
	int len;

	KASSERT(ofkbd_ihandle != -1);

	do {
		len = OF_read(ofkbd_ihandle, &c, 1);
	} while (len != 1);

	return c;
}

void
cninit(void)
{
	if (ofwoea_use_serial_console) {
		if (selected_serial_consdev != NULL) {
			cn_tab = selected_serial_consdev;
			(*cn_tab->cn_probe)(cn_tab);
			(*cn_tab->cn_init)(cn_tab);
		}
		return;
	}

#if NWSDISPLAY > 0
	rascons_cnattach();
#endif
	if (selected_keyboard != NULL) {
		(*selected_keyboard)();

#if NWSDISPLAY > 0
		/*
		 * XXX This is a little gross, but we don't get to call
		 * XXX wskbd_cnattach() twice.
		 */
		wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL);
#endif
	}
}

void
ofwoea_consinit(void)
{
	static int initted = 0;

	if (initted)
		return;

	initted = 1;
	cninit();
}