- implemented video mode setting with the property tags, and once again it only
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 12 Nov 2020 18:01:32 +0000 (20:01 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 12 Nov 2020 18:01:32 +0000 (20:01 +0200)
  works in the emulator
- added hexdump function for debugging
- added reboot function using the watchdog timer

src/debug.c [new file with mode: 0644]
src/debug.h [new file with mode: 0644]
src/main.c
src/mem.h
src/rpi.c
src/rpi.h
src/video.c

diff --git a/src/debug.c b/src/debug.c
new file mode 100644 (file)
index 0000000..241b147
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <ctype.h>
+#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<nlines; i++) {
+               printf("%08x  ", (uint32_t)ptr);
+
+               for(j=0; j<16; j++) {
+                       if(ptr + j < end) {
+                               printf("%02x ", ptr[j]);
+                       } else {
+                               printf("   ");
+                       }
+                       if((j & 7) == 7) putchar(' ');
+               }
+
+               putchar('|');
+               for(j=0; j<16; j++) {
+                       if(ptr + j < end) {
+                               putchar(isprint(ptr[j]) ? ptr[j] : '.');
+                       } else {
+                               putchar(' ');
+                       }
+               }
+               printf("|\n");
+
+               ptr += 16;
+       }
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644 (file)
index 0000000..654d876
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+void hexdump(void *start, int nbytes);
+
+#endif /* DEBUG_H_ */
index db2ab86..29c0f14 100644 (file)
@@ -12,6 +12,8 @@
 
 void dbgled(int x);
 
+void reboot(void);
+
 static void cmdrun(char *cmd);
 
 int main(void)
@@ -61,6 +63,12 @@ int main(void)
        return 0;
 }
 
+void reboot(void)
+{
+       printf("Rebooting ...\n");
+       rpi_reboot();
+}
+
 static void cmdrun(char *cmd)
 {
        char *ptr, *args;
@@ -71,7 +79,9 @@ static void cmdrun(char *cmd)
        *ptr = 0;
        args = ptr + 1;
 
-       if(strcmp(cmd, "help") == 0) {
+       if(strcmp(cmd, "reboot") == 0) {
+               reboot();
+       } else if(strcmp(cmd, "help") == 0) {
                printf("help not implemented yet\n");
        } else if(strcmp(cmd, "ver") == 0) {
                printf("rpikern version 0.0\n");
index 8285c05..d2961e2 100644 (file)
--- a/src/mem.h
+++ b/src/mem.h
@@ -1,7 +1,4 @@
 #ifndef MEM_H_
 #define MEM_H_
 
-#define MEM_BUS_COHERENT(addr) (((uint32_t)addr) | 0x40000000)
-#define MEM_BUS_UNCACHED(addr) (((uint32_t)addr) | 0xc0000000)
-
 #endif /* MEM_H_ */
index ba39596..0b2f298 100644 (file)
--- a/src/rpi.c
+++ b/src/rpi.c
 
 #define TMCTL_PRESCALER(x)     (((uint32_t)(x) & 0xff) << 16)
 
+/* watchdog */
+#define PM_RSTC_REG            IOREG(0x10001c)
+#define PM_WDOG_REG            IOREG(0x100024)
+
+#define PM_PASSWD                      0x5a000000
+#define PMRSTC_WRCFG_FULL_RESET        0x00000020
+#define PMRSTC_WRCFG_CLEAR             0xffffffcf
 
 /* MAILBOX */
 #define MBOX_READ_REG  IOREG(0xb880)
@@ -88,6 +95,12 @@ static int detect(void)
        return -1;
 }
 
+void rpi_reboot(void)
+{
+       PM_WDOG_REG = PM_PASSWD | 1;
+       PM_RSTC_REG = PM_PASSWD | (PM_RSTC_REG & PMRSTC_WRCFG_CLEAR) | PMRSTC_WRCFG_FULL_RESET;
+       for(;;) halt_cpu();
+}
 
 void rpi_mbox_send(int chan, uint32_t msg)
 {
index 36f8ac4..1ae7636 100644 (file)
--- a/src/rpi.h
+++ b/src/rpi.h
@@ -3,6 +3,11 @@
 
 #include <stdint.h>
 
+
+#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
 
 
 #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);
index 9b552dc..cd3533a 100644 (file)
 #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; i<prop->size / 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;
 }