mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
hw: misc, add educational driver
I am using qemu for teaching the Linux kernel at our university. I wrote a simple PCI device that can answer to writes/reads, generate interrupts and perform DMA. As I am dragging it locally over 2 years, I am sending it to you now. Signed-off-by: Jiri Slaby <jslaby@suse.cz> [Fix 32-bit compilation. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e720677e32
commit
b30934cb52
5 changed files with 525 additions and 0 deletions
110
docs/specs/edu.txt
Normal file
110
docs/specs/edu.txt
Normal file
|
@ -0,0 +1,110 @@
|
|||
|
||||
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 (0xRRrr00edu)
|
||||
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
|
||||
0x01 -- computing factorial (RO)
|
||||
0x80 -- raise interrupt 0x01 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
|
||||
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.
|
||||
|
||||
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)
|
||||
;
|
Loading…
Add table
Add a link
Reference in a new issue