+
+
+static struct {
+ int id, req_len, resp_len;
+} taginfo[] = {
+ {RPI_TAG_GETMODEL, 0, 4},
+ {RPI_TAG_GETREV, 0, 4},
+ {RPI_TAG_GETRAM, 0, 8},
+ {RPI_TAG_GETVRAM, 0, 8},
+ {RPI_TAG_SETCLOCK, 4, 8},
+ {RPI_TAG_ALLOCFB, 4, 8},
+ {RPI_TAG_RELEASEFB, 0, 0},
+ {RPI_TAG_BLANKSCR, 4, 4},
+ {RPI_TAG_SETFBPHYS, 8, 8},
+ {RPI_TAG_SETFBVIRT, 8, 8},
+ {RPI_TAG_SETFBDEPTH, 4, 4},
+ {RPI_TAG_GETFBPITCH, 0, 4},
+ {RPI_TAG_SETFBOFFS, 8, 8},
+ {RPI_TAG_GETFBOFFS, 0, 8},
+ {0, 0, 0}
+};
+
+void rpi_prop(int id, ...)
+{
+ int i, req_len = 0, resp_len = 0;
+ va_list ap;
+
+ if(!wrprop) {
+ wrprop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
+ }
+
+ for(i=0; taginfo[i].id; i++) {
+ if(taginfo[i].id == id) {
+ req_len = taginfo[i].req_len;
+ resp_len = taginfo[i].resp_len;
+ break;
+ }
+ }
+
+ wrprop->id = id;
+ wrprop->size = resp_len;
+ wrprop->res = 0;
+
+ va_start(ap, id);
+ for(i=0; i<resp_len >> 2; i++) {
+ if(i < req_len >> 2) {
+ wrprop->data[i] = va_arg(ap, uint32_t);
+ } else {
+ wrprop->data[i] = 0;
+ }
+ }
+ va_end(ap);
+
+ wrprop = RPI_PROP_NEXT(wrprop);
+}
+
+int rpi_prop_send(void)
+{
+ struct rpi_prop_header *hdr = (struct rpi_prop_header*)propbuf;
+ uint32_t addr = (uint32_t)propbuf;
+ uint32_t size;
+
+ /* terminate with null tag */
+ wrprop->id = 0;
+
+ size = (char*)wrprop - propbuf + 4;
+
+ hdr->size = (size + 15) & 0xfffffff0;
+ hdr->res = 0;
+
+ wrprop = rdprop = 0;
+
+ /* clean and invalidate cache, otherwise VC will see stale data */
+ sysctl_dcache_clean_inval(addr, hdr->size);
+
+ rpi_mbox_send(RPI_MBOX_PROP, addr);
+ while(rpi_mbox_recv(RPI_MBOX_PROP) != addr);
+
+ sysctl_dcache_clean_inval(addr, hdr->size);
+
+ if(hdr->res != 0x80000000) {
+ printf("Property request failed: %x\n", hdr->res);
+ return -1;
+ }
+ return 0;
+}
+
+struct rpi_prop *rpi_prop_next(void)
+{
+ struct rpi_prop *res;
+ if(!rdprop) {
+ rdprop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
+ }
+
+ if(rdprop->id == 0) {
+ res = rdprop = 0;
+ } else {
+ res = rdprop;
+ rdprop->size = rdprop->res & 0x7fffffff;
+ rdprop = RPI_PROP_NEXT(rdprop);
+ }
+ return res;
+}
+
+struct rpi_prop *rpi_prop_find(int id)
+{
+ struct rpi_prop *prop = (struct rpi_prop*)(propbuf + sizeof(struct rpi_prop_header));
+
+ while(prop->id) {
+ prop->size = prop->res & 0x7fffffff;
+ if(prop->id == id) {
+ return prop;
+ }
+ prop = RPI_PROP_NEXT(prop);
+ }
+ return 0;
+}