From 6da291dc416a718164b5596aa16b1901f2770732 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 12 Nov 2020 20:01:32 +0200 Subject: [PATCH] - implemented video mode setting with the property tags, and once again it only works in the emulator - added hexdump function for debugging - added reboot function using the watchdog timer --- src/debug.c | 38 ++++++++++++++++++++++ src/debug.h | 6 ++++ src/main.c | 12 ++++++- src/mem.h | 3 -- src/rpi.c | 13 ++++++++ src/rpi.h | 28 ++++++++-------- src/video.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 src/debug.c create mode 100644 src/debug.h diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..241b147 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,38 @@ +#include +#include +#include "debug.h" + + +void hexdump(void *start, int nbytes) +{ + int i, j, nlines; + unsigned char *ptr = start; + unsigned char *end = ptr + nbytes; + + nlines = (nbytes + 0xf) >> 4; + + for(i=0; i + +#define RPI_MEM_BUS_COHERENT(addr) (((uint32_t)addr) | 0x40000000) +#define RPI_MEM_BUS_UNCACHED(addr) (((uint32_t)addr) | 0xc0000000) + + #define RPI_MBOX_FRAMEBUF 1 #define RPI_MBOX_PROP 8 @@ -13,35 +18,30 @@ #define RPI_TAG_ALLOCFB 0x040001 #define RPI_TAG_RELEASEFB 0x048001 +#define RPI_TAG_BLANKSCR 0x040002 #define RPI_TAG_SETFBPHYS 0x048003 #define RPI_TAG_SETFBVIRT 0x048004 #define RPI_TAG_SETFBDEPTH 0x048005 -struct rpi_tag_getmodel { - uint32_t id, size, res; - uint32_t model; -}; - -struct rpi_tag_getram { - uint32_t id, size, res; - uint32_t membase, memsize; +struct rpi_prop_header { + uint32_t size; + uint32_t res; }; -struct rpi_tag_setclock { +struct rpi_prop { uint32_t id, size, res; - uint32_t clock_id, rate, skip_turbo; + uint32_t data[1]; }; -struct rpi_prop_header { - uint32_t size; - uint32_t res; -}; +#define RPI_PROP_NEXT(p) \ + ((struct rpi_prop*)((char*)((p) + 1) + ((p)->size - sizeof (p)->data))) extern int rpi_model; extern uint32_t rpi_iobase; extern uint32_t rpi_memsize, rpi_vc_memsize; void rpi_init(void); +void rpi_reboot(void) __attribute__((noreturn)); void rpi_mbox_send(int chan, uint32_t msg); uint32_t rpi_mbox_recv(int chan); diff --git a/src/video.c b/src/video.c index 9b552dc..cd3533a 100644 --- a/src/video.c +++ b/src/video.c @@ -5,14 +5,115 @@ #include "rpi.h" #include "video.h" #include "mem.h" +#include "debug.h" /* needs to by 16-byte aligned, because the address we send over the mailbox * interface, will have its 4 least significant bits masked off and taken over * by the mailbox id */ -static uint8_t propbuf[64] __attribute__((aligned(16))); +static char propbuf[256] __attribute__((aligned(16))); + +static void *fb_pixels; +static int fb_width, fb_height, fb_depth, fb_size; int video_init(void) { + int i; + struct rpi_prop_header *hdr = (struct rpi_prop_header*)propbuf; + struct rpi_prop *prop = (struct rpi_prop*)(hdr + 1); + + hdr->size = sizeof propbuf; + hdr->res = 0; + + fb_width = 1024; + fb_height = 600; + fb_depth = 32; + + prop->id = RPI_TAG_SETFBPHYS; + prop->size = 8; + prop->res = 0; + prop->data[0] = fb_width; + prop->data[1] = fb_height; + prop = RPI_PROP_NEXT(prop); + + prop->id = RPI_TAG_SETFBVIRT; + prop->size = 8; + prop->res = 0; + prop->data[0] = fb_width; + prop->data[1] = fb_height; + prop = RPI_PROP_NEXT(prop); + + prop->id = RPI_TAG_SETFBDEPTH; + prop->size = 4; + prop->res = 0; + prop->data[0] = fb_depth; + prop = RPI_PROP_NEXT(prop); + + prop->id = RPI_TAG_ALLOCFB; + prop->size = 4; + prop->res = 0; + prop->data[0] = 4; /* alignment */ + prop = RPI_PROP_NEXT(prop); + + prop->id = 0; + prop->size = 0; + prop->res = 0; + prop = RPI_PROP_NEXT(prop); + + printf("Requesting video mode: %dx%d (%d bpp)\n", fb_width, fb_height, fb_depth); + + rpi_mbox_send(RPI_MBOX_PROP, RPI_MEM_BUS_COHERENT(propbuf)); + while(rpi_mbox_recv(RPI_MBOX_PROP) != RPI_MEM_BUS_COHERENT(propbuf)); + + hexdump(propbuf, sizeof propbuf); + + if(hdr->res != 0x80000000) { + printf("Request failed, error: %x\n", hdr->res); + return -1; + } + + prop = (struct rpi_prop*)(hdr + 1); + while(prop->id) { + prop->size = prop->res & 0x7fffffff; + + switch(prop->id) { + case RPI_TAG_SETFBPHYS: + printf("setfbphys"); + break; + + case RPI_TAG_SETFBVIRT: + printf("setfbvirt"); + fb_width = prop->data[0]; + fb_height = prop->data[1]; + break; + + case RPI_TAG_SETFBDEPTH: + printf("setfbdepth"); + fb_depth = prop->data[0]; + break; + + case RPI_TAG_ALLOCFB: + printf("allocfb"); + fb_pixels = (void*)prop->data[0]; + fb_size = prop->data[1]; + break; + + default: + printf("tag %x", prop->id); + break; + } + + printf(" %08x (%u bytes):", prop->res, prop->size); + for(i=0; isize / 4; i++) { + printf(" %u", prop->data[i]); + } + putchar('\n'); + prop = RPI_PROP_NEXT(prop); + } + + printf("Got video mode: %dx%d (%d bpp) at %p (%d bytes)\n", fb_width, fb_height, + fb_depth, fb_pixels, fb_size); + + memset(fb_pixels, 0, fb_size); return 0; } -- 1.7.10.4