diff --git a/src/mailbox.c b/src/mailbox.c index befa7b6..902f6bb 100644 --- a/src/mailbox.c +++ b/src/mailbox.c @@ -4,14 +4,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "mailbox.h" @@ -41,41 +42,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. void *mapmem(unsigned base, unsigned size) { - int mem_fd; - unsigned offset = base % PAGE_SIZE; - base = base - offset; - /* open /dev/mem */ - if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { - printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); - exit (-1); - } - void *mem = mmap( - 0, - size, - PROT_READ|PROT_WRITE, - MAP_SHARED/*|MAP_FIXED*/, - mem_fd, - base); + int mem_fd; + unsigned offset = base % PAGE_SIZE; + base = base - offset; + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); + exit (-1); + } + void *mem = mmap( + 0, + size, + PROT_READ|PROT_WRITE, + MAP_SHARED/*|MAP_FIXED*/, + mem_fd, + base); #ifdef DEBUG - printf("base=0x%x, mem=%p\n", base, mem); + printf("base=0x%x, mem=%p\n", base, mem); #endif - if (mem == MAP_FAILED) { - printf("mmap error %d\n", (int)mem); - exit (-1); - } - close(mem_fd); - return (char *)mem + offset; + if (mem == MAP_FAILED) { + printf("mmap error %d\n", (int)mem); + exit (-1); + } + close(mem_fd); + return (char *)mem + offset; } void *unmapmem(void *addr, unsigned size) { - int s = munmap(addr, size); - if (s != 0) { - printf("munmap error %d\n", s); - exit (-1); - } + int s = munmap(addr, size); + if (s != 0) { + printf("munmap error %d\n", s); + exit (-1); + } - return NULL; + return NULL; } /* @@ -84,177 +85,192 @@ void *unmapmem(void *addr, unsigned size) static int mbox_property(int file_desc, void *buf) { - int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); + int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); - if (ret_val < 0) { - printf("ioctl_set_msg failed:%d\n", ret_val); - } + if (ret_val < 0) { + printf("ioctl_set_msg failed:%d\n", ret_val); + } #ifdef DEBUG - unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; - for (i=0; i= 0) { + printf("Using mbox device " DEVICE_FILE_NAME ".\n"); + return file_desc; + } + + // Try to create one + unlink(LOCAL_DEVICE_FILE_NAME); + if(mknod(LOCAL_DEVICE_FILE_NAME, S_IFCHR|0600, makedev(MAJOR_NUM_A, 0)) >= 0 && + (file_desc = open(LOCAL_DEVICE_FILE_NAME, 0)) >= 0) { + printf("Using local mbox device file with major %d.\n", MAJOR_NUM_A); + return file_desc; + } + + unlink(LOCAL_DEVICE_FILE_NAME); + if(mknod(LOCAL_DEVICE_FILE_NAME, S_IFCHR|0600, makedev(MAJOR_NUM_B, 0)) >= 0 && + (file_desc = open(LOCAL_DEVICE_FILE_NAME, 0)) >= 0) { + printf("Using local mbox device file with major %d.\n", MAJOR_NUM_B); + return file_desc; + } + + return -1; } void mbox_close(int file_desc) { - close(file_desc); + close(file_desc); } diff --git a/src/mailbox.h b/src/mailbox.h index cd882b7..5315591 100644 --- a/src/mailbox.h +++ b/src/mailbox.h @@ -27,9 +27,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#define MAJOR_NUM 100 -#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -#define DEVICE_FILE_NAME "mbox" +// Newer kernels (>= 4.1) use major 249, older ones major 100. +#define MAJOR_NUM_A 249 +#define MAJOR_NUM_B 100 +#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM_B, 0, char *) +#define DEVICE_FILE_NAME "/dev/vcio" +#define LOCAL_DEVICE_FILE_NAME "mbox" int mbox_open(); void mbox_close(int file_desc); diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index 0682f85..b8e91b8 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -109,7 +109,7 @@ #include "control_pipe.h" #include "mailbox.h" -#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */ +#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */ #if (RASPI)==1 #define PERIPH_VIRT_BASE 0x20000000 @@ -140,24 +140,24 @@ #define DMA_CONBLK_AD (0x04/4) #define DMA_DEBUG (0x20/4) -#define DMA_BASE_OFFSET 0x00007000 +#define DMA_BASE_OFFSET 0x00007000 #define DMA_LEN 0x24 -#define PWM_BASE_OFFSET 0x0020C000 -#define PWM_LEN 0x28 -#define CLK_BASE_OFFSET 0x00101000 -#define CLK_LEN 0xA8 -#define GPIO_BASE_OFFSET 0x00200000 -#define GPIO_LEN 0x100 +#define PWM_BASE_OFFSET 0x0020C000 +#define PWM_LEN 0x28 +#define CLK_BASE_OFFSET 0x00101000 +#define CLK_LEN 0xA8 +#define GPIO_BASE_OFFSET 0x00200000 +#define GPIO_LEN 0x100 -#define DMA_VIRT_BASE (PERIPH_VIRT_BASE + DMA_BASE_OFFSET) -#define PWM_VIRT_BASE (PERIPH_VIRT_BASE + PWM_BASE_OFFSET) -#define CLK_VIRT_BASE (PERIPH_VIRT_BASE + CLK_BASE_OFFSET) -#define GPIO_VIRT_BASE (PERIPH_VIRT_BASE + GPIO_BASE_OFFSET) -#define PCM_VIRT_BASE (PERIPH_VIRT_BASE + PCM_BASE_OFFSET) +#define DMA_VIRT_BASE (PERIPH_VIRT_BASE + DMA_BASE_OFFSET) +#define PWM_VIRT_BASE (PERIPH_VIRT_BASE + PWM_BASE_OFFSET) +#define CLK_VIRT_BASE (PERIPH_VIRT_BASE + CLK_BASE_OFFSET) +#define GPIO_VIRT_BASE (PERIPH_VIRT_BASE + GPIO_BASE_OFFSET) +#define PCM_VIRT_BASE (PERIPH_VIRT_BASE + PCM_BASE_OFFSET) -#define PWM_PHYS_BASE (PERIPH_PHYS_BASE + PWM_BASE_OFFSET) -#define PCM_PHYS_BASE (PERIPH_PHYS_BASE + PCM_BASE_OFFSET) -#define GPIO_PHYS_BASE (PERIPH_PHYS_BASE + GPIO_BASE_OFFSET) +#define PWM_PHYS_BASE (PERIPH_PHYS_BASE + PWM_BASE_OFFSET) +#define PCM_PHYS_BASE (PERIPH_PHYS_BASE + PCM_BASE_OFFSET) +#define GPIO_PHYS_BASE (PERIPH_PHYS_BASE + GPIO_BASE_OFFSET) #define PWM_CTL (0x00/4) @@ -201,12 +201,12 @@ typedef struct { static struct { - int handle; /* From mbox_open() */ - unsigned mem_ref; /* From mem_alloc() */ - unsigned bus_addr; /* From mem_lock() */ - uint8_t *virt_addr; /* From mapmem() */ + int handle; /* From mbox_open() */ + unsigned mem_ref; /* From mem_alloc() */ + unsigned bus_addr; /* From mem_lock() */ + uint8_t *virt_addr; /* From mapmem() */ } mbox; - + static volatile uint32_t *pwm_reg; @@ -278,9 +278,9 @@ fatal(char *fmt, ...) static uint32_t mem_virt_to_phys(void *virt) { - uint32_t offset = (uint8_t *)virt - mbox.virt_addr; + uint32_t offset = (uint8_t *)virt - mbox.virt_addr; - return mbox.bus_addr + offset; + return mbox.bus_addr + offset; } static uint32_t @@ -327,22 +327,25 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, clk_reg = map_peripheral(CLK_VIRT_BASE, CLK_LEN); gpio_reg = map_peripheral(GPIO_VIRT_BASE, GPIO_LEN); - /* Use the mailbox interface to the VC to ask for physical memory */ - unlink(MBFILE); - if (mknod(MBFILE, S_IFCHR|0600, makedev(100, 0)) < 0) - fatal("Failed to create mailbox device.\n"); - mbox.handle = mbox_open(); - if (mbox.handle < 0) - fatal("Failed to open mailbox.\n"); - printf("Allocating physical memory: size = %d ", NUM_PAGES * 4096); - mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * 4096, 4096, MEM_FLAG); - /* TODO: How do we know that succeeded? */ - printf("mem_ref = %u ", mbox.mem_ref); - mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref); - printf("bus_addr = %x ", mbox.bus_addr); - mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * 4096); - printf("virt_addr = %p\n", mbox.virt_addr); - + // Use the mailbox interface to the VC to ask for physical memory. + mbox.handle = mbox_open(); + if (mbox.handle < 0) + fatal("Failed to open mailbox. Check kernel support for vcio / BCM2708 mailbox.\n"); + printf("Allocating physical memory: size = %d ", NUM_PAGES * 4096); + if(! (mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * 4096, 4096, MEM_FLAG))) { + fatal("Could not allocate memory.\n"); + } + // TODO: How do we know that succeeded? + printf("mem_ref = %u ", mbox.mem_ref); + if(! (mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref))) { + fatal("Could not lock memory.\n"); + } + printf("bus_addr = %x ", mbox.bus_addr); + if(! (mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * 4096))) { + fatal("Could not map memory.\n"); + } + printf("virt_addr = %p\n", mbox.virt_addr); + // GPIO4 needs to be ALT FUNC 0 to output the clock gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12);