xref: /netbsd-src/sys/arch/sandpoint/sandpoint/machdep.c (revision f36002f244a49908fef9cba8789032bdbf48d572)
1 /*	$NetBSD: machdep.c,v 1.70 2024/03/05 14:15:35 thorpej Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.70 2024/03/05 14:15:35 thorpej Exp $");
36 
37 #include "opt_compat_netbsd.h"
38 #include "opt_ddb.h"
39 #include "opt_interrupt.h"
40 #include "opt_modular.h"
41 
42 #include <sys/param.h>
43 #include <sys/buf.h>
44 #include <sys/bus.h>
45 #include <sys/conf.h>
46 #include <sys/device.h>
47 #include <sys/exec.h>
48 #include <sys/extent.h>
49 #include <sys/intr.h>
50 #include <sys/kernel.h>
51 #include <sys/ksyms.h>
52 #include <sys/mbuf.h>
53 #include <sys/module.h>
54 #include <sys/mount.h>
55 #include <sys/msgbuf.h>
56 #include <sys/proc.h>
57 #include <sys/reboot.h>
58 #include <sys/syscallargs.h>
59 #include <sys/sysctl.h>
60 #include <sys/syslog.h>
61 #include <sys/systm.h>
62 
63 #include <uvm/uvm_extern.h>
64 
65 #include <machine/powerpc.h>
66 #include <machine/bootinfo.h>
67 
68 #include <powerpc/pmap.h>
69 #include <powerpc/trap.h>
70 
71 #include <powerpc/oea/bat.h>
72 #include <powerpc/openpic.h>
73 #include <powerpc/pic/picvar.h>
74 
75 #ifdef DDB
76 #include <powerpc/db_machdep.h>
77 #include <ddb/db_extern.h>
78 #endif
79 
80 #include <dev/cons.h>
81 #include <sys/termios.h>
82 
83 #include "com.h"
84 #if (NCOM > 0)
85 #include <dev/ic/comreg.h>
86 #include <dev/ic/comvar.h>
87 #endif
88 
89 #include "com_eumb.h"
90 #if (NCOM_EUMB > 0)
91 #include <sandpoint/sandpoint/eumbvar.h>
92 #endif
93 
94 #include "pcib.h"
95 #include "ksyms.h"
96 
97 char bootinfo[BOOTINFO_MAXSIZE];
98 void (*md_reboot)(int);
99 
100 void initppc(u_int, u_int, u_int, void *);
101 void consinit(void);
102 void sandpoint_bus_space_init(void);
103 size_t mpc107memsize(void);
104 
105 /* we support single chunk of memory */
106 struct mem_region physmemr[2], availmemr[2];
107 
108 paddr_t avail_end;
109 struct pic_ops *isa_pic = NULL;
110 extern int primary_pic;
111 
112 #if NKSYMS || defined(DDB) || defined(MODULAR)
113 extern void *startsym, *endsym;
114 #endif
115 
116 #if 1
117 extern struct consdev kcomcons;
118 #endif
119 
120 void
initppc(u_int startkernel,u_int endkernel,u_int args,void * btinfo)121 initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo)
122 {
123 	extern u_long ticks_per_sec, ns_per_tick;
124 	struct btinfo_magic *bi_magic = btinfo;
125 	struct btinfo_memory *meminfo;
126 	struct btinfo_clock *clockinfo;
127 	size_t memsize;
128 	u_long ticks;
129 
130 	if ((unsigned)btinfo != 0 && (unsigned)btinfo < startkernel
131 	    && bi_magic->magic == BOOTINFO_MAGIC)
132 		memcpy(bootinfo, btinfo, sizeof(bootinfo));
133 	else
134 		args = RB_SINGLE;	/* boot via S-record loader */
135 
136 	meminfo = lookup_bootinfo(BTINFO_MEMORY);
137 	if (meminfo)
138 		memsize = meminfo->memsize & ~PGOFSET;
139 	else
140 		memsize = mpc107memsize();
141 	physmemr[0].start = 0;
142 	physmemr[0].size = memsize;
143 	physmemr[1].size = 0;
144 	availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET;
145 	availmemr[0].size = memsize - availmemr[0].start;
146 	availmemr[1].size = 0;
147 	avail_end = physmemr[0].start + physmemr[0].size; /* XXX */
148 
149 	clockinfo = lookup_bootinfo(BTINFO_CLOCK);
150 	if (clockinfo)
151 		ticks = clockinfo->ticks_per_sec;
152 	else {
153 		ticks = 1000000000;	/* 100 MHz */
154 		ticks /= 4;		/* 4 cycles per DEC tick */
155 	}
156 	ticks_per_sec = ticks;
157 	ns_per_tick = 1000000000 / ticks_per_sec;
158 
159 	/*
160 	 * boothowto
161 	 */
162 	boothowto = args;
163 
164 	/*
165 	 * Now setup fixed bat registers
166 	 * We setup a pair of BAT to have "Map B" layout, one for the
167 	 * PCI memory space, another to cover many; MPC107/MPC824x EUMB,
168 	 * ISA mem, PCI/ISA I/O, PCI configuration, PCI interrupt
169 	 * acknowledge and flash/ROM space.
170 	 */
171 	oea_batinit(
172 	    0x80000000, BAT_BL_256M,	/* SANDPOINT_BUS_SPACE_MEM */
173 	    0xfc000000, BAT_BL_64M,	/* _EUMB|_IO */
174 	    0x70000000, BAT_BL_8M,	/* only for NH230 board control */
175 	    0);
176 
177 	/* Install vectors and interrupt handler */
178 	oea_init(NULL);
179 
180 #if 1 /* bumpy ride in pre-dawn time, for people knows what he/she is doing */
181 	cn_tab = &kcomcons;
182 	(*cn_tab->cn_init)(&kcomcons);
183 
184 #if NKSYMS || defined(DDB) || defined(MODULAR)
185 	ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
186 #endif
187 #ifdef DDB
188 	if (boothowto & RB_KDB)
189 		Debugger();
190 #endif
191 #endif
192 
193 	/* Initialize bus_space */
194 	sandpoint_bus_space_init();
195 
196 	/* Initialize the console */
197 	consinit();
198 
199 	uvm_md_init();
200 
201 	/* Initialize pmap module */
202 	pmap_bootstrap(startkernel, endkernel);
203 
204 #if 0 /* NKSYMS || defined(DDB) || defined(MODULAR) */
205 	ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
206 #endif
207 }
208 
209 void
mem_regions(struct mem_region ** mem,struct mem_region ** avail)210 mem_regions(struct mem_region **mem, struct mem_region **avail)
211 {
212 
213 	*mem = physmemr;
214 	*avail = availmemr;
215 }
216 
217 /*
218  * Machine dependent startup code.
219  */
220 void
cpu_startup(void)221 cpu_startup(void)
222 {
223 	struct btinfo_prodfamily *bi_fam;
224 	struct btinfo_model *bi_model;
225 	char prod_name[32];
226 	char *model;
227 	void *baseaddr;
228 	int msr;
229 
230 	/*
231 	 * Do common startup.
232 	 */
233 	bi_fam = lookup_bootinfo(BTINFO_PRODFAMILY);
234 	bi_model = lookup_bootinfo(BTINFO_MODEL);
235 	if (bi_fam != NULL) {
236 		snprintf(prod_name, sizeof(prod_name), "%s %s", bi_fam->name,
237 		    bi_model != NULL ? bi_model->name : "");
238 		model = prod_name;
239 	} else
240 		model = NULL;
241 	oea_startup(model);
242 
243 	/*
244 	 * Prepare EPIC and install external interrupt handler.
245 	 *  0..15	used by South bridge i8259 PIC if exists.
246 	 *  16..39/41	EPIC interrupts, 24 source or 26 source.
247 	 */
248 	baseaddr = (void *)(SANDPOINT_BUS_SPACE_EUMB + 0x40000);
249 	pic_init();
250 
251 #ifdef PIC_I8259
252 	isa_pic = setup_i8259();
253 	(void)setup_mpcpic(baseaddr);
254 	primary_pic = 1;
255 	/*
256 	 * set up i8259 as a cascade on EPIC irq 0.
257 	 * XXX exceptional SP2 has 17
258 	 */
259 	intr_establish_xname(16, IST_LEVEL, IPL_HIGH, pic_handle_intr, isa_pic,
260 	    "i8259");
261 #else
262 	mpcpic_reserv16();
263 	(void)setup_mpcpic(baseaddr);
264 	primary_pic = 0;
265 #endif
266 
267 	oea_install_extint(pic_ext_intr);
268 
269 	/*
270 	 * Now that we have VM, malloc()s are OK in bus_space.
271 	 */
272 	bus_space_mallocok();
273 
274 	/*
275 	 * Now allow hardware interrupts.
276 	 */
277 	splraise(-1);
278 	__asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
279 	    :	"=r"(msr)
280 	    :	"K"(PSL_EE));
281 }
282 
283 #if (NPCIB > 0)
284 struct btinfo_console bi_cons = { { 0, 0 },  "com", 0x3f8, 38400 };
285 #else
286 struct btinfo_console bi_cons = { { 0, 0 },  "eumb", 0x4600, 57600 };
287 #endif
288 
289 /*
290  * lookup_bootinfo:
291  * Look up information in bootinfo of boot loader.
292  */
293 void *
lookup_bootinfo(int type)294 lookup_bootinfo(int type)
295 {
296 	struct btinfo_common *bt;
297 	struct btinfo_common *help = (struct btinfo_common *)bootinfo;
298 
299 	if (help->next == 0)
300 		return (NULL);	/* bootinfo[] was not made */
301 	do {
302 		bt = help;
303 		if (bt->type == type)
304 			return (help);
305 		help = (struct btinfo_common *)((char*)help + bt->next);
306 	} while (bt->next &&
307 		(size_t)help < (size_t)bootinfo + BOOTINFO_MAXSIZE);
308 
309 	return (NULL);
310 }
311 
312 /*
313  * consinit
314  * Initialize system console.
315  */
316 void
consinit(void)317 consinit(void)
318 {
319 	struct btinfo_console *bi;
320 	static int initted;
321 
322 	if (initted)
323 		return;
324 	initted = 1;
325 
326 	bi = lookup_bootinfo(BTINFO_CONSOLE);
327 	if (bi == NULL)
328 		bi = &bi_cons;
329 
330 #if (NCOM > 0)
331 	if (strcmp(bi->devname, "com") == 0) {
332 		bus_space_tag_t tag = &genppc_isa_io_space_tag;
333 		if (comcnattach(tag, bi->addr, bi->speed,
334 		    COM_FREQ, COM_TYPE_NORMAL,
335 		    ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
336 			panic("can't init com serial console");
337 		return;
338 	}
339 #endif
340 #if (NCOM_EUMB > 0)
341 	if (strcmp(bi->devname, "eumb") == 0) {
342 		bus_space_tag_t tag = &sandpoint_eumb_space_tag;
343 		extern u_long ticks_per_sec;
344 
345 		if (eumbcnattach(tag, bi->addr, bi->speed,
346 		    4 * ticks_per_sec, COM_TYPE_NORMAL,
347 		    ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
348 			panic("can't init eumb serial console");
349 		return;
350 	}
351 #endif
352 	panic("console device missing -- serial console not in kernel");
353 	/* Of course, this is moot if there is no console... */
354 }
355 
356 /*
357  * Halt or reboot the machine after syncing/dumping according to howto.
358  */
359 void
cpu_reboot(int howto,char * what)360 cpu_reboot(int howto, char *what)
361 {
362 	extern void jump_to_ppc_reset_entry(void);	/* from locore.S */
363 	static int syncing;
364 	register_t msr;
365 
366 	boothowto = howto;
367 	if ((howto & RB_NOSYNC) == 0 && syncing == 0) {
368 		syncing = 1;
369 		vfs_shutdown();		/* sync */
370 	}
371 
372 	/* Disable intr */
373 	/* splhigh(); */
374 
375 	/* Do dump if requested */
376 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
377 		oea_dumpsys();
378 
379 	doshutdownhooks();
380 
381 	pmf_system_shutdown(boothowto);
382 
383 	if ((howto & RB_POWERDOWN) == RB_HALT) {
384 		printf("\n");
385 		printf("The operating system has halted.\n");
386 		printf("Please press any key to reboot.\n\n");
387 		cnpollc(1);	/* for proper keyboard command handling */
388 		cngetc();
389 		cnpollc(0);
390 		howto = RB_AUTOBOOT;
391 	}
392 
393 	if (md_reboot != NULL)
394 		(*md_reboot)(howto);
395 
396 	/*
397 	 * No reboot method defined. So we disable the MMU and jump
398 	 * through the firmware's reset vector.
399 	 */
400 	msr = mfmsr();
401 	msr &= ~PSL_EE;
402 	mtmsr(msr);
403 	__asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
404 	msr &= ~(PSL_ME | PSL_DR | PSL_IR);
405 	mtmsr(msr);
406 	jump_to_ppc_reset_entry();
407 	for (;;);
408 }
409 
410 #ifdef MODULAR
411 void
module_init_md(void)412 module_init_md(void)
413 {
414         struct btinfo_modulelist *module;
415 	struct bi_modulelist_entry *bi, *biend;
416 
417         module = lookup_bootinfo(BTINFO_MODULELIST);
418         if (module == NULL)
419 		return;
420 	bi = (struct bi_modulelist_entry *)(module + 1);
421 	biend = bi + module->num;
422 	while (bi < biend) {
423 		printf("module %s at 0x%08x size %x\n",
424 		    bi->kmod, bi->base, bi->len);
425 		/* module_prime(bi->kmod, (void *)bi->base, bi->len); */
426 		bi += 1;
427 	}
428 }
429 #endif /* MODULAR */
430 
431 struct powerpc_bus_space sandpoint_io_space_tag = {
432 	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE,
433 	0xfe000000, 0x00000000, 0x00c00000,
434 };
435 struct powerpc_bus_space genppc_isa_io_space_tag = {
436 	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE,
437 	0xfe000000, 0x00000000, 0x00010000,
438 };
439 struct powerpc_bus_space sandpoint_mem_space_tag = {
440 	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
441 	0x00000000, 0x80000000, 0xfc000000,
442 };
443 struct powerpc_bus_space genppc_isa_mem_space_tag = {
444 	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
445 	0x00000000, 0xfd000000, 0xfe000000,
446 };
447 struct powerpc_bus_space sandpoint_eumb_space_tag = {
448 	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
449 	0xfc000000, 0x00000000, 0x00100000,
450 };
451 struct powerpc_bus_space sandpoint_flash_space_tag = {
452 	_BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
453 	0x00000000, 0xff000000, 0xffffffff,
454 };
455 struct powerpc_bus_space sandpoint_nhgpio_space_tag = {
456 	_BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
457 	0x70000000, 0x00000000, 0x00001000,
458 };
459 
460 static char ex_storage[7][EXTENT_FIXED_STORAGE_SIZE(8)]
461     __attribute__((aligned(8)));
462 
463 void
sandpoint_bus_space_init(void)464 sandpoint_bus_space_init(void)
465 {
466 	int error;
467 
468 	error = bus_space_init(&sandpoint_io_space_tag, "ioport",
469 	    ex_storage[0], sizeof(ex_storage[0]));
470 	if (error)
471 		panic("sandpoint_bus_space_init: can't init io tag");
472 
473 	error = extent_alloc_region(sandpoint_io_space_tag.pbs_extent,
474 	    0x10000, 0x7fffff, EX_NOWAIT);
475 	if (error)
476 		panic("sandpoint_bus_space_init: can't block out reserved I/O"
477 		    " space 0x10000-0x7fffff: error=%d", error);
478 
479 	error = bus_space_init(&sandpoint_mem_space_tag, "iomem",
480 	    ex_storage[1], sizeof(ex_storage[1]));
481 	if (error)
482 		panic("sandpoint_bus_space_init: can't init mem tag");
483 
484 	error = bus_space_init(&genppc_isa_io_space_tag, "isa-ioport",
485 	    ex_storage[2], sizeof(ex_storage[2]));
486 	if (error)
487 		panic("sandpoint_bus_space_init: can't init isa io tag");
488 
489 	error = bus_space_init(&genppc_isa_mem_space_tag, "isa-iomem",
490 	    ex_storage[3], sizeof(ex_storage[3]));
491 	if (error)
492 		panic("sandpoint_bus_space_init: can't init isa mem tag");
493 
494 	error = bus_space_init(&sandpoint_eumb_space_tag, "eumb",
495 	    ex_storage[4], sizeof(ex_storage[4]));
496 	if (error)
497 		panic("sandpoint_bus_space_init: can't init eumb tag");
498 
499 	error = bus_space_init(&sandpoint_flash_space_tag, "flash",
500 	    ex_storage[5], sizeof(ex_storage[5]));
501 	if (error)
502 		panic("sandpoint_bus_space_init: can't init flash tag");
503 
504 	/* NH230/231 only: extended ROM space at 0x70000000 for GPIO */
505 	error = bus_space_init(&sandpoint_nhgpio_space_tag, "nh23x-gpio",
506 	    ex_storage[6], sizeof(ex_storage[6]));
507 	if (error)
508 		panic("sandpoint_bus_space_init: can't init nhgpio tag");
509 }
510 
511 #define MPC107_EUMBBAR		0x78	/* Eumb base address */
512 #define MPC107_MEMENDADDR1	0x90	/* Memory ending address 1 */
513 #define MPC107_EXTMEMENDADDR1	0x98	/* Extd. memory ending address 1 */
514 #define MPC107_MEMEN		0xa0	/* Memory enable */
515 
516 size_t
mpc107memsize(void)517 mpc107memsize(void)
518 {
519 	/*
520 	 * assumptions here;
521 	 * - first 4 sets of SDRAM controlling register have been
522 	 * set right in the ascending order.
523 	 * - total SDRAM size is the last valid SDRAM address +1.
524 	 */
525 	unsigned val, n, bankn, end;
526 
527 	out32rb(0xfec00000, (1U<<31) | MPC107_MEMEN);
528 	val = in32rb(0xfee00000);
529 	if ((val & 0xf) == 0)
530 		return 32 * 1024 * 1024; /* eeh? */
531 
532 	bankn = 0;
533 	for (n = 0; n < 4; n++) {
534 		if ((val & (1U << n)) == 0)
535 			break;
536 		bankn = n;
537 	}
538 	bankn = bankn * 8;
539 
540 	/* the format is "00 xx xxxxxxxx << 20" */
541 	out32rb(0xfec00000, (1U<<31) | MPC107_EXTMEMENDADDR1); /* bit 29:28 */
542 	val = in32rb(0xfee00000);
543 	end =  ((val >> bankn) & 0x03) << 28;
544 	out32rb(0xfec00000, (1U<<31) | MPC107_MEMENDADDR1);    /* bit 27:20 */
545 	val = in32rb(0xfee00000);
546 	end |= ((val >> bankn) & 0xff) << 20;
547 	end |= 0xfffff;					       /* bit 19:00 */
548 
549 	return (end + 1); /* recognize this as the amount of SDRAM */
550 }
551 
552 /* XXX XXX debug purpose only XXX XXX */
553 
554 static dev_type_cninit(kcomcninit);
555 static dev_type_cngetc(kcomcngetc);
556 static dev_type_cnputc(kcomcnputc);
557 static dev_type_cnpollc(kcomcnpollc);
558 
559 struct consdev kcomcons = {
560 	NULL, kcomcninit, kcomcngetc, kcomcnputc, kcomcnpollc, NULL,
561 	NULL, NULL, NODEV, CN_NORMAL
562 };
563 
564 #define THR		0
565 #define RBR		0
566 #define LSR		5
567 #define LSR_THRE	0x20
568 #define UART_READ(r)		*(volatile char *)(uartbase + (r))
569 #define UART_WRITE(r, v)	*(volatile char *)(uartbase + (r)) = (v)
570 #define LSR_RFE		0x80
571 #define LSR_TXEMPTY		0x20
572 #define LSR_BE			0x10
573 #define LSR_FE			0x08
574 #define LSR_PE			0x04
575 #define LSR_OE			0x02
576 #define LSR_RXREADY		0x01
577 #define LSR_ANYE		(LSR_OE|LSR_PE|LSR_FE|LSR_BE)
578 
579 static unsigned uartbase = 0xfe0003f8;
580 
581 static void
kcomcninit(struct consdev * cn)582 kcomcninit(struct consdev *cn)
583 {
584 	struct btinfo_console *bi = lookup_bootinfo(BTINFO_CONSOLE);
585 
586 	if (bi == NULL)
587 		bi = &bi_cons;
588 	if (strcmp(bi->devname, "com") == 0)
589 		uartbase = 0xfe000000 + bi->addr;
590 	else if (strcmp(bi->devname, "eumb") == 0)
591 		uartbase = 0xfc000000 + bi->addr;
592 	/*
593 	 * we do not touch UART operating parameters since bootloader
594 	 * is supposed to have done well.
595 	 */
596 }
597 
598 static int
kcomcngetc(dev_t dev)599 kcomcngetc(dev_t dev)
600 {
601 	unsigned lsr;
602 	int s, c;
603 
604 	s = splserial();
605 #if 1
606 	do {
607 		lsr = UART_READ(LSR);
608 	} while ((lsr & LSR_ANYE) || (lsr & LSR_RXREADY) == 0);
609 #else
610     again:
611 	do {
612 		lsr = UART_READ(LSR);
613 	} while ((lsr & LSR_RXREADY) == 0);
614 	if (lsr & (LSR_BE | LSR_FE | LSR_PE)) {
615 		(void)UART_READ(RBR);
616 		goto again;
617 	}
618 #endif
619 	c = UART_READ(RBR);
620 	splx(s);
621 	return c & 0xff;
622 }
623 
624 static void
kcomcnputc(dev_t dev,int c)625 kcomcnputc(dev_t dev, int c)
626 {
627 	unsigned lsr, timo;
628 	int s;
629 
630 	s = splserial();
631 	timo = 150000;
632 	do {
633 		lsr = UART_READ(LSR);
634 	} while (timo-- > 0 && (lsr & LSR_TXEMPTY) == 0);
635 	if (timo > 0)
636 		UART_WRITE(THR, c);
637 	splx(s);
638 }
639 
640 static void
kcomcnpollc(dev_t dev,int on)641 kcomcnpollc(dev_t dev, int on)
642 {
643 }
644 
645 SYSCTL_SETUP(sysctl_machdep_prodfamily, "sysctl machdep prodfamily")
646 {
647 	const struct sysctlnode *mnode, *node;
648 	struct btinfo_prodfamily *pfam;
649 
650 	pfam = lookup_bootinfo(BTINFO_PRODFAMILY);
651 	if (pfam != NULL) {
652 		sysctl_createv(NULL, 0, NULL, &mnode,
653 		    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
654 		    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
655 
656 		sysctl_createv(NULL, 0, &mnode, &node,
657 		    CTLFLAG_PERMANENT, CTLTYPE_STRING, "prodfamily",
658 		    SYSCTL_DESCR("Board family name."),
659 		    NULL, 0, pfam->name, 0,
660 		    CTL_CREATE, CTL_EOL);
661 	}
662 }
663