Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 May 2014 20:54:49 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Andrew Turner <andrew@fubar.geek.nz>
Cc:        svn-src-projects@freebsd.org, src-committers@freebsd.org, Bruce Evans <brde@optusnet.com.au>
Subject:   Re: svn commit: r265268 - projects/arm64/sys/arm64/arm64
Message-ID:  <20140504202222.H1763@besplex.bde.org>
In-Reply-To: <20140504105608.70a60909@bender.Home>
References:  <201405031527.s43FRUTg019278@svn.freebsd.org> <20140504182755.K1388@besplex.bde.org> <20140504105608.70a60909@bender.Home>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 4 May 2014, Andrew Turner wrote:

> On Sun, 4 May 2014 19:25:06 +1000 (EST)
> Bruce Evans <brde@optusnet.com.au> wrote:
>
>> On Sat, 3 May 2014, Andrew Turner wrote:
>>
>>> Log:
>>>  Replace panic with printf in spinlock_{enter,exit} as panic makes
>>> use of spinlocks.
>>
>> printf has been broken to use spinlocks too.  It used to be careful to
>> use atomic operations to avoid locking.  Most console drivers are
>> broken too.  Some serial ones avoid locking in debugger mode only.
>
> This is a stub function. I need to implement it, however I'm working on
> other parts of the early code and would prefer it if panic at least
> told me what called it even if it is broken.
>
> I'm not yet using a console driver and instead using EARLY_PRINTF with
> a function that relies on the early boot code mapping the UART with an
> identity map. This contains no locking and will produce incorrect
> output when too many characters are sent to it, however as this code is
> only run on a hardware simulator that appears to output data with no
> latency this has not been a problem.

In 386BSD, I used a combination of my debugger and "LED"s faked on the
vga frame buffer and never bothered to make printf work very early
(my debugger has its own vga and serial output routines, so it is
independent of the kernel i/o, but this depends on the vga mode being
text and not changing too much).

Here is my vga splatting code for syscons.  This is very suitable for
EARLY_PRINTF too if you have a vga (or just a text-mode frame buffer).
It has full (atomic) locking but no formatting (not even linefeeds)
to keep it simple.  It is not quite as simple as for a simple uart.
Pixel mode would be harder. Setting up fonts for text mode would be
hard if the early boot (BIOS) code didn't do it.  USB uarts would
be much harder.  And we really should have ethernet consoles by now.

syscons.c.dif:
@ ...
@ ***************
@ *** 246,249 ****
@ --- 251,315 ----
@   };
@ 
@ + static char bde_putc_log[0x40000];
@ + static int bde_putc_logindex;
@ + static int bde_putc_scrindex;
@ + 
@ + static void
@ + bde_putc(int c)
@ + {
@ + 	static u_short attrs[2] = { FG_YELLOW << 8, FG_LIGHTRED << 8 };

Color coding for 2 CPUs.  Could use more colors/attributes for more CPUs.
The output may be interleaved, and then it is difficult to read even with
this color coding.  Nice patterns though.  EARLY_PRINTF probably doesn't
need this.

@ + 	static u_short * const scrptr = (short *)0xc00b8000;

We need to know the frame buffer address and not much else.

@ + 	int attr, ind;
@ + 
@ + 	attr = attrs[PCPU_GET(cpuid) % 2];
@ + 	do
@ + 		ind = bde_putc_scrindex;
@ + 	while (atomic_cmpset_rel_int(&bde_putc_scrindex, ind, ind + 1) == 0);
@ + 	scrptr[5 * 80 + (ind % (15 * 80))] = attr | (c & 0xff);

Partially formatted for 80x25.  80 is the width, and 5 and 15 are to
keep it far away from the top and bottom edges (to reduces problems
from scrolling for normal output).

@ + 	bde_putc_log[ind % sizeof(bde_putc_log)] = c;
@ + }
@ + 
@ + static void
@ + bde_puts(const char *s)
@ + {
@ + 	while (*s != '\0')
@ + 		bde_putc(*s++);
@ + }
@ + 
@ + static void
@ + bde_wait(void)
@ + {
@ + 	int timeout;
@ + 
@ + 	if (bde_kill_bde_wait)
@ + 		return;
@ + 	if (!bde_wait_verbose) {
@ + 		DELAY(bde_wait_delay);
@ + 		return;
@ + 	}
@ + 	bde_puts("hit any key to abort wait of 300 seconds...");

Callers should use this function to wait occasonally so that the special
output doesn't overwrite itself or get overwritten with normal output
by the screen refresh.

@ + 	timeout = 300 * 1000;
@ + 	do {
@ + 		if (cncheckc() != -1)
@ + 			break;
@ + 		DELAY(1000);
@ + 	} while (--timeout != 0);
@ + 	bde_puts("done");
@ + }
@ + 
@ + void bde_printf_emerg(const char *fmt, ...);
@ + void
@ + bde_printf_emerg(const char *fmt, ...)
@ + {
@ + 	va_list ap;
@ + 	char buf[256];
@ + 
@ + 	va_start(ap, fmt);
@ + 	vsnprintf(buf, sizeof(buf) - 3, fmt, ap);
@ + 	// strcat(buf, "!E!");
@ + 	bde_puts(buf);
@ + 	// bde_wait();
@ + }
@ + 
@   int
@   sc_probe_unit(int unit, int flags)

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140504202222.H1763>