mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
Rework the EARLY_PRINTF mechanism. Instead of defining a special eprintf()
routine, now a platform can provide a pointer to an early_putc() routine which is used instead of cn_putc(). Control can be handed off from early printf support to standard console support by NULLing out the pointer during standard console init. This leverages all the existing error reporting that uses printf calls, such as panic() which can now be usefully employed even in early platform init code (useful at least to those who maintain that code and build kernels with EARLY_PRINTF defined). Reviewed by: imp, eadler
This commit is contained in:
parent
2a261121af
commit
42c8459bed
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=261786
@ -228,6 +228,27 @@ static struct uart_ops at91_usart_ops = {
|
||||
.getc = at91_usart_getc,
|
||||
};
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
/*
|
||||
* Early printf support. This assumes that we have the SoC "system" devices
|
||||
* mapped into AT91_BASE. To use this before we adjust the boostrap tables,
|
||||
* you'll need to define SOCDEV_VA to be 0xdc000000 and SOCDEV_PA to be
|
||||
* 0xfc000000 in your config file where you define EARLY_PRINTF
|
||||
*/
|
||||
volatile uint32_t *at91_dbgu = (volatile uint32_t *)(AT91_BASE + AT91_DBGU0);
|
||||
|
||||
static void
|
||||
eputc(int c)
|
||||
{
|
||||
|
||||
while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY))
|
||||
continue;
|
||||
at91_dbgu[USART_THR / 4] = c;
|
||||
}
|
||||
|
||||
early_putc_t * early_putc = eputc;
|
||||
#endif
|
||||
|
||||
static int
|
||||
at91_usart_probe(struct uart_bas *bas)
|
||||
{
|
||||
@ -244,6 +265,22 @@ at91_usart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
|
||||
int parity)
|
||||
{
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
if (early_putc != NULL) {
|
||||
printf("Early printf yielding control to the real console.\n");
|
||||
early_putc = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine is called multiple times, sometimes right after writing
|
||||
* some output, and the last byte is still shifting out. If that's the
|
||||
* case delay briefly before resetting, but don't loop on TXRDY because
|
||||
* we don't want to hang here forever if the hardware is in a bad state.
|
||||
*/
|
||||
if (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY))
|
||||
DELAY(1000);
|
||||
|
||||
at91_usart_param(bas, baudrate, databits, stopbits, parity);
|
||||
|
||||
/* Reset the rx and tx buffers and turn on rx and tx */
|
||||
@ -276,28 +313,6 @@ at91_usart_putc(struct uart_bas *bas, int c)
|
||||
WR4(bas, USART_THR, c);
|
||||
}
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
/*
|
||||
* Early printf support. This assumes that we have the SoC "system" devices
|
||||
* mapped into AT91_BASE. To use this before we adjust the boostrap tables,
|
||||
* You'll need to define SOCDEV_VA to be 0xdc000000 and SOCDEV_PA to be
|
||||
* 0xfc000000 in your config file where you define EARLY_PRINTF
|
||||
*/
|
||||
volatile uint32_t *at91_dbgu = (volatile uint32_t *)(AT91_BASE + AT91_DBGU0);
|
||||
|
||||
void
|
||||
eputc(int c)
|
||||
{
|
||||
|
||||
if (c == '\n')
|
||||
eputc('\r');
|
||||
|
||||
while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY))
|
||||
continue;
|
||||
at91_dbgu[USART_THR / 4] = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for a character available.
|
||||
*/
|
||||
|
@ -464,6 +464,15 @@ cnputc(int c)
|
||||
struct consdev *cn;
|
||||
char *cp;
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
if (early_putc != NULL) {
|
||||
if (c == '\n')
|
||||
early_putc('\r');
|
||||
early_putc(c);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cn_mute || c == '\0')
|
||||
return;
|
||||
STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
|
||||
|
@ -1137,25 +1137,3 @@ hexdump(const void *ptr, int length, const char *hdr, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
/*
|
||||
* Support for calling an alternate printf early in boot (like before
|
||||
* cn_init() can be called). Platforms need to define eputc that want
|
||||
* to use this.
|
||||
*/
|
||||
static void
|
||||
early_putc_func(int ch, void *arg __unused)
|
||||
{
|
||||
eputc(ch);
|
||||
}
|
||||
|
||||
void
|
||||
eprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
kvprintf(fmt, early_putc_func, NULL, 10, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
@ -197,8 +197,8 @@ void init_param2(long physpages);
|
||||
void init_static_kenv(char *, size_t);
|
||||
void tablefull(const char *);
|
||||
#ifdef EARLY_PRINTF
|
||||
void eprintf(const char *, ...) __printflike(1, 2);
|
||||
void eputc(int ch);
|
||||
typedef void early_putc_t(int ch);
|
||||
extern early_putc_t *early_putc;
|
||||
#endif
|
||||
int kvprintf(char const *, void (*)(int, void*), void *, int,
|
||||
__va_list) __printflike(1, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user