[MAJOR] The first version of mailbox driver

DON'T USE THIS VESRION.
Basic functional of mailbox realized.
This commit is contained in:
Korobov Nikita
2017-07-05 12:00:33 +03:00
parent 65def63cad
commit ef69c49d79
10 changed files with 392 additions and 14 deletions

View File

@@ -16,12 +16,12 @@
./etc/system.conf.d/usbd minix-base
./service/bmp085 minix-base
./service/cat24c256 minix-base
./service/omap_emmc minix-base
./service/rpi_emmc minix-base
./service/fb minix-base
./service/gpio minix-base
./service/i2c minix-base
./service/lan8710a minix-base
./service/mailbox minix-base
./service/omap_emmc minix-base
./service/omap_mmc minix-base
./service/rpi_mmc minix-base
./service/random minix-base

View File

@@ -539,18 +539,6 @@ service edfictl
ipc ALL;
};
service rpi_emmc
{
system
PRIVCTL
IRQCTL
PADCONF
;
irq
52 # MMCSD1INT
;
};
service omap_emmc
{
system

View File

@@ -98,6 +98,8 @@ PROGRAMS+= rpi_mmc
dir.rpi_mmc:= minix/drivers/storage/mmc/rpi
PROGRAMS+= omap_mmc
dir.omap_mmc:= minix/drivers/storage/mmc/omap
PROGRAMS+= mailbox
dir.mailbox:= minix/drivers/system/mailbox
.endif # ${MACHINE_ARCH} == "earm"
.if ${LDSTATIC} == "-dynamic"

View File

@@ -31,6 +31,7 @@ d--755 0 0
#ifdef __arm__
rpi_mmc ---755 0 0 rpi_mmc
omap_mmc ---755 0 0 omap_mmc
mailbox ---755 0 0 mailbox
#endif
mfs ---755 0 0 mfs
procfs ---755 0 0 procfs

View File

@@ -6,5 +6,6 @@ SUBDIR+= gpio
SUBDIR+= log
SUBDIR+= random
SUBDIR+= mailbox
.include <bsd.subdir.mk>

View File

@@ -0,0 +1,15 @@
# Makefile for the mailbox driver.
PROG= mailbox
SRCS= mbox.c main.c
FILES=${PROG}.conf
FILESNAME=${PROG}
FILESDIR= /service
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
LDADD+= -lchardriver -lsys
# This is a system driver.
CPPFLAGS+= -D_SYSTEM=1
.include <minix.service.mk>

View File

@@ -0,0 +1,11 @@
service gpio
{
system
PRIVCTL # 4
IRQCTL # 19
;
irq
33
;
};

View File

@@ -0,0 +1,111 @@
#include <minix/drivers.h>
#include <minix/chardriver.h>
#include <minix/type.h>
#include "mbox.h"
#define NR_DEVS 1 /* number of minor devices */
#define MAILBOX_DEV 0 /* minor device for /dev/mailbox */
/* SEF functions and variables. */
static void sef_local_startup(void);
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
static ssize_t m_read(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
static ssize_t m_write(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
static int m_open(devminor_t minor, int access, endpoint_t user_endpt);
static int m_select(devminor_t, unsigned int, endpoint_t);
/* Entry points to this driver. */
static struct chardriver m_dtab = {
.cdr_open = m_open, /* open device */
.cdr_read = m_read, /* read from device */
.cdr_write = m_write, /* write to device (seeding it) */
.cdr_select = m_select, /* select hook */
};
/*===========================================================================*
* main *
*===========================================================================*/
int main(void)
{
/* SEF local startup. */
sef_local_startup();
/* Call the generic receive loop. */
chardriver_task(&m_dtab);
return(OK);
}
/*===========================================================================*
* sef_local_startup *
*===========================================================================*/
static void sef_local_startup()
{
/* Register init callbacks. */
sef_setcb_init_fresh(sef_cb_init_fresh);
sef_setcb_init_restart(sef_cb_init_fresh);
/* Let SEF perform startup. */
sef_startup();
}
/*===========================================================================*
* sef_cb_init_fresh *
*===========================================================================*/
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Initialize the random driver. */
static struct k_randomness krandom;
int i, s;
mailbox_init();
/* Announce we are up! */
chardriver_announce();
return(OK);
}
static ssize_t m_read(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{
/* Read from one of the driver's minor devices. */
size_t offset, chunk;
int r;
if (minor != MAILBOX_DEV)
return(EIO);
}
static ssize_t m_write(devminor_t minor, u64_t position, endpoint_t endpt,
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
{
/* Write to one of the driver's minor devices. */
size_t offset, chunk;
int r;
if (minor != MAILBOX_DEV)
return(EIO);
}
static int m_open(devminor_t minor, int access, endpoint_t user_endpt)
{
if (minor < 0 || minor >= NR_DEVS)
return(ENXIO);
}
static int m_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
{
/* mailbox device is always writable; it's infinitely readable
* once seeded, and doesn't block when it's not, so all operations
* are instantly possible. we ignore CDEV_OP_ERR.
*/
int ready_ops = 0;
if (minor != MAILBOX_DEV)
return(EIO);
return ops & (CDEV_OP_RD | CDEV_OP_WR);
}

View File

@@ -0,0 +1,110 @@
#include <minix/drivers.h>
#include <minix/chardriver.h>
#include <minix/type.h>
#include <minix/log.h>
#include <minix/vm.h>
#include <minix/spin.h>
#include <sys/mman.h>
#include <assert.h>
#include "mbox.h"
struct mailbox_t mailbox = {
.read = 0x00,
.res1 = 0x04,
.res2 = 0x08,
.res3 = 0x0c,
.peek = 0x10,
.sender = 0x14,
.status = 0x18,
.config = 0x1c,
.write = 0x20
};
struct mailbox_t *gmailbox;
uint32_t mbox_base;
/*
* Define a structure to be used for logging
*/
static struct log log = {
.name = "mailbox",
.log_level = LEVEL_INFO,
.log_func = default_log
};
static void write32(vir_bytes reg, uint32_t data)
{
assert(reg >= 0 && reg <= sizeof (struct mailbox_t));
uint32_t addr = mbox_base + reg;
addr = data;
}
static uint32_t read32(vir_bytes reg)
{
assert(reg >= 0 && reg <= sizeof (struct mailbox_t));
return mbox_base + reg;
}
void mailbox_init()
{
uint32_t value;
value = 0;
struct minix_mem_range mr;
mr.mr_base = MBOX_BASE;
mr.mr_limit = MBOX_BASE + sizeof (struct mailbox_t);
/* grant ourself rights to map the register memory */
if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
panic("Unable to request permission to map memory");
}
/* Set the base address to use */
mbox_base =
(uint32_t) vm_map_phys(SELF, (void *) MBOX_BASE,
sizeof (struct mailbox_t));
if (mbox_base == (uint32_t) MAP_FAILED)
panic("Unable to map MMC memory");
gmailbox = &mailbox;
}
uint32_t mbox_read(uint8_t chan)
{
uint32_t data = 0;
while (1) {
while (read32(gmailbox->status) & MAILBOX_EMPTY) {
log_debug(&log, "status: 0x%x\n", read32(gmailbox->status));
//mem barrier
}
data = read32(gmailbox->read);
log_debug(&log, "received data %d\n", data);
if (((uint8_t) data & 0xf) == chan) {
return (data & ~0xf);
}
}
}
void mbox_write(uint8_t chan, uint32_t data)
{
while (read32(gmailbox->status) & MAILBOX_FULL) ;
write32(gmailbox->write, (data & ~0xf) | (uint32_t) (chan & 0xf));
}
void mbox_flush(void)
{
spin_t spin;
while (!(read32(gmailbox->status) & MAILBOX_EMPTY)) {
spin_init(&spin, 20000);
while (1) {
if(spin_check(&spin) == FALSE)
break;
}
}
}

View File

@@ -0,0 +1,139 @@
#ifndef _MBOX_H_
#define _MBOX_H_
#define MBOX_BASE (0x3f000000 + 0xb880)
struct mailbox_t {
vir_bytes read;
vir_bytes res1;
vir_bytes res2;
vir_bytes res3;
vir_bytes peek;
vir_bytes sender;
vir_bytes status;
vir_bytes config;
vir_bytes write;
};
enum mail_chan {
MBOX_POWER,
MBOX_FRAMEBUFFER,
MBOX_UART,
MBOX_VCHIQ,
MBOX_LEDS,
MBOX_BUTTONS,
MBOX_TOUCH,
MBOX_NUSED,
MBOX_PROP,
MBOX_REVPROP
};
void mailbox_init();
uint32_t mbox_read(uint8_t chan);
void mbox_write(uint8_t chan, uint32_t data);
void mbox_flush();
#define MAILBOX_FULL 0x80000000
#define MAILBOX_EMPTY 0x40000000
#define MBX_TAG_GET_BOARD_MODEL 0x00010001
#define MBX_TAG_GET_BOARD_REVISION 0x00010002
// Timers interrupt control registers
#define CORE0_TIMER_IRQCNTL 0x40000040
#define CORE1_TIMER_IRQCNTL 0x40000044
#define CORE2_TIMER_IRQCNTL 0x40000048
#define CORE3_TIMER_IRQCNTL 0x4000004C
// Where to route timer interrupt to, IRQ/FIQ
// Setting both the IRQ and FIQ bit gives an FIQ
#define TIMER0_IRQ 0x01
#define TIMER1_IRQ 0x02
#define TIMER2_IRQ 0x04
#define TIMER3_IRQ 0x08
#define TIMER0_FIQ 0x10
#define TIMER1_FIQ 0x20
#define TIMER2_FIQ 0x40
#define TIMER3_FIQ 0x80
// Mailbox interrupt control registers
#define CORE0_MBOX_IRQCNTL 0x40000050
#define CORE1_MBOX_IRQCNTL 0x40000054
#define CORE2_MBOX_IRQCNTL 0x40000058
#define CORE3_MBOX_IRQCNTL 0x4000005C
// Where to route mailbox interrupt to, IRQ/FIQ
// Setting both the IRQ and FIQ bit gives an FIQ
#define MBOX0_IRQ 0x01
#define MBOX1_IRQ 0x02
#define MBOX2_IRQ 0x04
#define MBOX3_IRQ 0x08
#define MBOX0_FIQ 0x10
#define MBOX1_FIQ 0x20
#define MBOX2_FIQ 0x40
#define MBOX3_FIQ 0x80
// IRQ & FIQ
#define CORE0_IRQ_SOURCE 0x40000060
#define CORE1_IRQ_SOURCE 0x40000064
#define CORE2_IRQ_SOURCE 0x40000068
#define CORE3_IRQ_SOURCE 0x4000006C
#define CORE0_FIQ_SOURCE 0x40000070
#define CORE1_FIQ_SOURCE 0x40000074
#define CORE2_FIQ_SOURCE 0x40000078
#define CORE3_FIQ_SOURCE 0x4000007C
// Interrupt source bits
// IRQ and FIQ are the same
// GPU bits can be set
#define INT_SRC_TIMER0 0x00000001
#define INT_SRC_TIMER1 0x00000002
#define INT_SRC_TIMER2 0x00000004
#define INT_SRC_TIMER3 0x00000008
#define INT_SRC_MBOX0 0x00000010
#define INT_SRC_MBOX1 0x00000020
#define INT_SRC_MBOX2 0x00000040
#define INT_SRC_MBOX3 0x00000080
#define INT_SRC_GPU 0x00000100
#define INT_SRC_PMU 0x00000200
// Mailbox write
#define CORE0_MBOX0_SET 0x40000080
#define CORE0_MBOX1_SET 0x40000084
#define CORE0_MBOX2_SET 0x40000088
#define CORE0_MBOX3_SET 0x4000008C
#define CORE1_MBOX0_SET 0x40000090
#define CORE1_MBOX1_SET 0x40000094
#define CORE1_MBOX2_SET 0x40000098
#define CORE1_MBOX3_SET 0x4000009C
#define CORE2_MBOX0_SET 0x400000A0
#define CORE2_MBOX1_SET 0x400000A4
#define CORE2_MBOX2_SET 0x400000A8
#define CORE2_MBOX3_SET 0x400000AC
#define CORE3_MBOX0_SET 0x400000B0
#define CORE3_MBOX1_SET 0x400000B4
#define CORE3_MBOX2_SET 0x400000B8
#define CORE3_MBOX3_SET 0x400000BC
// Mailbox write (Read & Write)
#define CORE0_MBOX0_RDCLR 0x400000C0
#define CORE0_MBOX1_RDCLR 0x400000C4
#define CORE0_MBOX2_RDCLR 0x400000C8
#define CORE0_MBOX3_RDCLR 0x400000CC
#define CORE1_MBOX0_RDCLR 0x400000D0
#define CORE1_MBOX1_RDCLR 0x400000D4
#define CORE1_MBOX2_RDCLR 0x400000D8
#define CORE1_MBOX3_RDCLR 0x400000DC
#define CORE2_MBOX0_RDCLR 0x400000E0
#define CORE2_MBOX1_RDCLR 0x400000E4
#define CORE2_MBOX2_RDCLR 0x400000E8
#define CORE2_MBOX3_RDCLR 0x400000EC
#define CORE3_MBOX0_RDCLR 0x400000F0
#define CORE3_MBOX1_RDCLR 0x400000F4
#define CORE3_MBOX2_RDCLR 0x400000F8
#define CORE3_MBOX3_RDCLR 0x400000FC
#endif /* _MBOX_H_ */