.. _adlerdev-en: ========================== Example PCI Device ========================== The example device is used for hardware calculation of the Adler-32 checksum. We provide it as a modified version of qemu. Driver for the example device: :download:`adlerdev.tar.gz` QEMU ==== To use the example device, a modified version of qemu is required, available in source version. To compile the modified version of qemu, you should: 1. Clone the repository https://github.com/mwkmwkmwk/qemu 2. ``git checkout adlerdev`` 3. Make sure the dependencies are installed: ``ncurses``, ``libsdl``, ``curl``, and in some distributions also ``ncurses-dev``, ``libsdl-dev``, ``curl-dev`` (package names may vary slightly depending on the distribution) 4. Run ``./configure`` with options as desired (see ``./configure --help``). The official binary was compiled with:: --target-list=x86_64-softmmu 5. Execute ``make`` 6. Install by executing ``make install``, or run directly (the binary is ``x86_64-softmmu/qemu-system-x86_64``). Device ========== The device is connected to the computer via the PCI bus -- the vendor identifier is ``0x0666``, and the device identifier is ``0x0a32``. The device has 5 registers: ``BAR0 + 0x0000: INTR`` Interrupt status register. When read, it has a value of 1 if the device is signaling an interrupt, or 0 if it is not. To respond to an interrupt (and cause the device to stop signaling an interrupt), you should write 1 to this register. You should also write 1 to this register when starting the device (the device may signal an interrupt at startup). ``BAR0 + 0x0004: INTR_ENABLE`` Interrupt enable register, read and write. If it has a value of 1, the device is allowed to signal an interrupt. If it has a value of 0, the device will not signal a PCI interrupt (the interrupt will still be visible in the ``INTR`` register). ``BAR0 + 0x0008: DATA_PTR`` Pointer to the data to be processed, read and write. During data processing, the device will automatically increment this pointer. ``BAR0 + 0x000c: DATA_SIZE`` Size of the data to be processed, read and write. Writing a non-zero value to this register will immediately start data processing. During processing, the device will automatically decrement this register. When all data has been processed (and this register drops to zero), an interrupt will be signaled (``INTR`` will have a value of 1). ``BAR0 + 0x0010: SUM`` Current sum. Before processing data, the initial value of the sum should be written here. As data is processed, the device updates the sum. To process data, you should: - make sure that ``INTR`` is zeroed and ``INTR_ENABLE`` is enabled - write the initial value of the sum to ``SUM`` - write the data pointer to ``DATA_PTR`` - write the data size to ``DATA_SIZE`` - wait for an interrupt - clear the interrupt (write 1 to ``INTR``)