Chinaunix首页 | 论坛 | 博客
  • 博客访问: 677773
  • 博文数量: 118
  • 博客积分: 7172
  • 博客等级: 少将
  • 技术积分: 1799
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-12 13:33
文章分类

全部博文(118)

文章存档

2012年(5)

2011年(12)

2010年(18)

2009年(36)

2008年(47)

我的朋友

分类: LINUX

2010-04-16 13:40:46

16.4 busy box的init 和各种脚本的分工
  看到上面的脚本...写的不咋样,甚至都不符合各种配置文件的具体分工,很不规整. 下面来研究一个比较规整的方案. 下面是google结果(看busybox init的代码?,人生苦短,以后把) 
1)在串口上启动 shell 
   为了避开在busybox "job control"的那个问题, 把/dev/console 直接改成 s3c2410_serial1的设备号,就是:
  mknod -m 666 console c 204 65  #204, 64,65,66
  然后直接用busybox _install目录下的linuxrc,到busybox的一个软连接,也是启动init.  

2)busybox init的流程
   简单说,就是执行inittab里指定的命令.具体流程如下:   
a)如果没有/etc/inittab,则默认执行/etc/init.d/rcS (见下面说明)   
b)执行inittab中动作类型为wait的命令   
c)执行inittab中动作类型是once的命令   
d)然后进入等待和循环执过程: 
     .如果一动作为respawn类型的进程退出了,就重新启动它. 
     .如果动作为askfirst类型的程序退出了,也要重新启动它,但是先询问用户.
   busybox的inittab的语法格式是: (examples/inittab)  
id:runlevels:action:process 
  id: busybox 用id域指定程序运行的控制台. 如果是串口控制台,id域
  runlevels:  busybox根本不使用它
  action: 字段定义了该进程应该运行在何种状态下:
      sysinit :boot time时执行 (第一此运行init的时候?) 
      respawn :init 监视其启动的进程,如果退出了,这种类型的进程需要重新启动
      askfirst:和respawn差不多,就是要按下回车键才运行
      wait    : 要等待其运行完成
      once    : 只运行一次
      ctrlaltdel : 这个组合键按下时启动.

  busybox init的默认动作:
 ::sysinit:/etc/init.d/rcS
 ::askfirst:/bin/sh
  如果/dev/console 不是串口终端则继续运行:
  tty2::askfirst:/bin/sh

3) inittab
#在pc机上这个inittab本来是定义运行级别来着,这里就简单这么写吧
::sysinit:/etc/init.d/rcS 
console::askfirst:-/bin/sh         #我们把console换成了第一串口

4)etc/init.d/rcS
#!/bin/sh
echo
echo "Open ARM AKAE- "
echo 
mount -t proc /proc /proc 
mount -t devpts devpts /dev/pts
echo "Start mdev..."
# read the busybox docs: mdev.txt, you need config your kernerl with hotplug surport
mount -t sysfs sysfs /sys
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

5)一个空的/etc/mdev.conf文件先对付着

6)/etc/fstab也没有做    

--------------------------------------------------------------------------------
17.内核启动信息分析

Uncompressing Linux...................................................... done           
, booting the kernel.                                              [archarmootcompressedmisc.c: decompress_kernel()]
Linux version 2.6.24.4 (root@localhost.localdomain) (gcc version 4.1.2) #7 
Tue Apr 15 07:50:25 CST 2008                                                                                      [init/main.c:start_kernel]
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177                   [start_kernel->setup_arch->setup_processor]
Machine: SMDK2410                                                                                           [setup_arch->setup_machine]
Converting old-style param struct to taglist                                  [setup_arch->convert_to_tag_list->..->build_tag_list]
ATAG_INITRD is deprecated; please update your bootloader.                       [setup_arch->parse_tags->parse_tag_initrd ]
Memory policy: ECC disabled, Data cache writeback                          [setup_arch->paging_init->build_mem_type_table]
On node 0 totalpages: 16384   [setup_arch->paging_init->bootmem_init_node->free_area_init_node-> calculate_node_totalpages]
   DMA zone: 128 pages used for memmap                        [setup_arch->..->free_area_init_node->free_area_init_core]
   DMA zone: 0 pages reserved
   DMA zone: 16256 pages, LIFO batch:3
   Normal zone: 0 pages used for memmap
   Movable zone: 0 pages used for memmap

CPU S3C2440A (id 0x32440001) [setup_arch->paging_init->devicemaps_init->mdesc->smdk2410_map_io->s3c24xx_init_io]
S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz [..smdk2410_map_io->cpu_ids->s3c244x_init_clocks]
S3C24XX Clocks, (c) 2004 Simtec Electronics                                       [...s3c244x_init_clocks->s3c24xx_setup_clocks]
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on                          [...s3c244x_init_clocks->s3c2410_baseclk_add]

CPU0: D VIVT write-back cache                                                                [setup_arch->cpu_init->dump_cpu_info] 
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256                         [start_kernel->build_all_zonelists]
Kernel command line: root=/dev/ram init=/linuxrc initrd=0x30a00000,0x00100000                  [start_kernel, print cmd line ]
console=ttySAC1,115200 mem=65536K devfs=mount 
irq: clearing pending ext status 000dff00          [start_kernel->init_IRQ->init_arch_irq(mdesc->init_irq)->s3c24xx_init_irq]
irq: clearing pending ext status 00001000          [init_arch_irq 在arm体系下是一个函数指针,setup_arch初始化其为mdesc->init_irq]
irq: clearing subpending status 0000009a
irq: clearing subpending status 00000092
PID hash table entries: 256 (order: 8, 1024 bytes)  [start_kernel->pidhash_init]
timer tcon=00090000, tcnt a2c1, tcfg 00000200,00000000, usec 00001eb8  [start_kernel->time_init->system_timer.init->
                                                                                                  s3c2410_timer_init->s3c2410_timer_setup]
        [setup_arch中初始化全局函数指针 system_timer = mdesc->timer ,既s3c24xx_timer, arch/arm/plat-s3c24xx/timer.c]
Console: colour dummy device 80x30                [start_kernel->console_init-> via lds __con_initcall_start ->vt:con_init]
selected clock c0239b70 (pclk) quot 26, calc 115740 [console_initcall(s3c24xx_serial_initconsole)->register_console->console.setup->
s3c24xx_serial_console.setup(s3c24xx_serial_console_setup)->uart_set_options->s3c24xx_serial_set_termios->s3c24xx_serial_getclk]console [ttySAC1] enabled                             [console_initcall(s3c24xx_serial_initconsole)->register_console]
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)                                          [start_kernel->vfs_caches_init_early]
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total                                                                                                             [start_kernel->mem_init]
Memory: 61440KB available (2060K code, 248K data, 108K init)
Calibrating delay loop... 199.47 BogoMIPS (lpj=498688)                                                            [start_kernel->calibrate_delay]
Mount-cache hash table entries: 512                                &n bsp;                                     [start_kernel-> vfs_caches_init->mnt_init]
CPU: Testing write buffer coherency: ok                                    [start_kernel->check_bugs->check_writebuffer_bugs]
net_namespace: 64 bytes                   [start_kernel->rest_init->kernel_init->do_basic_setup->pure_initcall(net_ns_init)]
NET: Registered protocol family 16                                                     [core_initcall(netlink_proto_init)->sock_register]
S3C2440: Initialising architecture                          [arch_initcall(s3c_arch_init)->(cpu->init())->cpu_ids->s3c2410_init]
S3C2440: IRQ Support             [arch_initcall(s3c2440_irq_init)->sysdev_driver_register->drv.add()->s3c2440_irq_add]
S3C2440: Clock Support, DVS off                          [arch_initcall(s3c24xx_clk_driver)->s3c2440_clk_driver.s3c2440_clk_add]
S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics       [arch_initcall(s3c2410_dma_drvinit)->sysdev_driver_register->
DMA channel 0 at c4800000, irq 33              c2410_dma_driver.s3c2410_dma_add->s3c2410_dma_init->s3c24xx_dma_init]
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
usbcore: registered new interface driver usbfs   [subsys_initcall(usb_init)->usb_register(&usbfs_driver)->usb_register_driver]
usbcore: registered new interface driver hub    [subsys_initcall(usb_init)->usb_hub_init(&hub_driver)->usb_register_driver]
usbcore: registered new device driver usb        [subsys_initcall(usb_init)->usb_register_device_driver(&usb_generic_driver)]
NET: Registered protocol family 2                                                                                        [fs_initcall(inet_init)->sock_register]
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)                                [fs_initcall(inet_init)->ip_init->ip_rt_init ]
TCP established hash table entries: 2048 (order: 2, 16384 bytes)    [fs_initcall(inet_init)->ip_init->tcp_init]
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)                [fs_initcall(inet_init)->ip_init->tcp_init]
TCP: Hash tables configured (established 2048 bind 2048)              [fs_initcall(inet_init)->ip_init->tcp_init]
TCP reno registered                              [fs_initcall(inet_init)->ip_init->tcp_init->tcp_register_congestion_control]
checking if image is initramfs...<5>it isn't (no cpio magic); looks like an initrd                  [rootfs_initcall(populate_rootfs)]
Freeing initrd memory: 1024K              [rootfs_initcall(populate_rootfs)->free_initrd->free_initrd_mem->free_area]
NetWinder Floating Point Emulator V0.97 (extended precision)  [module_init(fpe_init);]
JFFS2 version 2.2. (NAND) 漏 2001-2006 Red Hat, Inc.    [module_init(init_jffs2_fs);]
io scheduler noop registered                            [module_init(noop_init)->elv_register]
io scheduler anticipatory registered (default)                      [module_init(as_init)->elv_register]
io scheduler deadline registered                     [module_init(deadline_init)->elv_register]
io scheduler cfq registered                                              [module_init(cfq_init)->elv_register]
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled            [module_init(serial8250_init)]
s3c2440-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440 [module_init(s3c24xx_serial_modinit)->s3c2440_serial_init->
s3c2440-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440  s3c2440_serial_probe->uart_add_one_port->
s3c2440-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2440  uart_configure_port->uart_report_port]
RAMDISK driver initialized: 2 RAM disks of 4096K size 1024 blocksize                                               [module_init(rd_init);]
loop: module loaded                                                                                                               [module_init(loop_init);]
S3C24XX NAND Driver, (c) 2004 Simtec Electronics                                          [module_init(s3c2410_nand_init);]
s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns  [s3c2440_nand_probes->3c2410_nand_inithw]
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit) [ form above...->nand_scan_ident nand_get_flash_type]
Scanning device for bad blocks   [s3c24xx_nand_probe->nand_scan ->nand_scan_tail->chip->scan_bbt:..->create_bbt]
Creating 4 MTD partitions on "NAND 64MiB 3,3V 8-bit":                       [s3c2410_nand_add_partition->add_mtd_partitions]
0x00000000-0x00030000 : "Boot Agent"
0x00030000-0x00200000 : "kernel"
0x00200000-0x02000000 : "ramfs"
0x02000000-0x04000000 : "extfs"
ohci_hcd: 2006 August 04 USB 1.1 'Open' Host Controller (OHCI) Driver
ohci_hcd: block sizes: ed 64 td 64
s3c2410-ohci s3c2410-ohci: s3c2410_start_hc:
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
s3c2410-ohci s3c2410-ohci: created debug files
s3c2410-ohci s3c2410-ohci: OHCI controller state
s3c2410-ohci s3c2410-ohci: OHCI 1.0, NO legacy support registers
s3c2410-ohci s3c2410-ohci: control 0x083 HCFS=operational CBSR=3
s3c2410-ohci s3c2410-ohci: cmdstatus 0x00000 SOC=0
s3c2410-ohci s3c2410-ohci: intrstatus 0x00000004 SF
s3c2410-ohci s3c2410-ohci: intrenable 0x8000005a MIE RHSC UE RD WDH
s3c2410-ohci s3c2410-ohci: hcca frame #001e
s3c2410-ohci s3c2410-ohci: roothub.a 02001202 POTPGT=2 NOCP NPS NDP=2(2)
s3c2410-ohci s3c2410-ohci: roothub.b 00000000 PPCM=0000 DR=0000
s3c2410-ohci s3c2410-ohci: roothub.status 00008000 DRWE
s3c2410-ohci s3c2410-ohci: roothub.portstatus [0] 0x00000100 PPS
s3c2410-ohci s3c2410-ohci: roothub.portstatus [1] 0x00000100 PPSu
sb usb1: default language 0x0409
usb usb1: uevent
usb usb1: usb_probe_device
usb usb1: configuration #1 chosen from 1 choice
usb usb1: adding 1-0:1.0 (config #1, interface 0)
usb 1-0:1.0: uevent
hub 1-0:1.0: usb_probe_interface
hub 1-0:1.0: usb_probe_interface - got id
hub 1-0:1.0: USB hub found
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0xa006,0x2900,0x0000,c3c19a84,000f)
hub 1-0:1.0: 2 ports detected
hub 1-0:1.0: standalone hub
hub 1-0:1.0: no power switching (usb 1.0)
hub 1-0:1.0: no over-current protection
hub 1-0:1.0: power on to power good time: 4ms
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0xa000,0x0000,0x0000,c3c19a40,0004)
hub 1-0:1.0: local power source is good
hub 1-0:1.0: trying to enable port power on non-switchable hub
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0x2303,0x0008,0x0001,c3c19a40,0000)
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0x2303,0x0008,0x0002,c3c19a40,0000)
hub 1-0:1.0: state 7 ports 2 chg 0000 evt 0000
usb usb1: new device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: S3C24XX OHCI
usb usb1: Manufacturer: Linux 2.6.24.4 ohci_hcd
usb usb1: SerialNumber: s3c24xx
s3c2410_udc: debugfs dir creation failed -19
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0xa300,0x0000,0x0001,c3c6fe30,0004)
s3c2410-ohci s3c2410-ohci: s3c2410_hub_control(c3c2b400,0xa300,0x0000,0x0002,c3c6fe30,0004)
mice: PS/2 mouse device common for all mice                        [module_init(mousedev_init);]
S3C24XX RTC, (c) 2004,2006 Simtec Electronics                       [module_init(s3c_rtc_init);]
s3c2440-i2c s3c2440-i2c: slave address 0x10    [s3c2440_i2c_driver.s3c24xx_i2c_probe->s3c24xx_i2c_init]
s3c2440-i2c s3c2440-i2c: bus frequency set to 390 KHz   [同上]
s3c2440-i2c s3c2440-i2c: i2c-0: S3C I2C adapter                           [s3c2440_i2c_driver.s3c24xx_i2c_probe]
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics   [module_init(watchdog_init);]
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
TCP cubic registered          [module_init(cubictcp_register)->tcp_register_congestion_control]
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)   [late_initcall(rtc_hctosys)]
RAMDISK: Compressed image found at block 0  [kernel_init->prepare_namespace->initrd_load->rd_load_image->identify_ramdisk_image]
VFS: Mounted root (ext2 filesystem).      [kernel_init->prepare_namespace->mount_root->mount_block_root->do_mount_root]
Freeing init memory: 108K
selected clock c0239b70 (pclk) quot 26, calc 115740  /*以下内容为busybox产生*/
selected clock c0239b70 (pclk) quot 26, calc 115740
init started: BusyBox v1.10.1 (2008-04-19 15:27:01 CST)
selected clock c0239b70 (pclk) quot 26, calc 115740
starting pid 225, tty '': '/etc/init.d/rcS'
Open ARM AKAE- 
Start mdev...
mount: mounting sysfs on /sys failed: Device or resource busy
selected clock c0239b70 (pclk) quot 26, calc 115740
starting pid 236, tty '/dev/console': '-/bin/sh '
BusyBox v1.10.1 (2008-04-19 15:27:01 CST) built-in shell (msh)
Enter 'help' for a list of built-in commands.

--------------------------------------------------------------------------------

18 .Uart devices register and driver select

1.machine和cpu的检测与uart设备名的设置
 
CPU S3C2440A (id 0x32440001) [setup_arch->paging_init->devicemaps_init->mdesc->smdk2410_map_io->s3c24xx_init_io]
   mdesc是SMDK2410,smdk2410_map_io->s3c24xx_init_io根据cpuid设置arm/plat-s3c24xx的全局变量cpu.然后mdk2410_map_io
调用s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));通过(cpu->init_uarts)(cfg, no);注册cpu特的定的uart资源. cpu_ids在arch/arm/plat-s3c24xx/cpu.c中,其中2440a的uart初始化函数是:

void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
    s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
}
void __init s3c24xx_init_uartdevs(char *name,
                  struct s3c24xx_uart_resources *res,
                  struct s3c2410_uartcfg *cfg, int no)
{
    struct platform_device *platdev;
    struct s3c2410_uartcfg *cfgptr = uart_cfgs;
    struct s3c24xx_uart_resources *resp;
    int uart;

    memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);

    for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
        platdev = s3c24xx_uart_src[cfgptr->hwport];

        resp = res + cfgptr->hwport;

        s3c24xx_uart_devs[uart] = platdev;  /*uart的platform设备*/

        platdev->name = name;   /*platform 设备名称初始化为 "s3c2440-uart" */
        platdev->resource = resp->resources;
        platdev->num_resources = resp->nr_resources;

        platdev->dev.platform_data = cfgptr;
    }

    nr_uarts = no;
}
然后arch_initcall(s3c_arch_init);-> platform_add_devices(s3c24xx_uart_devs, nr_uarts);注册设备到
platform_bus_type.

2.console 设备初始化

selected clock c0239b70 (pclk) quot 26, calc 115740 [console_initcall(s3c24xx_serial_initconsole)->register_console->console.setup->s3c24xx_serial_console.setup(s3c24xx_serial_console_setup)->uart_set_options->s3c24xx_serial_set_termios->s3c24xx_serial_getclk]console [ttySAC1] enabled                             [console_initcall(s3c24xx_serial_initconsole)->register_console]
先是根据内核命令行选择并配置一个uart的驱动:static int s3c24xx_serial_initconsole(void){
    struct s3c24xx_uart_info *info;
    struct platform_device *dev = s3c24xx_uart_devs[0]; /*上面已经初始化了*/
    ......
    } else if (strcmp(dev->name, "s3c2440-uart") == 0) {
        info = s3c2440_uart_inf_at;  /*根据设备名称(通过cpu设这的,见上面第一节分析*/
    }
    ........
    s3c24xx_serial_console.data = &s3c24xx_uart_drv; /*选择uart驱动: ttySACx, 204,64-66*/
    s3c24xx_serial_init_ports(info);

    register_console(&s3c24xx_serial_console);
    return 0;
}
然后再根据命令行参数选择uart端口和波特率:
void register_console(struct console *console) /*s3c24xx_serial_console*/
{
    ......
    for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
            i++) {
        if (strcmp(console_cmdline[i].name, console->name) != 0)
            continue;
        if (console->index >= 0 &&
            console->index != console_cmdline[i].index)
            continue;
        if (console->index < 0)
            console->index = console_cmdline[i].index;
        if (console->setup &&
            console->setup(console, console_cmdline[i].options) != 0) /*options中存的是波特率*/
            break;
        console->flags |= CON_ENABLED;
        console->index = console_cmdline[i].index; /*我们的选择是ttySAC1*/
        if (i == selected_console) {
            console->flags |= CON_CONSDEV;
            preferred_console = selected_console;
        }
        break;
    }
.............
}

3.uart设备驱动初始化

Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled [ module_init(serial8250_init)]
s3c2440-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440 
s3c2440-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440 
s3c2440-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2440
 
上面三行信息就是uart初始化的信息,具体是在uart_report_port这个函数内打印的.但是通过什么路径确时费了番周折.串口初始化就是
module_init(s3c24xx_serial_modinit)
static int __init s3c24xx_serial_modinit(void)
{
    int ret;

    ret = uart_register_driver(&s3c24xx_uart_drv); /*选择uart驱动: ttySACx, 204,64-66,设备名称s3c2410_serial*/
    if (ret < 0) {
        printk(KERN_ERR "failed to register UART driver ");
        return -1;
    }
    s3c2400_serial_init();  /*这里有4个cpu的串口初始化函数,到底那个可以成功?*/
    s3c2410_serial_init();  /*这个在配置里选上了*/
    s3c2412_serial_init();
    s3c2440_serial_init();  /*这个也在配置里选上了*/
    return 0;
}
只从打印信息看,当然是选择了2440那个,下面从代码里找这个根据:
static inline int s3c2410_serial_init(void)
{
    return s3c24xx_serial_init(&s3c2410_serial_drv, &s3c2410_uart_inf);
}
static inline int s3c2440_serial_init(void)
{
    return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
}
static struct platform_driver s3c2410_serial_drv = {
    .probe        = s3c2410_serial_probe,
    .remove        = s3c24xx_serial_remove,
    .suspend    = s3c24xx_serial_suspend,
    .resume        = s3c24xx_serial_resume,
    .driver        = {
        .name    = "s3c2410-uart",
        .owner    = THIS_MODULE,
    },
};
static struct platform_driver s3c2440_serial_drv = {
    .probe        = s3c2440_serial_probe,
    .remove        = s3c24xx_serial_remove,
    .suspend    = s3c24xx_serial_suspend,
    .resume        = s3c24xx_serial_resume,
    .driver        = {
        .name    = "s3c2440-uart",
        .owner    = THIS_MODULE,
    },
};
上面两个初始化函数其实都是调用:
static int s3c24xx_serial_init->
int platform_driver_register(struct platform_driver *drv)
{
    drv->driver.bus = &platform_bus_type;
    if (drv->probe)
        drv->driver.probe = platform_drv_probe;
    ......
    return driver_register(&drv->driver);
}
driver_register->bus_add_driver->
int bus_add_driver(struct device_driver *drv)
{  
    ......
    if (drv->bus->drivers_autoprobe) { /*默认是autoprobe*/
        error = driver_attach(drv);
        if (error)
            goto out_unregister;
    }
  ......
}
driver_attach->bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);->
static int __driver_attach(struct device * dev, void * data)
{
    struct device_driver * drv = data;
    .......
    if (!dev->driver) /*这里就能找到在第一节中注册的uart dev*/
        driver_probe_device(drv, dev);
    }
    .....
}
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
    int ret = 0;
    if (drv->bus->match && !drv->bus->match(dev, drv))
        goto done;
    ret = really_probe(dev, drv); /* -> dev->bus->probe(dev)或者drv->probe(dev),这个bus没有probe*/
    ....
}
这里终于找到判定一个设备的驱动的条件:platform_bus_type ->platform_match->就是一个字符创的比较,看设备和驱动的名字是否一致:
strncmp(pdev->name, drv->name, BUS_ID_SIZE)
翻翻上面注册的名字,当然是2440的驱动胜出. 所以probe就调用了:
s3c2440_serial_probe->uart_add_one_port->uart_report_port.

4. uart设备注册后对console设备的影响(register_console只是早期注册给内核printk的)
第二节谈到console的注册:
static int s3c24xx_serial_initconsole(void)
{
    struct platform_device *dev = s3c24xx_uart_devs[0]; /*上面已经初始化了*/
    ......
    s3c24xx_serial_console.data = &s3c24xx_uart_drv; /*选择uart驱动: ttySACx, 204,64-66*/
    register_console(&s3c24xx_serial_console);
    return 0;
}
static struct console s3c24xx_serial_console =
{
    .name        = S3C24XX_SERIAL_NAME,
    .device        = uart_console_device, /*找到此console对应的tty*/
    .flags        = CON_PRINTBUFFER,
    .index        = -1,
    .write        = s3c24xx_serial_console_write,
    .setup        = s3c24xx_serial_console_setup
    .data =  &s3c24xx_uart_drv
};
static struct uart_driver s3c24xx_uart_drv = {
    .owner        = THIS_MODULE,
    .dev_name    = "s3c2410_serial",
    .nr        = 3,
    .cons        = S3C24XX_SERIAL_CONSOLE,
    .driver_name    = S3C24XX_SERIAL_NAME,
    .major        = S3C24XX_SERIAL_MAJOR,
    .minor        = S3C24XX_SERIAL_MINOR,
};
这个console只提供了最少的接口供printk使用.见register_console->release_console_sem.

然后,在第三节谈到的uart设备初始化中:
static int __init s3c24xx_serial_modinit(void)
{
    int ret;
    ret = uart_register_driver(&s3c24xx_uart_drv); /*初始化s3c24xx_uart_drv->tty_driver*/
     /*初始化tty_driver后uart_console_device就能找到对应tty设备了*/
   ...
}
static inline int s3c2440_serial_init->s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf)-> __driver_attach ->...->really_probe内,将注册的uart platform_device设备进行进一步初始化:dev->driver = drv;要注意s3c2440_serial_drv是platform_driver,而不是uart_driver:s3c24xx_uart_drv().

阅读(1354) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~