static int __init serial8250_init(void)
{
int ret;
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
printk(KERN_INFO "Serial: 8250/16550 driver, "
"%d ports, IRQ sharing %sabled\n", nr_uarts,
share_irqs ? "en" : "dis");
#ifdef CONFIG_SPARC
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
#else
serial8250_reg.nr = UART_NR;
ret = uart_register_driver(&serial8250_reg);
#endif
if (ret)
goto out;
serial8250_isa_devs = platform_device_alloc("serial8250",PLAT8250_DEV_LEGACY);
if (!serial8250_isa_devs) {
ret = -ENOMEM;
goto unreg_uart_drv;
}
ret = platform_device_add(serial8250_isa_devs);
if (ret)
goto put_dev;
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
ret = platform_driver_register(&serial8250_isa_driver);
if (ret == 0)
goto out;
platform_device_del(serial8250_isa_devs);
put_dev:
platform_device_put(serial8250_isa_devs);
unreg_uart_drv:
#ifdef CONFIG_SPARC
sunserial_unregister_minors(&serial8250_reg, UART_NR);
#else
uart_unregister_driver(&serial8250_reg);
#endif
out:
return ret;
}
uart_register_driver(struct uart_driver *drv)向uart核心层注册一个uart驱动。在uart驱动中,用uart_state来表示一个uart设备。所以首先为drv->state分配内存空间,驱动支持drv->nr个设备,就分配对应个数的内存空间。接着调用alloc_tty_dirver()申请一个tty_driver,该函数会先分配tty_driver的内存空间,然后做简单的初始化。tty_driver大部分的初始化工作在该函数之后完成,利用uart_driver的信息初始化tty_driver,比如驱动和设备的名字,以及主次设备号的值,最重要的是会绑定uart_driver和tty_driver之间的链接关系。在ldd3的tty驱动中有提到tty_driver中的重要成员tty_operations,所以调用tty_set_operations()把uart_ops赋值给tty_driver的tty_operations变量。在uart驱动层这边,用uart_state和uart_port来表示具体的设备,所以最后是对uart_state进行初始化,而且主要是对里面的tty_port进行初始化操作。uart驱动注册的最后就是调用tty_register_dirver()注册tty驱动,从注册过程可以看出uart驱动是作为tty的驱动的成员被注册到tty核心层,用户空间通过系统调用是先跟tty核心沟通,往下层就是tty驱动,最后是通过tty_driver的成员driver_state找到最终的uart驱动。
/*
* Maybe we should be using a slab cache for this, especially if
* we have a large number of