| EDU device | |
| ========== | |
| .. | |
| Copyright (c) 2014-2015 Jiri Slaby | |
| This document is licensed under the GPLv2 (or later). | |
| This is an educational device for writing (kernel) drivers. Its original | |
| intention was to support the Linux kernel lectures taught at the Masaryk | |
| University. Students are given this virtual device and are expected to write a | |
| driver with I/Os, IRQs, DMAs and such. | |
| The devices behaves very similar to the PCI bridge present in the COMBO6 cards | |
| developed under the Liberouter wings. Both PCI device ID and PCI space is | |
| inherited from that device. | |
| Command line switches | |
| --------------------- | |
| ``-device edu[,dma_mask=mask]`` | |
| ``dma_mask`` makes the virtual device work with DMA addresses with the given | |
| mask. For educational purposes, the device supports only 28 bits (256 MiB) | |
| by default. Students shall set dma_mask for the device in the OS driver | |
| properly. | |
| PCI specs | |
| --------- | |
| PCI ID: | |
| ``1234:11e8`` | |
| PCI Region 0: | |
| I/O memory, 1 MB in size. Users are supposed to communicate with the card | |
| through this memory. | |
| MMIO area spec | |
| -------------- | |
| Only ``size == 4`` accesses are allowed for addresses ``< 0x80``. | |
| ``size == 4`` or ``size == 8`` for the rest. | |
| 0x00 (RO) : identification | |
| Value is in the form ``0xRRrr00edu`` where: | |
| - ``RR`` -- major version | |
| - ``rr`` -- minor version | |
| 0x04 (RW) : card liveness check | |
| It is a simple value inversion (``~`` C operator). | |
| 0x08 (RW) : factorial computation | |
| The stored value is taken and factorial of it is put back here. | |
| This happens only after factorial bit in the status register (0x20 | |
| below) is cleared. | |
| 0x20 (RW) : status register | |
| Bitwise OR of: | |
| 0x01 | |
| computing factorial (RO) | |
| 0x80 | |
| raise interrupt after finishing factorial computation | |
| 0x24 (RO) : interrupt status register | |
| It contains values which raised the interrupt (see interrupt raise | |
| register below). | |
| 0x60 (WO) : interrupt raise register | |
| Raise an interrupt. The value will be put to the interrupt status | |
| register (using bitwise OR). | |
| 0x64 (WO) : interrupt acknowledge register | |
| Clear an interrupt. The value will be cleared from the interrupt | |
| status register. This needs to be done from the ISR to stop | |
| generating interrupts. | |
| 0x80 (RW) : DMA source address | |
| Where to perform the DMA from. | |
| 0x88 (RW) : DMA destination address | |
| Where to perform the DMA to. | |
| 0x90 (RW) : DMA transfer count | |
| The size of the area to perform the DMA on. | |
| 0x98 (RW) : DMA command register | |
| Bitwise OR of: | |
| 0x01 | |
| start transfer | |
| 0x02 | |
| direction (0: from RAM to EDU, 1: from EDU to RAM) | |
| 0x04 | |
| raise interrupt 0x100 after finishing the DMA | |
| IRQ controller | |
| -------------- | |
| An IRQ is generated when written to the interrupt raise register. The value | |
| appears in interrupt status register when the interrupt is raised and has to | |
| be written to the interrupt acknowledge register to lower it. | |
| The device supports both INTx and MSI interrupt. By default, INTx is | |
| used. Even if the driver disabled INTx and only uses MSI, it still | |
| needs to update the acknowledge register at the end of the IRQ handler | |
| routine. | |
| DMA controller | |
| -------------- | |
| One has to specify, source, destination, size, and start the transfer. One | |
| 4096 bytes long buffer at offset 0x40000 is available in the EDU device. I.e. | |
| one can perform DMA to/from this space when programmed properly. | |
| Example of transferring a 100 byte block to and from the buffer using a given | |
| PCI address ``addr``: | |
| :: | |
| addr -> DMA source address | |
| 0x40000 -> DMA destination address | |
| 100 -> DMA transfer count | |
| 1 -> DMA command register | |
| while (DMA command register & 1) | |
| ; | |
| :: | |
| 0x40000 -> DMA source address | |
| addr+100 -> DMA destination address | |
| 100 -> DMA transfer count | |
| 3 -> DMA command register | |
| while (DMA command register & 1) | |
| ; |