الاتصال بين السائق والجهاز بطريقة _HID ACPI باستخدام GPIO لوحدة تحكم Lynxpoint كمثال

بيان المشكلة


يحتوي Linux على واجهة قياسية للعمل مع GPIO من خلال sysfs. يمكن العثور على وثائق ذلك هنا .

باختصار ، هناك ملفات "تصدير" و "unexport" في مجلد "/ sys / class / gpio". من خلال كتابة الرقم X في ملف التصدير ، يمكنك فتح الواجهة في مساحة المستخدم للتحكم في GPIOX

#    user space   GPIO12 $ echo 12 > /sys/class/gpio/export 

بعد فتح الواجهة ، سيظهر المجلد / sys / class / gpio / gpioX / الذي سيكون فيه ملفات مثل "القيمة" أو "الاتجاه" ، وكتابة "في" أو "الخروج" إلى ملف "الاتجاه" وكتابة 1 أو 0 إلى الملف يمكن لـ "القيمة" التحكم في إخراج GPIO مباشرة من سطر الأوامر.

 #  GPIO   $ echo "out" > /sys/class/gpio/gpio12/direction #  1   GPIO $ echo 1 > /sys/class/gpio/gpio12/value 

من أجل أمر "echo X> / sys / class / gpio / export" لإنشاء مجلد "gpioX" ، يجب تسجيل برنامج تشغيل وحدة تحكم GPIO في kernel ، الذي يفتح الواجهة لخطوط GPIO.

حدث ذلك أنني أعمل على نقل coreboot للوحة مخصصة تعتمد على معالج Intel Haswell i7 [بالنسبة لأولئك الذين لا يعرفون ، يعد coreboot مفتوح المصدر لمشروع BIOS مفتوح المصدر ( https://www.coreboot.org/ ) ]. تم بناء الجسر الجنوبي LynxpointLP الذي يوجد فيه 94 خط GPIO في المعالج الخاص بي. وأردت فتحها في sysfs ...

حل المشكلات (اتصال برنامج التشغيل والجهاز في Linux)


بعد بحث قصير على كود النواة ، وجدت أن برنامج التشغيل هذا قد تمت كتابته بالفعل ، موجود في ملف "drivers \ gpio \ gpio-lynxpoint.c" وتم تمكينه باستخدام Kconfig

 config GPIO_LYNXPOINT tristate "Intel Lynxpoint GPIO support" depends on ACPI && X86 select GPIOLIB_IRQCHIP help driver for GPIO functionality on Intel Lynxpoint PCH chipset Requires ACPI device enumeration code to set up a platform device. 

تم تمكين خيار GPIO_LYNXPOINT في النواة التي كنت أعمل معها ، ومع ذلك ، لم يكن هناك مجلد "gpiochipN" لوحدة تحكم GPIO في المجلد "/ sys / class / gpio /" (الذي يجب أن يكون كذلك) ، وحتى هذا النص لم يصدر أي خطوط.

 $ for i in {0..255}; do echo $i > /sys/class/gpio/export; done 

بالنظر إلى رمز coreboot أو النظر في الوثائق الخاصة بهذا الجسر الجنوبي ، يمكنك أن ترى أن وحدة تحكم GPIO ليست جهاز PCI منفصلًا. وهو جزء من جهاز PCI آخر: جسر واجهة LPC. باستخدام مسجلات مساحة التكوين PCI لهذا الجهاز ، يجب تمكين وحدة تحكم GPIO وتعيينها BASE_ADDRESS في مساحة الإدخال / الإخراج. سيؤدي هذا إلى فتح نافذة في مساحة 1KV I / O. من خلال كتابة / قراءة وحدات البايت في هذه النافذة ، يمكنك التحكم في خطوط GPIO.

ما يمكن أن نراه في رمز الأساسية:

الجسر الجنوبي \ Intel \ lynxpoint \ pch.h:

 #define DEFAULT_GPIOBASE 0x1400 #define DEFAULT_GPIOSIZE 0x400 ... #define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ #define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ ... /* PCI Configuration Space (D31:F0): LPC */ #define PCH_LPC_DEV PCI_DEV(0, 0x1f, 0) 

الجسر الجنوبي \ Intel \ lynxpoint \ early_pch.c:

 /* Setup GPIO Base Address */ pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE|1); /* Enable GPIO functionality. */ pci_write_config8(PCH_LPC_DEV, GPIO_CNTL, 0x10); 

إذا نظرنا إلى تسجيلات جهاز LPC في Linux من خلال "lspci -xxx" ، فسوف نرى أن البيانات التي سجلناها موجودة في هذه السجلات. لذلك يبدو أن كل شيء تم تكوينه كما ينبغي.

بمتابعة النظر إلى رمز برنامج التشغيل ، لاحظت أن برنامج تشغيل Linux يتصل بالجهاز من خلال حقل acci_match_table. نظرًا لأنه لا يمكن تعداد جهازنا (لا يوجد في PCI أو ناقل USB) ، فإنه يحتاج إلى برنامج تشغيل النظام الأساسي ، ويتم توصيل برنامج التشغيل هذا بالجهاز عبر جداول ACPI. الحالة المعتادة لـ x86 ، في حالة ARM ، سوف نسجل الجهاز في DeviceTree ، أو نستخدم الرموز الصلبة القديمة في النواة.

برامج التشغيل \ gpio \ gpio-lynxpoint.c:

 static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { { "INT33C7", 0 }, { "INT3437", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); static struct platform_driver lp_gpio_driver = { .probe = lp_gpio_probe, .remove = lp_gpio_remove, .driver = { .name = "lp_gpio", .pm = &lp_gpio_pm_ops, .acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match), }, }; 

يعمل مثل هذا: إذا كانت النواة ، عند تحليل جدول ACPI ، ترى جهازًا به معرف _HID "INT33C7" ، فستحاول العثور على برنامج تشغيل النظام الأساسي له بمعرفات مطابقة في حقول البنية ".driver-> acpi_match_table".

عند العثور على تطابق ، سينفذ Linux وظيفة برنامج التشغيل .probe.

كما اتضح ، تم تقديم رمز ACPI لهذا الجهاز في coreboot ، لقد علقت عليه للتو. تم التعليق بسبب حقيقة أن Windows لهذا الجهاز لم يتمكن من العثور على برنامج التشغيل وعرض "جهاز غير معروف" في إدارة الجهاز. المزيد عن هذا أدناه.

لذلك نحن مهتمون بالمعلومات من الملف
src \ southbridge \ intel \ lynxpoint \ acpi \ serialio.asl (الرمز مبسط قليلاً):

 /*     * src\southbridge\intel\lynxpoint\pch.h * #define DEFAULT_GPIOBASE 0x1400 * #define DEFAULT_GPIOSIZE 0x400 */ Scope (\_SB) { Device (PCI0) { ... Device (GPIO) { // GPIO Controller Name (_HID, "INT33C7") Name (_CID, "INT33C7") Name (_UID, 1) Name (RBUF, ResourceTemplate() { DWordIo (ResourceProducer, MinFixed, // IsMinFixed MaxFixed, // IsMaxFixed PosDecode, // Decode EntireRange, // ISARanges 0x00000000, // AddressGranularity 0x00000000, // AddressMinimum 0x00000000, // AddressMaximum 0x00000000, // AddressTranslation 0x00000001, // RangeLength , // ResourceSourceIndex , // ResourceSource BAR0) Interrupt (ResourceConsumer, Level, ActiveHigh, Shared, , , ) {14} }) Method (_CRS, 0, NotSerialized) { CreateDwordField (^RBUF, ^BAR0._MIN, BMIN) CreateDwordField (^RBUF, ^BAR0._MAX, BMAX) CreateDwordField (^RBUF, ^BAR0._LEN, BLEN) Store (DEFAULT_GPIOSIZE, BLEN) Store (DEFAULT_GPIOBASE, BMIN) Store (Subtract (Add (DEFAULT_GPIOBASE, DEFAULT_GPIOSIZE), 1), BMAX) Return (RBUF) } Method (_STA, 0, NotSerialized) { Return (0xF) } } ... } } 

لفهم هذا الرمز بالتفصيل ، يجب أن تتعرف على بناء جملة ASL في مواصفات ACPI .

ولكن باختصار ، ينشئ هذا الرمز جهازًا مع المعرف "INT33C7" الذي يحتوي على 2 موارد:

 I/O memory: 1400-17ff; IRQ: 14; 

داخل وظيفة .probe Linux ، يتلقى برنامج التشغيل موارد الجهاز المذكورة أعلاه على النحو التالي:

 io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0); irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 

استنادًا إلى هذه البيانات ، سيقوم رمز برنامج التشغيل بملء بنية gpio_chip وتسجيل وحدة تحكم gpio في النظام ، مما يجعلها قابلة للوصول من خلال واجهة sysfs.

بعد إرجاع رمز ASL للجهاز وإعادة تجميع صورة BIOS ، تمكن النظام من الوصول إلى GPIO من خلال sysfs.

للبدء ، ظهر المجلد "gpiochip162" في / sys / class / gpio. يحتوي هذا المجلد على ملف "base" و "ngpio". الملف الأساسي مسؤول عن رقم GPIO الأول لوحدة التحكم هذه ، ngpio عن عددها.

 $ cat /sys/class/gpio/gpiochip162/base 162 $ cat /sys/class/gpio/gpiochip162/ngpio 94 

وبالتالي ، تم تصدير كل شيء كما ينبغي. نقوم بتنفيذ البرنامج النصي:

 $ for i in {162..255}; do echo $i > /sys/class/gpio/export; done 

بعد ذلك ، ستظهر مجلدات gpioN الفرعية في المجلد / sys / class / gpio / ، حيث توجد ملفات للتحكم في حالة الخط.

زوجان من التعليقات:

  • المجلد / sys / class / gpio162 / مسؤول عن إدارة GPIO0 ، المجلد / sys / class / gpio163 / مسؤول عن GPIO1 حدث هذا التحول بسبب حقيقة أن السائق أثناء تهيئة هيكل التحكم "هيكل gpio_chip" تعيين "gc-> base = -1؛". أي ، تركت النواة لأختار الأرقام بنفسي. هذا ليس حرجًا بشكل عام ، ولكن من الجدير أن نتذكره.
  • يتم منح الوصول فقط لخطوط GPIO التي تم تكوينها على أنها GPIO ، وليس كميزات Southbridge الأصلية. لمثل هذه الخطوط ، يعرض برنامج التشغيل المعلومات في dmesg: "gpio٪ d محجوز لـ ACPI". في حالة Coreboot ، يتم تكوين GPIO في ملف "gpio.h" في المجلد مع اللوحة الأم.
  • يمكن أيضًا تعيين الجهاز وبرنامج التشغيل باستخدام طريقة _CID (المعرّف المتوافق) ، ويتم تقديم وثائق موضوعنا في النواة في المستند "تعداد الجهاز المستند إلى ACPI"

تجدر الإشارة إلى أن جهاز INT33C7 لا يحتوي على 2 من اللوحات الأم الخاصة على نفس مجموعة الشرائح في جداول ACPI (من IBASE و DFI). صحيح ، هناك على الأرجح خطوط GPIO لا يتم إخراجها (لم أنظر إلى الوثائق في تلك اللحظة بالتفصيل).

المعرف "INT33C7"


بعد رفع وظيفة sysfs ، كان لدي سؤال ، من أين جاء رقم تعريف "INT33C7"؟

بعد النظر في وثائق طريقة _HID ، أصبح من الواضح أنه يجدر النظر في http://www.uefi.org/PNP_ACPI_Registry

_HID (معرف الجهاز)
_HID (معرف الجهاز)
يستخدم هذا الكائن لتزويد OSPM بمعرف PNP للجهاز أو معرف ACPI *
عند وصف النظام الأساسي ، يكون استخدام أي كائنات _HID اختياريًا. ومع ذلك ، يجب أن يكون كائن _HID
يستخدم لوصف أي جهاز سيتم تعداده بواسطة OSPM. يقوم OSPM فقط بتعداد جهاز
عندما يتعذر على عداد الحافلات اكتشاف معرف الجهاز. على سبيل المثال ، الأجهزة الموجودة على ناقل ISA هي
تم تعدادها بواسطة OSPM. استخدم كائن _ADR لوصف الأجهزة التي تم تعدادها بواسطة عد الناقل
بخلاف OSPM.

الحجج:
لا يوجد

قيمة الإرجاع:
عدد صحيح أو سلسلة تحتوي على HID
يتم تقييم كائن _HID إما إلى معرف نوع EISA مضغوط رقمي 32 بت أو سلسلة. إذا
السلسلة ، يجب أن يكون التنسيق عبارة عن معرف PNP أبجدي رقمي أو ACPI بدون علامة نجمية أو بادئة أخرى
الشخصيات.

يجب أن يكون معرف PNP صالحًا بالصيغة "AAA ####" حيث يكون الحرف من أحرف كبيرة و # عبارة عن سداسي
رقم. يجب أن يكون معرف ACPI صالحًا بالصيغة "NNNN ####" حيث N هو حرف كبير أو
الرقم ("0" - "9") و # عبارة عن رقم سداسي. تحتفظ هذه المواصفات بالسلسلة "ACPI" للاستخدام فقط
مع قائمة الأجهزة المحددة. تحتفظ أيضًا بجميع السلاسل التي تمثل 4 أرقام HEX لـ
الاستخدام الحصري مع معرفات البائعين المخصصة لـ PCI.

* -PNP ID و ACPI ID Registry موجودان على http://www.uefi.org/PNP_ACPI_Registry

هناك 3 نقاط على هذا الرابط:

  • يشار إلى جميع أنواع معرفات الأحرف الثلاثة (PNP ID) هنا
  • يشار إلى معرفات PNP التي تبدأ بـ "PNP" المحجوزة من قبل Microsoft هنا.
  • يشار إلى جميع أنواع معرفات 4 أحرف (ACPI ID) هنا

ليس من الواضح لماذا ، ولكن من قائمة معرفات PNP ، يمكنك العثور على معرفات "INT" محجوزة على INTERPHASE CORPORATION:

 INTERPHASE CORPORATION INT 11/29/1996 

على ما يبدو ، لم يتم نشر قائمة واحدة من معرفات الجهاز الكاملة (جزء الرسالة + رقمي). ولكن بمساعدة Google ، كان من الممكن العثور على قوائم الأجهزة و _HID الخاصة بها على سبيل المثال هنا أو هنا .

تشير إلى:

 INT33C7=Intel Serial I/O GPIO Host Controller 

وإذا حكمنا من خلال بقية الأسطر من هذه القائمة ، فإن جميع أجهزة INTxxxx هي أجهزة Intel (الآن يبدو واضحًا جدًا ، ولكن الاتصال مع INTERPHASE CORPORATION لا يزال غير واضح ؛ كما أنه ليس من الواضح جدًا سبب بدء الترقيم بهذه الأرقام الكبيرة ، ولكنه مرئي على تقدير Intel).

برنامج تشغيل الاتصال والجهاز في Windows


بعد أن أرضيت فضولي ، قررت تنزيل Windows على لوحتي. كما هو متوقع ، تعذر على النظام العثور على برنامج تشغيل للجهاز. لم يكن هناك أي مساعدة من السائقين للوحات IBASE و DFI ، وهو أمر مفهوم ، لأنه في BIOS لهذه اللوحات لم تتم الإشارة إلى هذا الجهاز.

تمكنت من العثور على برنامج تشغيل على موقع Microsoft على الويب

ومع ذلك ، يتم تقديم برنامج التشغيل هذا لنظام التشغيل Windows 8.1 والإصدارات الأحدث فقط. ما زلت أعمل مع Windows 7.

ومع ذلك ، حاولت تنزيل أحد برامج التشغيل وتحديد مجلده عند البحث عن برنامج تشغيل لجهازي غير المعروف.

ومع ذلك ، تعذر على المرسل تعيين برنامج التشغيل للجهاز. على الرغم من أن ملف inf يحتوي بوضوح على معلومات حول جهاز INT33C7.

 [Manufacturer] %INTEL%=Intel,NTamd64.6.3 [Intel.NTamd64.6.3] %iaLPSS_GPIO.DeviceDesc_LPT%=iaLPSS_GPIO_Device, ACPI\INT33C7 %iaLPSS_GPIO.DeviceDesc_WPT%=iaLPSS_GPIO_Device, ACPI\INT3437 

في عملية تحليل ملف INF ، اتضح أن قسم [الشركة المصنعة] أشار بوضوح إلى أنه غير مخصص لنظامي:

ما يعنيه Intel.NTamd64.6.3 يمكن فهمه من الوصف :

 nt[Architecture][.[OSMajorVersion][.[OSMinorVersion] OSMajorVersion=6 => Windows 7/Windows 8.1/Windows Server 2012 R2/... OSMinorVersion=3 => Windows 8.1/Windows Server 2012 R2 

محاولة دفع برنامج تشغيل Windows 7 عن طريق استبدال Intel.NTamd64.6.3 بـ Intel.NTamd64.6.1 ، لوضعه بشكل معتدل ، فشل ، حيث أعطاني شاشة زرقاء للموت ونظام تشغيل غير قابل للتمهيد ، وبالتالي كان عليّ إجراء استرداد.

تم العثور على برنامج تشغيل Win7 فقط على موقع ويب غير مفهوم على الإنترنت ، وبعد ذلك يتم عرض الجهاز في إدارة الجهاز بعلامة تعجب.

أدركت ضعفه ، وقررت اختبار الوظيفة على Windows 10. كانت هناك مفاجأة سارة. قام برنامج Intel Chipset Device Software (INF Update Utility) بتثبيت برنامج التشغيل لوحدة التحكم الخاصة بي دون أي مشاكل.



كما ترى ، هذا الجهاز لديه الموارد المخصصة



من الناحية النظرية ، بعد تثبيت برنامج التشغيل باستخدام وحدة تحكم GPIO ، من المحتمل أن يكون من الممكن العمل من خلال وظائف IOCTL ( كما هو الحال في هذا المستند) .

ومع ذلك ، لم تكن هناك مهمة برمجة GPIO من Windows ، لذلك تم تأجيل البحث عن مستند مشابه لشرائحي.



الخلاصة:


فحصت هذه المقالة الاتصال بين برنامج التشغيل والجهاز باستخدام طريقة _HID ACPI. قد يكون هذا الاتصال مطلوبًا على نظام x86 للأجهزة التي لا يمكن تعدادها.

  • في حالة Linux ، يتم التواصل مع برنامج التشغيل عبر .acpi_match_table
  • في حالة Windows ، يتم الاتصال ببرنامج التشغيل عبر ملف INF

Source: https://habr.com/ru/post/ar429336/


All Articles