printk如何调用底层驱动?
printk->vprintk_func->vprintk_default(在未定义CONFIG_PRINTK_NMI)->vprintk_emit->console_unlock->call_console_drivers(通过遍历console_drivers(for_each_console))->(con->write)
asmlinkage __visible int printk(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = vprintk_func(fmt, args);
va_end(args);
return r;
}
static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
{
return vprintk_default(fmt, args);
}
int vprintk_default(const char *fmt, va_list args)
{
int r;
r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
return r;
}
asmlinkage int vprintk_emit(int facility, int level,
const char *dict, size_t dictlen,
const char *fmt, va_list args) {
console_unlock();
}
static void call_console_drivers(int level,
const char *ext_text, size_t ext_len,
const char *text, size_t len)
{
struct console *con;
trace_console_rcuidle(text, len);
if (!console_drivers)
return;
//for (con = console_drivers; con != NULL; con = con->next)
for_each_console(con) {
if (exclusive_console && con != exclusive_console)
continue;
if (!(con->flags & CON_ENABLED))
continue;
if (!con->write)
continue;
if (!cpu_online(smp_processor_id()) &&
!(con->flags & CON_ANYTIME))
continue;
if (con->flags & CON_EXTENDED)
con->write(con, ext_text, ext_len);
else
con->write(con, text, len);
}
}
查看控制台如何注册的,通过s3c244x.c来进行分析:
#define S3C24XX_SERIAL_NAME "ttySAC"
static struct console s3c24xx_serial_console = {
.name = S3C24XX_SERIAL_NAME,
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -1,
.write = s3c24xx_serial_console_write,
.setup = s3c24xx_serial_console_setup,
.data = &s3c24xx_uart_drv,
};
#define console_initcall(fn) \
static initcall_t __initcall_