2013-03-25 7 views
40

मैं पहले मंच ड्राइवर के बारे में एक विचार के साथ-साथ सामान्य डिवाइस ड्राइवर था की तरह:लिनक्स प्लेटफ़ॉर्म ड्राइवर और सामान्य डिवाइस ड्राइवर के बीच क्या अंतर है?

  • मंच चालक उन उपकरणों है कि चिप पर हैं के लिए है। और,
  • सामान्य डिवाइस ड्राइवर उन लोगों के लिए हैं जो प्रोसेसर चिप में इंटरफेस किए जाते हैं। एक i2c ड्राइवर में आने से पहले ।

    लेकिन यहां, मैं प्लेटफ़ॉर्म ड्राइवर के रूप में परिभाषित बहु फ़ंक्शन i2c ड्राइवर के माध्यम से पढ़ रहा हूं। मैं https://www.kernel.org/doc/Documentation/driver-model/platform.txt के माध्यम से चला गया था। लेकिन अभी भी ड्राइवरों को परिभाषित करने के बारे में एक निष्कर्ष निकालने के लिए स्पष्ट विचार नहीं मिल सका, जैसे ऑनचिप और इंटरफेस डिवाइस दोनों के लिए। मैं यह लिंक बहुत माध्यम से चला गया .. http://meld.org/discussion/general-discussion/platform-driver-vs-ordinary-device-drivers

कृपया किसी की व्याख्या।

+0

डिवाइस एक MFD- बहु समारोह उपकरण है। 'platform_device' में एक फ़ील्ड है; 'संरचना mfd सेल' जो' i2c_client' संरचना में नहीं है। शायद उस कारण से ड्राइवर प्लेटफॉर्म ड्राइवर के रूप में पंजीकृत है। कृपया इस पर टिप्पणी करें। !! – kzs

+0

http://www.atmel.com/Images/doc32098.pdf ..... इसे जांचें ... यह –

+0

मदद कर सकता है हाँ दस्तावेज़ अच्छा था .. मुझे लगता है कि मैं कुछ समय बाद उस दस्तावेज़ का उपयोग कर सकता था। लेकिन मैं अभी तक निष्कर्ष पर नहीं आ सकता था। मैंने एक मास्टर से पूछा है जो ड्राइवरों में अच्छा है .. जवाब मिलने के बाद मैं यहां पोस्ट करूंगा। – kzs

उत्तर

65

आपके संदर्भ अच्छे हैं लेकिन की परिभाषा की कमी है प्लेटफ़ॉर्म डिवाइस क्या है। LWN पर एक है। क्या हम इस पेज से सीख सकते हैं:

  1. मंच उपकरणों स्वाभाविक खोज योग्य है, यानी हार्डवेयर यह नहीं कह सकते हैं नहीं! "अरे मैं वर्तमान हूँ!" सॉफ़्टवेयर में

    पीसीआई या यूएसबी उपकरणों के विपरीत, I2C उपकरणों (रन टाइम पर) हार्डवेयर स्तर पर उनका वर्णन नहीं कर रहे हैं: विशिष्ट उदाहरण I2C उपकरणों, kernel/Documentation/i2c/instantiating-devices राज्य हैं। इसके बजाए, सॉफ़्टवेयर को प्रत्येक आई 2 सी बस सेगमेंट पर कौन से डिवाइस जुड़े हुए हैं (संकलन समय पर) पता होना चाहिए। तो यूएसबी और पीसीआई प्लेटफ़ॉर्म डिवाइस नहीं हैं।

  2. मंच उपकरणों, मिलान नाम द्वारा ड्राइवरों लिए बाध्य कर रहे

  3. मंच उपकरणों बहुत जल्दी प्रणाली बूट के दौरान दर्ज किया जाना चाहिए। क्योंकि वे अक्सर सिस्टम (प्लेटफ़ॉर्म) और उसके ड्राइवरों के लिए महत्वपूर्ण होते हैं।

तो बुनियादी तौर पर, सवाल "यह एक मंच डिवाइस या एक मानक उपकरण है?" अधिक एक सवाल जो बस की यह का उपयोग करता है।

  1. एक मंच चालक कि इस उपकरण का प्रबंधन करेगा रजिस्टर: एक विशेष मंच उपकरण के साथ काम करने के लिए, आप के लिए है। इसे अद्वितीय नाम,
  2. ड्राइवर प्लेटफ़ॉर्म के समान नाम को परिभाषित करने के लिए अपने प्लेटफ़ॉर्म डिवाइस को पंजीकृत करना चाहिए।

प्लेटफ़ॉर्म ड्राइवर उन डिवाइसों के लिए है जो चिप पर हैं।

सत्य नहीं (सिद्धांत में, लेकिन अभ्यास में सच)। i2c डिवाइस चालू नहीं हैं, लेकिन प्लेटफ़ॉर्म डिवाइस हैं क्योंकि वे खोजने योग्य नहीं हैं। इसके अलावा हम ऑनशिप डिवाइस पर विचार कर सकते हैं जो सामान्य डिवाइस हैं। उदाहरण: एक आधुनिक x86 प्रोसेसर पर एक एकीकृत पीसीआई जीपीयू चिप। यह खोजने योग्य है, इस प्रकार एक मंच डिवाइस नहीं है।

सामान्य डिवाइस ड्राइवर प्रोसेसर चिप में इंटरफेस किए गए लोगों के लिए हैं। एक आई 2 सी चालक में आने से पहले।

सत्य नहीं है। कई सामान्य डिवाइस प्रोसेसर में इंटरफेस किए जाते हैं, लेकिन i2c बस के माध्यम से नहीं। उदाहरण: एक यूएसबी माउस।

[संपादित करें] आपके मामले में, drivers/usb/host/ohci-pnx4008.c को एक नज़र है, जो एक USB होस्ट नियंत्रक मंच उपकरण है (यहाँ USB होस्ट नियंत्रक खोज योग्य नहीं है, यूएसबी उपकरणों, जो इसे से कनेक्ट करेगा जबकि, कर रहे हैं)। यह बोर्ड फ़ाइल (arch/arm/mach-pnx4008/core.c:pnx4008_init) द्वारा पंजीकृत एक प्लेटफ़ॉर्म डिवाइस है। और इसके जांच समारोह में, यह i2c_register_driver के साथ बस में आई 2 सी डिवाइस पंजीकृत करता है। हम अनुमान लगा सकते हैं कि यूएसबी होस्ट कंट्रोलर चिपसेट सीपीयू को i2c बस के माध्यम से बातचीत करता है।

वह वास्तुकला क्यों? क्योंकि एक तरफ, इस डिवाइस को एक नंगे आई 2 सी डिवाइस माना जा सकता है जो सिस्टम को कुछ कार्यक्षमता प्रदान करता है। दूसरी तरफ, यह एक यूएसबी होस्ट सक्षम डिवाइस है। इसे यूएसबी स्टैक (usb_create_hcd) में पंजीकरण करने की आवश्यकता है। तो केवल i2c की जांच अपर्याप्त होगी। Documentation/i2c/instantiating-devices पर एक नज़र डालें।

+0

बिल्कुल सही आप सही हैं। मैं इसके लिए +1 दूंगा: तो मूल रूप से, सवाल "क्या यह एक मंच डिवाइस या मानक उपकरण है?" यह एक सवाल है कि यह किस बस का उपयोग करता है। मैं सभी बिंदुओं से मिल सकता हूं और सहमत हूं। लेकिन मैं इसे समझ नहीं पाया या उससे संबंधित नहीं था: सामान्य डिवाइस ड्राइवर उन लोगों के लिए हैं जो प्रोसेसर चिप में इंटरफेस हैं। एक आई 2 सी चालक में आने से पहले। कृपया मुझे एक बेहतर आयाम में समझाएं ताकि यह मुझे समझ सके। – kzs

+0

मैं i2c_driver_register का उपयोग कर कुछ ड्राइवर देखता हूं और इस i2c मामले में मैं platform_driver_register देखता हूं। मेरे पास एक सवाल है कि दोनों के बीच क्या उपयोग करना है। – kzs

+1

@zair मेरे उत्तर के ** EDIT ** अनुभाग में, 'platform_driver_register' यूएसबी स्टैक के खिलाफ यूएसबी होस्ट ड्राइवर को पंजीकृत करता है, जबकि i2c_driver_register' का उपयोग i2c प्रोटोकॉल के माध्यम से CPU _talks_ को यूएसबी होस्ट नियंत्रक को अनुमति देने के लिए किया जाता है। यदि यूएसबी नियंत्रक एसपीआई-सक्षम था, तो इसके बजाय 'platform_driver_register' और 'spi_register_driver' होगा। –

1

मिनिमल मॉड्यूल कोड उदाहरण

शायद अंतर भी कुछ ठोस उदाहरण के साथ स्पष्ट हो जाएगा।

प्लेटफार्म डिवाइस उदाहरण

कोड:

आगे एकीकरण नोट पर: https://stackoverflow.com/a/44612957/895245

देखें कैसे:

  • रजिस्टर और बीच में पतों डिवाइस पेड़ में hardcoded कर रहे हैं और QEMU -M versatilepb मशीन वर्णन है, जो का प्रतिनिधित्व करता है से मेल खाते हैं SOC
  • डिवाइस हार्डवेयर को हटाने का कोई तरीका नहीं है (क्योंकि यह एसओसी का हिस्सा है)
  • सही ड्राइवर compatible डिवाइस पेड़ संपत्ति जो ड्राइवर
  • platform_driver_register में platform_driver.name से मेल खाता से चुना जाता है मुख्य रजिस्टर इंटरफ़ेस
#include <linux/init.h> 
#include <linux/interrupt.h> 
#include <linux/io.h> 
#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/of_address.h> 
#include <linux/of_device.h> 
#include <linux/of_irq.h> 
#include <linux/platform_device.h> 

MODULE_LICENSE("GPL"); 

static struct resource res; 
static unsigned int irq; 
static void __iomem *map; 

static irqreturn_t lkmc_irq_handler(int irq, void *dev) 
{ 
    /* TODO this 34 and not 18 as in the DTS, likely the interrupt controller moves it around. 
    * Understand precisely. 34 = 18 + 16. */ 
    pr_info("lkmc_irq_handler irq = %d dev = %llx\n", irq, *(unsigned long long *)dev); 
    /* ACK the IRQ. */ 
    iowrite32(0x9ABCDEF0, map + 4); 
    return IRQ_HANDLED; 
} 

static int lkmc_platform_device_probe(struct platform_device *pdev) 
{ 
    int asdf; 
    struct device *dev = &pdev->dev; 
    struct device_node *np = dev->of_node; 

    dev_info(dev, "probe\n"); 

    /* Play with our custom poperty. */ 
    if (of_property_read_u32(np, "lkmc-asdf", &asdf)) { 
     dev_err(dev, "of_property_read_u32\n"); 
     return -EINVAL; 
    } 
    if (asdf != 0x12345678) { 
     dev_err(dev, "asdf = %llx\n", (unsigned long long)asdf); 
     return -EINVAL; 
    } 

    /* IRQ. */ 
    irq = irq_of_parse_and_map(dev->of_node, 0); 
    if (request_irq(irq, lkmc_irq_handler, 0, "lkmc_platform_device", dev) < 0) { 
     dev_err(dev, "request_irq"); 
     return -EINVAL; 
    } 
    dev_info(dev, "irq = %u\n", irq); 

    /* MMIO. */ 
    if (of_address_to_resource(pdev->dev.of_node, 0, &res)) { 
     dev_err(dev, "of_address_to_resource"); 
     return -EINVAL; 
    } 
    if (!request_mem_region(res.start, resource_size(&res), "lkmc_platform_device")) { 
     dev_err(dev, "request_mem_region"); 
     return -EINVAL; 
    } 
    map = of_iomap(pdev->dev.of_node, 0); 
    if (!map) { 
     dev_err(dev, "of_iomap"); 
     return -EINVAL; 
    } 
    dev_info(dev, "res.start = %llx resource_size = %llx\n", 
      (unsigned long long)res.start, (unsigned long long)resource_size(&res)); 

    /* Test MMIO and IRQ. */ 
    iowrite32(0x12345678, map); 

    return 0; 
} 

static int lkmc_platform_device_remove(struct platform_device *pdev) 
{ 
    dev_info(&pdev->dev, "remove\n"); 
    free_irq(irq, &pdev->dev); 
    iounmap(map); 
    release_mem_region(res.start, resource_size(&res)); 
    return 0; 
} 

static const struct of_device_id of_lkmc_platform_device_match[] = { 
    { .compatible = "lkmc_platform_device", }, 
    {}, 
}; 

MODULE_DEVICE_TABLE(of, of_lkmc_platform_device_match); 

static struct platform_driver lkmc_plaform_driver = { 
    .probe  = lkmc_platform_device_probe, 
    .remove  = lkmc_platform_device_remove, 
    .driver  = { 
     .name = "lkmc_platform_device", 
     .of_match_table = of_lkmc_platform_device_match, 
     .owner = THIS_MODULE, 
    }, 
}; 

static int lkmc_platform_device_init(void) 
{ 
    pr_info("lkmc_platform_device_init\n"); 
    return platform_driver_register(&lkmc_plaform_driver); 
} 

static void lkmc_platform_device_exit(void) 
{ 
    pr_info("lkmc_platform_device_exit\n"); 
    platform_driver_unregister(&lkmc_plaform_driver); 
} 

module_init(lkmc_platform_device_init) 
module_exit(lkmc_platform_device_exit) 

पीसीआई गैर मंच डिवाइस उदाहरण

है

देखें कैसे:

  • रजिस्टर और व्यवधान से पतों गतिशील पीसीआई प्रणाली द्वारा आवंटित किए जाते हैं, कोई डिवाइस पेड़ प्रयोग किया जाता है
  • सही ड्राइवर पीसीआई vendor:device आईडी के आधार पर चयन किया जाता है (उदाहरण पर QEMU_VENDOR_ID, EDU_DEVICE_ID)। यह हर डिवाइस में बेक्ड है, और विक्रेताओं को विशिष्टता सुनिश्चित करना चाहिए।
  • हम device_add edu और device_del edu के साथ पीसीआई डिवाइस को सम्मिलित और हटा सकते हैं जैसा कि हम वास्तविक जीवन में कर सकते हैं। जांच स्वचालित नहीं है, लेकिन echo 1 > /sys/bus/pci/rescan के साथ बूट के बाद किया जा सकता है। यह भी देखें: Why is the probe method needed in Linux device drivers in addition to init?
#include <asm/uaccess.h> 
#include <linux/cdev.h> 
#include <linux/fs.h> 
#include <linux/init.h> 
#include <linux/interrupt.h> 
#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/pci.h> 

#define BAR 0 
#define CDEV_NAME "lkmc_hw_pci_min" 
#define EDU_DEVICE_ID 0x11e9 
#define QEMU_VENDOR_ID 0x1234 

MODULE_LICENSE("GPL"); 

static struct pci_device_id id_table[] = { 
    { PCI_DEVICE(QEMU_VENDOR_ID, EDU_DEVICE_ID), }, 
    { 0, } 
}; 
MODULE_DEVICE_TABLE(pci, id_table); 
static int major; 
static struct pci_dev *pdev; 
static void __iomem *mmio; 
static struct file_operations fops = { 
    .owner = THIS_MODULE, 
}; 

static irqreturn_t irq_handler(int irq, void *dev) 
{ 
    pr_info("irq_handler irq = %d dev = %d\n", irq, *(int *)dev); 
    iowrite32(0, mmio + 4); 
    return IRQ_HANDLED; 
} 

static int probe(struct pci_dev *dev, const struct pci_device_id *id) 
{ 
    pr_info("probe\n"); 
    major = register_chrdev(0, CDEV_NAME, &fops); 
    pdev = dev; 
    if (pci_enable_device(dev) < 0) { 
     dev_err(&(pdev->dev), "pci_enable_device\n"); 
     goto error; 
    } 
    if (pci_request_region(dev, BAR, "myregion0")) { 
     dev_err(&(pdev->dev), "pci_request_region\n"); 
     goto error; 
    } 
    mmio = pci_iomap(pdev, BAR, pci_resource_len(pdev, BAR)); 
    pr_info("dev->irq = %u\n", dev->irq); 
    if (request_irq(dev->irq, irq_handler, IRQF_SHARED, "pci_irq_handler0", &major) < 0) { 
     dev_err(&(dev->dev), "request_irq\n"); 
     goto error; 
    } 
    iowrite32(0x12345678, mmio); 
    return 0; 
error: 
    return 1; 
} 

static void remove(struct pci_dev *dev) 
{ 
    pr_info("remove\n"); 
    free_irq(dev->irq, &major); 
    pci_release_region(dev, BAR); 
    unregister_chrdev(major, CDEV_NAME); 
} 

static struct pci_driver pci_driver = { 
    .name  = CDEV_NAME, 
    .id_table = id_table, 
    .probe = probe, 
    .remove = remove, 
}; 

static int myinit(void) 
{ 
    if (pci_register_driver(&pci_driver) < 0) { 
     return 1; 
    } 
    return 0; 
} 

static void myexit(void) 
{ 
    pci_unregister_driver(&pci_driver); 
} 

module_init(myinit); 
module_exit(myexit); 
संबंधित मुद्दे