PB173 - Ovladače jádra - Linux VIII. Komunikace s HW Jiri Slabý Fakulta informatiky Masarykova univerzita 8. 11. 2016 Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 1/18 Komunikace s HW LDD3 kap. 9 a 12 O l/O Q PCI zařízení Q Zobecnění na jiné sběrnice Q EDU karta Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 2/18 Sekce 1 l/O Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 3/18 1/0 Na x86: 2 přístupy • Porty • Memory Mapped l/O Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 4/18 1/0 Porty Porty • Speciální adresový prostor • Závislé na architektuře • Speciální instrukce (in, out na x86) • Samostatná (malá) sběrnice • Na x86: řadič klávesnice, PC spkr, staré časovače a ovladače přerušení, ladicí port (0x80 => segmentový displej na desce), ... API • linux/io. h, linux/ioport.h • Požadavek:request_region, release_region • R/W: inX(port), outX(co, port), kde X G {b,w, 1} Demo: pb173/08 Úkol: Přečíst port 0x80, zapsat do něj 1B a znovu přečíst Jiri Slabý (Fakulta informatiky, MU) PB173/04 8.11.2016 5/18 1/0 MMI0 Memory Mapped l/O • Součástí fyzického adresového prostoru • Přístup standardním čtením/zápisem Nutnost přemapovat na virtuální adresy API • linux/io.h, linux/ioport.h Požadavek: request_mem_region, release_mem_region • /proc/iomem • Mapování: virt = ioremap(phys), iounmap(virt) • /proc/vmaiiocinf o (ne stará jádra) • R/W: readX(odkud), writeX(co, kam), kde X G {b,w,l,q} • POZOR: nelze číst jako z paměti (optimalizace, pořadí bytů, ...) Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 6/18 Sekce 2 PCI zařízení Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 7/18 PCI zařízení • PCI, PCI-X, PCIe • Hierarchická sběrnice • Identifikace doména:bus:slot.funkce • Bridge (=routery) • Konfigurační prostor • Automatická konfigurace • ID zařízení (vendor, device), l/O prostory, IRQ • Obsah l/O prostorů - specifikace zařízení (výrobce) • lspci 9 Podrobnosti v PCI specifikaci Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 8/18 PCI zařízení v jádře • linux/pci.h, Documentation/pci/* 9 struct pci_dev, struct pci_bus • pci_{set,get}_drvdata • Uloží/načte programátorova data do/z struct pci_dev • Referenční počet • PCI zařízení může být (fyzicky) odebráno ze systému • Ale struct pci_dev zůstává, pokud reference > 0 • Zvýšení: pci_dev_get • Snížení: pci_dev_put • Identifikace (ID) zařízení • pci_dev->vendor, pci_dev->device, ... • pci_any_id značí jakékoliv ID (při hledání) Jiri Slabý (Fakulta informatiky MU) PB173/04 8. 11. 2016 9/18 Hledání zařízení Iterátory (starší) • Dovoluje přístup k zařízení více ovladači • Nepodporuje hotplug • pci_get_device (vendor, device) Iterace přes zařízení struct pci_dev *pdev = NULL; while ((pdev = pci_get_device(VENDOR, DEVICE, pdev))) { pr_info("%.2x:%.2x.%.2x\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); Úkol: vypsat všechna zařízení v systému (jejich vendor+device ID) Jiri Slabý (Fakulta informatiky, MU) PB173/04 8. 11. 2016 10/18 Hledání zařízení Událostmi • Registrace háčků a seznamu chtěných zařízení • Seznam: struct pci_device_id (vendor, device, atd.) • Háčky: struct pci_driver (probe, remove, suspend, atd.) • pci_register_driver, pci_unregister_driver Události a PCI zařízení static struct pci_device_id my_table[] = { { PCI_DEVICE(VENDOR1, DEVICE1)}, { PCI_DEVICE(VENDOR1, DEVICE2)}, { PCI_DEVICE(0x8086, PCI_ANY_ID), .driver_data = 1 }, { 0, } }; MODULE_DEVICE_TABLE(pci, myjable); static struct pci_driver my_pci_driver = { .name = "my_driver", . id_table = my_table, .probe = myprobe, }; int my_probe(struct pci_dev *pdev, const struct pci_device_id *id) { pr_info("%2.x %lu\n", pdev->bus->number, id->driver_data); return 0; } Jiri Slabý (Fakulta informatiky, MU) PB 173/04 8. 11. 2016 11/18 Úkol Navázání PCI zařízení O linux/pci.h Q Definujte struct pci_device_id • lspci -nn a najděte EDU a jeho vendor+device ID O Definujte struct pci_driver • probe, remove, name, id_table O Definujte háčky (viz definici struct pci_driver) • int (*probe)(struct pci_dev *, const struct pci_device_id *) • void (*remove)(struct pci_dev *) O V probe a remove vypište • pdev->bus->number • PCI_SLOT(pdev->devfn) • PCI_FUNC(pdev->devfn) O Zavolejte pci_register_driver a pci_unregister_driver Q Vložte a odeberte modul a zkontrolujte dmesg Jiri Slabý (Fakulta informatiky, MU) PB173/04 8.11.2016 12/18 Práce s PCI Próbe • Inicializace PCI zařízení • pci_enable_device • Do té doby nelze některé vlastnosti struct pdev používat (irq) Rezervace a mapování l/O (jako v první části cvičení) • Požadavek: pci_request_region, pci_request_regions • Mapování: pci_ioremap_bar - alias pro ioremap(pci_resource_start (), pci_resource_len()) • Nastavení/detekce zařízení • Závisí na zařízení Remové • Opak Próbe • Tj. iounmap, pci_release_region(s), pci_disable_device Jiri Slabý (Fakulta informatiky MU) PB173/04 8. 11. 2016 13/18 Sekce 3 Zobecnění na jiné sběrnice Jiri Slabý (Fakulta informatiky MU) PB173/04 8. 11. 2016 14/18 Zobecnění Většina ostatních sběrnic funguje stejně • Např. USB, l2C, HID, IEEE1394, ACPI, INPUT, EISA, . • Nějaké probe/remove • Seznam ID • Registrace „ovladače" Jiri Slabý (Fakulta informatiky MU) PB173/04 8.11.2016 15/18 Sekce 4 EDU karta Jiri Slabý (Fakulta informatiky MU) PB 173/04 8. 11. 2016 16/18 Specifikace baru O karty EDU Specifikace baru O karty EDU Offset Len R/W Meaning 0x0000 4B R ID & Revision 0x0004 4B R/W Inverted value 0x0008 4B R/W Factorial 0x0020 4B R/W Status o ID & Revision: OxRRrrOOedu, RR - major, rr - minor o Inverted value: zapsané číslo se obrátí (C operátor ~) • Faktoriál: vypočte se faktoriál (je nutné počkat na status bit 0) • Status: • Bit 0 - probíhá výpočet faktoriálu • Bit 7 - má faktoriál generovat přerušení? Jiri Slabý (Fakulta informatiky MU) PB173/04 8. 11. 2016 17/18 Úkol Vyčtení identifikace karty EDU a práce s ní O Povolte zařízení (pci_enable_device) Q Rezervujte bar 0 (pci_request_region) Q Vypište fyzickou adresu baru 0 a porovnejte s výstupem íspci O Přemapujte bar 0 (ioremap) 9 Přečtěte a rozkódujte identifikaci a revizi (readX) • Vypište zvlášť major a minor revizi O Ověřte živost karty pomocí invertovacího registru O Ukliďte v remove (unmap, release, disable) Jiri Slabý (Fakulta informatiky MU) PB173/04 8. 11. 2016 18/18