Способы доступа к вводу / выводу
Когда программа предполагает доступ к порту ввода / вывода, мы всегда можем увидеть использование inb/outb Две функции (или семейство функций in / out), но реализация этих двух функций на разных процессорах различна, в основном это касается архитектуры фон Неймана (независимая адресация) и гарвардской архитектуры (унифицированная). адресации). также ioread8/iowrite8 и readb/writeb Функция, но одинаковая на разных архитектурах.
Единый сборник
Часть адресного пространства памяти разделена на порты ввода / вывода, так что мы можем получить доступ к адресному пространству ввода / вывода, например, к памяти
Унифицированная адресация также называется «Память ввода / вывода«Кстати, периферийные регистры расположены на»Пространство памяти”
Процесс доступа:
request_mem_region() -> ioremap() -> inb()/outb() ioread8()/iowrite8() readb()/writeb()-> iounmap() -> release_mem_region()
Взяв процессор arm в качестве примера, в ядре 2.6.32
arch/arm/include/asm/io.h #define ioread8(p) (< unsigned int __v = __raw_readb(p); __v; >) #define iowrite8(v,p) __raw_writeb(v, p) #define readb(c) (< __u8 __v = __raw_readb(__mem_pci(c)); __v; >) #define writeb(v,c) __raw_writeb(v,__mem_pci(c)) #define inb(p) (< __u8 __v = __raw_readb(__io(p)); __v; >) #define outb(v,p) __raw_writeb(v,__io(p)) #define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) #define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))
Независимая подготовка
Разделяйте адресное пространство памяти и адресное пространство ввода / вывода отдельно, используйте другой доступ к шине
Независимая адресация также называется режимом «порт ввода-вывода», а периферийные регистры расположены в «пространстве ввода-вывода (адреса)».
I / O port mapping Порт сопоставленного ввода / вывода
Читать напрямую
Процесс доступа:
request_region() -> inb()/outb() -> release_region()
Взяв процессор x86 в качестве примера, в ядре 2.6.32
arch/x86/include/asm/io_64.h __IN(b, "") __OUT(b, "b", char) #define __IN1(s) \ static inline RETURN_TYPE in##s(unsigned short port) \ < \ RETURN_TYPE _v; #define __IN2(s, s1, s2) \ asm volatile ("in" #s " %" s2 "1,%" s1 "0" #define __IN(s, s1, i. ) \ __IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \ return _v; \ >\ __IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \ slow_down_io(); \ return _v; > #define __OUT1(s, x) \ static inline void out##s(unsigned x value, unsigned short port) < #define __OUT2(s, s1, s2) \ asm volatile ("out" #s " %" s1 "0,%" s2 "1" #define __OUT(s, s1, x) \ __OUT1(s, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \ >\ __OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \ slow_down_io(); \ >
Используется много определений макросов, короче говоря, используются инструкции in и out сборки x86
Кроме того, определения inb и outb также можно найти в arch / x86 / boot / boot.h, который также использует инструкции in и out сборки x86, но inb и outb являются функциями Форма дает
/* Basic port I/O */ static inline void outb(u8 v, u16 port) < asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); >static inline u8 inb(u16 port)
Память сопоставлена с I / O
Порт IO отображается в память IO («пространство памяти»), а затем функция доступа к памяти IO используется для доступа к порту IO.
void ioport_map(unsigned long port, unsigned int count);
С помощью этой функции вы можете отобразить число последовательных портов ввода-вывода в начале порта в раздел «пространства памяти», а затем получить доступ к этим вводам-выводам по возвращенному адресу, как если бы вы обращались к памяти ввода-вывода. порт.
Процесс доступа:
request_region() -> ioport_map() -> readb()/writeb() -> ioport_unmap()(nothing to do) -> release_region()
Взяв процессор x86 в качестве примера, в ядре 2.6.32
arch/x86/include/asm/io_64.h #define build_mmio_read(name, size, type, reg, barrier) \ static inline type name(const volatile void __iomem *addr) \ < type ret; asm volatile("mov" size " %1,%0":reg (ret) \ :"m" (*(volatile type __force *)addr) barrier); return ret; >#define build_mmio_write(name, size, type, reg, barrier) \ static inline void name(type val, volatile void __iomem *addr) \ < asm volatile("mov" size " %0,%1": :reg (val), \ "m" (*(volatile type __force *)addr) barrier); >build_mmio_read(readb, "b", unsigned char, "=q", :"memory") build_mmio_write(writeb, "b", unsigned char, "q", :"memory") build_mmio_read(__readb, "b", unsigned char, "=q", ) build_mmio_write(__writeb, "b", unsigned char, "q", ) #define __raw_readb __readb #define __raw_writeb __writeb
Порты ввода вывода linux
Библиотека сайта rus-linux.net
центральным процессором ( Central Processing Unit или CPU ) посредством шин . На сегодняшний день наиболее часто используемыми шинами являются шины usb , pci , agp , pci-express , а также шина pcmcia , известная, как pc-card . Все они являются шинами с поддержкой технологии Plug and Play .
Более старые компьютеры архитектуры x86 обычно имели шины isa , которые настраивались с помощью джамперов или dip-переключателей .
Для того, чтобы получить список шин вашего компьютера, распознанных ядром Linux, следует обратиться к файлам из директории /proc/bus/ (ниже приведены примеры списков файлов из данной директории в случае использования дистрибутивов Ubuntu 7.04 и RHEL 4.4 соответственно).
root@laika:~# ls /proc/bus/ input pccard pci usb [root@RHEL4b ~]# ls /proc/bus/ input pci usb
Можете ли вы догадаться, какой из этих двух списков файлов был создан при работе с ноутбуком?
Для получения списка всех устройств usb, соединенных с вашей системой, вам придется прочитать содержимое файла /proc/bus/usb/devices (конечно же, в том случае, если этот файл существует), причем вы также можете получить аналогичный лучше читаемый список с помощью утилиты lsusb , вывод которой для системы SPARC под управлением дистрибутива Ubuntu приведен ниже.
root@shaka:~# lsusb Bus 001 Device 002: ID 0430:0100 Sun Microsystems, Inc. 3-button Mouse Bus 001 Device 003: ID 0430:0005 Sun Microsystems, Inc. Type 6 Keyboard Bus 001 Device 001: ID 04b0:0136 Nikon Corp. Coolpix 7900 (storage) root@shaka:~#
Файл /var/lib/usbutils/usb.ids
Файл /var/lib/usbutils/usb.ids содержит сжатый с помощью утилиты gzip список всех известных идентификаторов и соответствующих им описаний устройств usb.
paul@barry:~$ zmore /var/lib/usbutils/usb.ids | head ------> /var/lib/usbutils/usb.ids # If you have any new entries, send them to the maintainer. # The latest version can be obtained from # http://www.linux-usb.org/usb.ids # # $Id: usb.ids,v 1.225 2006/07/13 04:18:02 dbrownell Exp $
Для получения списка всех подсоединенных к системе устройств PCI вы можете либо обратиться к содержимому файла /proc/bus/pci , либо использовать утилиту lspci (фрагмент вывода которой приведен ниже).
paul@laika:~$ lspci . 00:06.0 FireWire (IEEE 1394): Texas Instruments TSB43AB22/A IEEE-139. 00:08.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-816. 00:09.0 Multimedia controller: Philips Semiconductors SAA7133/SAA713. 00:0a.0 Network controller: RaLink RT2500 802.11g Cardbus/mini-PCI 00:0f.0 RAID bus controller: VIA Technologies, Inc. VIA VT6420 SATA . 00:0f.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A. 00:10.0 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1. 00:10.1 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1. .
Запросы прерываний
О запросах прерываний
Запрос прерывания ( Interrupt request или IRQ ) является запросом, отправляемым устройством центральному процессору. Устройство генерирует запрос прерывания в тот момент, когда ему должно быть уделено внимание со стороны центрального процессора (этот момент может наступить тогда, когда устройство заканчивает накопление данных, которые должны быть переданы центральному процессору).
С момента презентации шины PCI запросы прерываний могут разделяться между устройствами.
Запрос прерывания с идентификатором 0 всегда зарезервирован за системным таймером, с идентификатором 1 — за клавиатурой, а с идентификатором 2 используется в качестве канала для запросов прерываний с идентификаторами из диапазона от 8 до 15 и, таким образом, совпадает с запросом прерывания с идентификатором 9.
Вы можете ознакомиться со списком идентификаторов запросов прерываний в вашей системе, прочитав содержимое файла /proc/interrupts .
paul@laika:~$ cat /proc/interrupts CPU0 CPU1 0: 1320048 555 IO-APIC-edge timer 1: 10224 7 IO-APIC-edge i8042 7: 0 0 IO-APIC-edge parport0 8: 2 1 IO-APIC-edge rtc 10: 3062 21 IO-APIC-fasteoi acpi 12: 131 2 IO-APIC-edge i8042 15: 47073 0 IO-APIC-edge ide1 18: 0 1 IO-APIC-fasteoi yenta 19: 31056 1 IO-APIC-fasteoi libata, ohci1394 20: 19042 1 IO-APIC-fasteoi eth0 21: 44052 1 IO-APIC-fasteoi uhci_hcd:usb1, uhci_hcd:usb2. 22: 188352 1 IO-APIC-fasteoi ra0 23: 632444 1 IO-APIC-fasteoi nvidia 24: 1585 1 IO-APIC-fasteoi VIA82XX-MODEM, VIA8237
Также вы можете использовать утилиту dmesg для установления идентификаторов запросов прерываний, резервируемых для определенных устройств в процессе загрузки системы.
paul@laika:~$ dmesg | grep "irq 1[45]" [ 28.930069] ata3: PATA max UDMA/133 cmd 0x1f0 ctl 0x3f6 bmdma 0x2090 irq 14 [ 28.930071] ata4: PATA max UDMA/133 cmd 0x170 ctl 0x376 bmdma 0x2098 irq 15
Порты ввода-вывода
Передача данных в противоположном направлении от центрального процессора к устройству осуществляется посредством портов ввода-вывода ( IO Ports ). Центральный процессор записывает данные или управляющие коды в порт ввода-вывода устройства. Но данный метод передачи данных не является односторонним, так как центральный процессор может также использовать порт ввода-вывода устройства для чтения информации о состоянии устройства. В отличие от запросов прерываний, порты ввода-вывода не могут разделяться между устройствами!
Вы можете получить список портов ввода-вывода устройств вашей системы, прочитав содержимое файла /proc/interrupts .
[root@RHEL4b ~]# cat /proc/ioports 0000-001f : dma1 0020-0021 : pic1 0040-0043 : timer0 0050-0053 : timer1 0060-006f : keyboard 0070-0077 : rtc 0080-008f : dma page reg 00a0-00a1 : pic2 00c0-00df : dma2 00f0-00ff : fpu 0170-0177 : ide1 02f8-02ff : serial .
Технология DMA
Устройство, которое передает большие объемы данных, а также требует для своей работы генерации большого количества запросов прерываний и создания большого количества портов ввода-вывода, может создавать значительную нагрузку на центральный процессор. Благодаря технологии прямого доступа к памяти ( Direct Memory Access или DMA ), устройство может получить доступ (временный) к определенному диапазону адресов оперативной памяти .
Прочитав содержимое файла /proc/dma , вы наверняка не получите необходимой информации ввиду того, что данный файл содержит исключительно информацию об используемых в данный момент каналах прямого доступа к памяти для устройств ISA .
root@laika:~# cat /proc/dma 1: parport0 4: cascade
Ввиду того, что данные об устройствах PCI , использующих технологию прямого доступа к памяти, не приводятся в файле /proc/dma , в случае необходимости получения информации о таких устройствах может оказаться полезной утилита dmesg . В примере ниже показано, что в процессе загрузки параллельный порт получил канал прямого доступа к памяти номер 1, а инфракрасный порт — канал прямого доступа к памяти номер 3.
root@laika:~# dmesg | egrep -C 1 'dma 1|dma 3' [ 20.576000] parport: PnPBIOS parport detected. [ 20.580000] parport0: PC-style at 0x378 (0x778), irq 7, dma 1. [ 20.764000] irda_init() -- [ 21.204000] pnp: Device 00:0b activated. [ 21.204000] nsc_ircc_pnp_probe() : From PnP, found firbase 0x2F8. [ 21.204000] nsc-ircc, chip->init
Предыдущий раздел: | Оглавление | Следующий раздел: |
Приложение A. Раскладки клавиатуры | Приложение C. Лицензия |