이제는 실제 보드에서 사용하고 있는  AX88796 이더넷칩의 디바이스 드라이버에 대하여 살펴 보도록 하겠습니다.


 

디바이스 드라이버에서 platform_driver_register가 호출 됩니다.

platform driver 가 등록될때 name 이 동일해야 probe 함수가 호출 됩니다.

 

호출 되는 probe 함수에 대하여 알아 보도록  하겠습니다.

 

 probe 함수는 실제 이더넷 디바이스의 물리적인 연결이 정상적으로 되어 있는지를 확인을 하는 곳입니다.


 

실제 AX88796 이더넷 드라이버의 probe 소스 내용은 다음과 같습니다. 


/* ax_probe * * 플랫폼 디바이스 시스템에 붙어서, 새로운 장치에 대하여 알려고 할 때 사용하는 진입점 입니다. * 메모리를 할당 과 자원과 정보를 찾을 수 있으며, 필요한 레지스터를 매핑합니다. */ static int ax_probe(struct platform_device *pdev) { struct net_device *dev; struct ax_device *ax; struct resource *res; size_t size; int ret = 0; dev = ax__alloc_ei_netdev(sizeof(struct ax_device)); if (dev == NULL) return -ENOMEM; /* 디바이스 설정 시작 */ ax = to_ax_dev(dev); memset(ax, 0, sizeof(struct ax_device)); spin_lock_init(&ax->mii_lock); ax->dev = pdev; ax->plat = pdev->dev.platform_data; platform_set_drvdata(pdev, dev); ei_status.rxcr_base = ax->plat->rcr_val; /* 플랫폼 자원을 찿는다. */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "no IRQ specified\n"); goto exit_mem; } dev->irq = res->start; ax->irqflags = res->flags & IRQF_TRIGGER_MASK; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "no MEM specified\n"); ret = -ENXIO; goto exit_mem; } size = (res->end - res->start) + 1; /* 플랫폼 데이터 에서 제공된 것중 하나에서 리소스의 크기를 사용하여 레지스터 오프셋을 설정 */ if (ax->plat->reg_offsets) ei_status.reg_offset = ax->plat->reg_offsets; else { ei_status.reg_offset = ax->reg_offsets; for (ret = 0; ret < 0x18; ret++) ax->reg_offsets[ret] = (size / 0x18) * ret; } ax->mem = request_mem_region(res->start, size, pdev->name); if (ax->mem == NULL) { dev_err(&pdev->dev, "cannot reserve registers\n"); ret = -ENXIO; goto exit_mem; } ei_status.mem = ioremap(res->start, size); dev->base_addr = (unsigned long)ei_status.mem; if (ei_status.mem == NULL) { dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n", (unsigned long long)res->start, (unsigned long long)res->end); ret = -ENXIO; goto exit_req; } /* 리셋 영역을 찾는다. */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res == NULL) { if (!ax->plat->reg_offsets) { for (ret = 0; ret < 0x20; ret++) ax->reg_offsets[ret] = (size / 0x20) * ret; } ax->map2 = NULL; } else { size = (res->end - res->start) + 1; ax->mem2 = request_mem_region(res->start, size, pdev->name); if (ax->mem2 == NULL) { dev_err(&pdev->dev, "cannot reserve registers\n"); ret = -ENXIO; goto exit_mem1; } ax->map2 = ioremap(res->start, size); if (ax->map2 == NULL) { dev_err(&pdev->dev, "cannot map reset register\n"); ret = -ENXIO; goto exit_mem2; } ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem; } /* 확보한 자원으로, 디바이스의 레지스터를 초기화한다. */ ret = ax_init_dev(dev, 1); if (!ret) return 0; if (ax->map2 == NULL) goto exit_mem1; iounmap(ax->map2); exit_mem2: release_resource(ax->mem2); kfree(ax->mem2); exit_mem1: iounmap(ei_status.mem); exit_req: release_resource(ax->mem); kfree(ax->mem); exit_mem: free_netdev(dev); return ret; }

 


이상과 같이 실제 이더넷 디바이스 드라이버의 probe  함수에 대하여 살펴 보았습니다.