# EDU device

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)
        ;