int GetMACAddress (unsigned char Buffer[6]) { unsigned int mb_addr = 0x40007000; // 0x7000 in L2 cache coherent mode volatile unsigned int *mailbuffer = (unsigned int *) mb_addr; /* Get the display size */ mailbuffer[0] = 8 * 4; // size of this message mailbuffer[1] = 0; // this is a request mailbuffer[2] = 0x00010003; // get MAC address tag mailbuffer[3] = 6; // value buffer size mailbuffer[4] = 0; // request/response mailbuffer[5] = 0; // space to return value mailbuffer[6] = 0; mailbuffer[7] = 0; mbox_write(MAIL_TAGS, mb_addr); mbox_read(MAIL_TAGS); if (mailbuffer[1] == MAIL_FULL) { volatile unsigned char *ptr = (unsigned char *)&mailbuffer[5]; Buffer[0] = ptr[0]; Buffer[1] = ptr[1]; Buffer[2] = ptr[2]; Buffer[3] = ptr[3]; Buffer[4] = ptr[4]; Buffer[5] = ptr[5]; return 1; } return 0; }
bool bcm2835_prop_get_memory(uint32_t *base, uint32_t *size) { bool ret; MBOX_BUFF_ALLOC(req, mbox_getmem_buf_t); req->buf_hdr.size = sizeof(mbox_getmem_buf_t); req->buf_hdr.code = MBOX_PROP_CODE_REQ; req->tag_hdr.tag_id = TAG_GET_ARM_MEMORY; req->tag_hdr.buf_size = sizeof(mbox_tag_getmem_resp_t); req->tag_hdr.val_len = 0; req->zero = 0; mbox_write((bcm2835_mbox_t *)BCM2835_MBOX0_ADDR, MBOX_CHAN_PROP_A2V, KA2VCA((uint32_t)req)); mbox_read((bcm2835_mbox_t *)BCM2835_MBOX0_ADDR, MBOX_CHAN_PROP_A2V); if (req->buf_hdr.code == MBOX_PROP_CODE_RESP_OK) { *base = req->data.base; *size = req->data.size; ret = true; } else { ret = false; } return ret; }
static int TryInitFb() { //Some (or even all?) of these memory barriers can probably be omitted safely MemoryBarrier(); //We need to put the frame buffer structure somewhere with the lower 4 bits zero. //2^22 is a convenient place not used by anything, and with sufficient alignment volatile struct Bcm2835FrameBuffer *fb = (volatile struct Bcm2835FrameBuffer *)(1 << 22); //See the comments for Bcm2835FrameBuffer fb->width = 640; fb->height = 480; fb->vwidth = fb->width; fb->vheight = fb->height; fb->pitch = 0; fb->depth = 24; fb->x = 0; fb->y = 0; fb->pointer = 0; fb->size = 0; MemoryBarrier(); mbox_write(ArmToVc((void *)fb)); //Tell the GPU the address of the structure //memory barrier is in the register read/write functions MemoryBarrier(); //also an explicit one we probably don't need uint32_t r = mbox_read(); //Wait for the GPU to respond, and get its response MemoryBarrier(); if (r){ //If r != 0, some kind of error occured WriteGpio(17); return -1; } if (!fb->pointer){ //if the frame buffer pointer is zero, an error occured WriteGpio(18); return -2; } //Set up our frame buffer information fbinfo.width = fb->width; fbinfo.height = fb->height; fbinfo.pitch = fb->pitch; fbinfo.pointer = (volatile unsigned char *)fb->pointer; //2^23 is just a convenient space not used by anything fbinfo.cb = (struct FrameBufferCharacter *)(1 << 23); fbinfo.line_pos = 0; fbinfo.charpix = (unsigned char *)chars_pixels; fbinfo.xoffs = 0; //It works in the x direction nicely (no overscanning) fbinfo.yoffs = CHAR_HEIGHT; //cope with overscanning by adding 1 char border fbinfo.cbwidth = fb->width / CHAR_WIDTH; fbinfo.cbheight = (fb->height / CHAR_HEIGHT) - 2; //add 1 char border at the top and bottom return 0; }
static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) { int rc; struct vc_mailbox *mailbox = dev_get_drvdata(dev); device_lock(dev); rc = mbox_read(mailbox, chan, data28); device_unlock(dev); return rc; }
int main() { atexit(cleanup); mbox_create(); mbox_read(STDIN_FILENO); for(;;) { mbox_write(); mbox_log(); } }
void main() { // set as output mmio32(GPIO_FSEL_ADDR + GPFSEL1_OFFS) |= (1<<LED_BIT_SET); mailbox[0] = 1024; mailbox[1] = 768; mailbox[2] = 1024; mailbox[3] = 768; mailbox[4] = 0; mailbox[5] = 16; mailbox[6] = 0; mailbox[7] = 0; mailbox[8] = 0; mailbox[9] = 0; mbox_write((uint32_t)mailbox); if(mbox_read()==0) { uint16_t* start = (uint16_t*)(mailbox[8]); if(start == 0) mmio32(GPIO_FSEL_ADDR + GPCLR0_OFFS) |= (1<<GPIO_PIN_OFFS); // switch on led uint16_t color = 0; uint32_t x = 0; uint32_t y = 0; while(1){ for(y=0; y < 768; ++y) { for(x=0; x < 1024; ++x) { start[y*1024+x] = color; } ++color; if(color > 65000) color = 0; } // switch on led mmio32(GPIO_FSEL_ADDR + GPCLR0_OFFS) |= (1<<GPIO_PIN_OFFS); // wait 1 delay_with_loop(WAIT_DELAY); // switch off led mmio32(GPIO_FSEL_ADDR + GPSET0_OFFS) |= (1<<GPIO_PIN_OFFS); // wait 2 delay_with_loop(WAIT_DELAY); } } }
bool bcm2835_fb_init(fb_properties_t *prop) { bcm2835_mbox_t *fb_mbox; bool ret = false; MBOX_BUFF_ALLOC(fb_desc, bcm2835_fb_desc_t); fb_mbox = (void *) km_map(BCM2835_MBOX0_ADDR, sizeof(bcm2835_mbox_t), PAGE_NOT_CACHEABLE); fb_desc->width = 640; fb_desc->height = 480; fb_desc->virt_width = fb_desc->width; fb_desc->virt_height = fb_desc->height; fb_desc->pitch = 0; /* Set by VC */ fb_desc->bpp = 16; fb_desc->x_offset = 0; fb_desc->y_offset = 0; fb_desc->addr = 0; /* Set by VC */ fb_desc->size = 0; /* Set by VC */ mbox_write(fb_mbox, MBOX_CHAN_FB, KA2VCA(fb_desc)); if (mbox_read(fb_mbox, MBOX_CHAN_FB)) { printf("BCM2835 framebuffer initialization failed\n"); goto out; } prop->addr = fb_desc->addr; prop->offset = 0; prop->x = fb_desc->width; prop->y = fb_desc->height; prop->scan = fb_desc->pitch; prop->visual = VISUAL_RGB_5_6_5_LE; printf("BCM2835 framebuffer at 0x%08x (%dx%d)\n", prop->addr, prop->x, prop->y); ret = true; out: km_unmap((uintptr_t)fb_mbox, sizeof(bcm2835_mbox_t)); return ret; }
static int slot_list(struct sbd_context *st) { struct sector_header_s *s_header = NULL; struct sector_node_s *s_node = NULL; struct sector_mbox_s *s_mbox = NULL; int i; int rc = 0; s_header = header_get(st); if (!s_header) { rc = -1; goto out; } s_node = sector_alloc(); s_mbox = sector_alloc(); for (i=0; i < s_header->slots; i++) { if (slot_read(st, i, s_node) < 0) { rc = -1; goto out; } if (s_node->in_use > 0) { if (mbox_read(st, i, s_mbox) < 0) { rc = -1; goto out; } printf("%d\t%s\t%s\t%s\n", i, s_node->name, char2cmd(s_mbox->cmd), s_mbox->from); } } out: free(s_node); free(s_header); free(s_mbox); return rc; }
int SetPowerStateOn (unsigned nDeviceId) { unsigned int mb_addr = 0x40007000; // 0x7000 in L2 cache coherent mode volatile unsigned int *mailbuffer = (unsigned int *) mb_addr; mailbuffer[0] = 8 * 4; // size of this message mailbuffer[1] = 0; // this is a request mailbuffer[2] = TAG_SET_POWER_STATE; mailbuffer[3] = 8; // value buffer size mailbuffer[4] = 8; // request/response mailbuffer[5] = PWR_USB_HCD_ID; // device id mailbuffer[6] = POWER_STATE_ON; // power state mailbuffer[7] = 0; mbox_write(MAIL_TAGS, mb_addr); mbox_read(MAIL_TAGS); if (mailbuffer[1] == MAIL_FULL) { return 1; } return 0; }
static int slot_ping(struct sbd_context *st, const char *name) { struct sector_header_s *s_header = NULL; struct sector_mbox_s *s_mbox = NULL; int mbox; int waited = 0; int rc = 0; if (!name) { cl_log(LOG_ERR, "slot_ping(): No recipient specified.\n"); rc = -1; goto out; } s_header = header_get(st); if (!s_header) { rc = -1; goto out; } if (strcmp(name, "LOCAL") == 0) { name = local_uname; } mbox = slot_lookup(st, s_header, name); if (mbox < 0) { cl_log(LOG_ERR, "slot_msg(): No slot found for %s.", name); rc = -1; goto out; } s_mbox = sector_alloc(); s_mbox->cmd = SBD_MSG_TEST; strncpy(s_mbox->from, local_uname, sizeof(s_mbox->from)-1); DBGLOG(LOG_DEBUG, "Pinging node %s", name); if (mbox_write(st, mbox, s_mbox) < -1) { rc = -1; goto out; } rc = -1; while (waited <= timeout_msgwait) { if (mbox_read(st, mbox, s_mbox) < 0) break; if (s_mbox->cmd != SBD_MSG_TEST) { rc = 0; break; } sleep(1); waited++; } if (rc == 0) { cl_log(LOG_DEBUG, "%s successfully pinged.", name); } else { cl_log(LOG_ERR, "%s failed to ping.", name); } out: free(s_mbox); free(s_header); return rc; }
int servant(const char *diskname, int mode, const void* argp) { struct sector_mbox_s *s_mbox = NULL; struct sector_node_s *s_node = NULL; struct sector_header_s *s_header = NULL; int mbox; int rc = 0; time_t t0, t1, latency; union sigval signal_value; sigset_t servant_masks; struct sbd_context *st; pid_t ppid; char uuid[37]; const struct servants_list_item *s = argp; if (!diskname) { cl_log(LOG_ERR, "Empty disk name %s.", diskname); return -1; } cl_log(LOG_INFO, "Servant starting for device %s", diskname); /* Block most of the signals */ sigfillset(&servant_masks); sigdelset(&servant_masks, SIGKILL); sigdelset(&servant_masks, SIGFPE); sigdelset(&servant_masks, SIGILL); sigdelset(&servant_masks, SIGSEGV); sigdelset(&servant_masks, SIGBUS); sigdelset(&servant_masks, SIGALRM); /* FIXME: check error */ sigprocmask(SIG_SETMASK, &servant_masks, NULL); atexit(servant_exit); servant_inform_parent = 1; st = open_device(diskname, LOG_WARNING); if (!st) { return -1; } s_header = header_get(st); if (!s_header) { cl_log(LOG_ERR, "Not a valid header on %s", diskname); return -1; } if (servant_check_timeout_inconsistent(s_header) < 0) { cl_log(LOG_ERR, "Timeouts on %s do not match first device", diskname); return -1; } if (s_header->minor_version > 0) { uuid_unparse_lower(s_header->uuid, uuid); cl_log(LOG_INFO, "Device %s uuid: %s", diskname, uuid); } mbox = slot_allocate(st, local_uname); if (mbox < 0) { cl_log(LOG_ERR, "No slot allocated, and automatic allocation failed for disk %s.", diskname); rc = -1; goto out; } s_node = sector_alloc(); if (slot_read(st, mbox, s_node) < 0) { cl_log(LOG_ERR, "Unable to read node entry on %s", diskname); exit(1); } DBGLOG(LOG_INFO, "Monitoring slot %d on disk %s", mbox, diskname); if (s_header->minor_version == 0) { set_proc_title("sbd: watcher: %s - slot: %d", diskname, mbox); } else { set_proc_title("sbd: watcher: %s - slot: %d - uuid: %s", diskname, mbox, uuid); } s_mbox = sector_alloc(); if (s->first_start) { if (mode > 0) { if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed during start-up in servant."); rc = -1; goto out; } if (s_mbox->cmd != SBD_MSG_EXIT && s_mbox->cmd != SBD_MSG_EMPTY) { /* Not a clean stop. Abort start-up */ cl_log(LOG_WARNING, "Found fencing message - aborting start-up. Manual intervention required!"); ppid = getppid(); sigqueue(ppid, SIG_EXITREQ, signal_value); rc = 0; goto out; } } DBGLOG(LOG_INFO, "First servant start - zeroing inbox"); memset(s_mbox, 0, sizeof(*s_mbox)); if (mbox_write(st, mbox, s_mbox) < 0) { rc = -1; goto out; } } memset(&signal_value, 0, sizeof(signal_value)); while (1) { struct sector_header_s *s_header_retry = NULL; struct sector_node_s *s_node_retry = NULL; t0 = time(NULL); sleep(timeout_loop); ppid = getppid(); if (ppid == 1) { /* Our parent died unexpectedly. Triggering * self-fence. */ do_reset(); } /* These attempts are, by definition, somewhat racy. If * the device is wiped out or corrupted between here and * us reading our mbox, there is nothing we can do about * that. But at least we tried. */ s_header_retry = header_get(st); if (!s_header_retry) { cl_log(LOG_ERR, "No longer found a valid header on %s", diskname); exit(1); } if (memcmp(s_header, s_header_retry, sizeof(*s_header)) != 0) { cl_log(LOG_ERR, "Header on %s changed since start-up!", diskname); exit(1); } free(s_header_retry); s_node_retry = sector_alloc(); if (slot_read(st, mbox, s_node_retry) < 0) { cl_log(LOG_ERR, "slot read failed in servant."); exit(1); } if (memcmp(s_node, s_node_retry, sizeof(*s_node)) != 0) { cl_log(LOG_ERR, "Node entry on %s changed since start-up!", diskname); exit(1); } free(s_node_retry); if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed in servant."); exit(1); } if (s_mbox->cmd > 0) { cl_log(LOG_INFO, "Received command %s from %s on disk %s", char2cmd(s_mbox->cmd), s_mbox->from, diskname); switch (s_mbox->cmd) { case SBD_MSG_TEST: memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); sigqueue(ppid, SIG_TEST, signal_value); break; case SBD_MSG_RESET: do_reset(); break; case SBD_MSG_OFF: do_off(); break; case SBD_MSG_EXIT: sigqueue(ppid, SIG_EXITREQ, signal_value); break; case SBD_MSG_CRASHDUMP: do_crashdump(); break; default: /* FIXME: An "unknown" message might result from a partial write. log it and clear the slot. */ cl_log(LOG_ERR, "Unknown message on disk %s", diskname); memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); break; } } sigqueue(ppid, SIG_LIVENESS, signal_value); t1 = time(NULL); latency = t1 - t0; if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) { cl_log(LOG_WARNING, "Latency: %d exceeded threshold %d on disk %s", (int)latency, (int)timeout_watchdog_warn, diskname); } else if (debug) { DBGLOG(LOG_INFO, "Latency: %d on disk %s", (int)latency, diskname); } } out: free(s_mbox); close_device(st); if (rc == 0) { servant_inform_parent = 0; } return rc; }