Example #1
0
static int
init_device(struct sbd_context *st)
{
	struct sector_header_s	*s_header;
	struct sector_node_s	*s_node;
	struct sector_mbox_s	*s_mbox;
	struct stat 		s;
	char			uuid[37];
	int			i;
	int			rc = 0;

	s_header = sector_alloc();
	s_node = sector_alloc();
	s_mbox = sector_alloc();
	memcpy(s_header->magic, sbd_magic, sizeof(s_header->magic));
	s_header->version = sbd_version;
	s_header->slots = 255;
	s_header->sector_size = sector_size;
	s_header->timeout_watchdog = timeout_watchdog;
	s_header->timeout_allocate = timeout_allocate;
	s_header->timeout_loop = timeout_loop;
	s_header->timeout_msgwait = timeout_msgwait;

	s_header->minor_version = 1;
	uuid_generate(s_header->uuid);
	uuid_unparse_lower(s_header->uuid, uuid);

	fstat(st->devfd, &s);
	/* printf("st_size = %ld, st_blksize = %ld, st_blocks = %ld\n",
			s.st_size, s.st_blksize, s.st_blocks); */

	cl_log(LOG_INFO, "Creating version %d.%d header on device %d (uuid: %s)",
			s_header->version, s_header->minor_version,
			st->devfd, uuid);
	fprintf(stdout, "Creating version %d.%d header on device %d (uuid: %s)\n",
			s_header->version, s_header->minor_version,
			st->devfd, uuid);
	if (header_write(st, s_header) < 0) {
		rc = -1; goto out;
	}
	cl_log(LOG_INFO, "Initializing %d slots on device %d",
			s_header->slots,
			st->devfd);
	fprintf(stdout, "Initializing %d slots on device %d\n",
			s_header->slots,
			st->devfd);
	for (i=0;i < s_header->slots;i++) {
		if (slot_write(st, i, s_node) < 0) {
			rc = -1; goto out;
		}
		if (mbox_write(st, i, s_mbox) < 0) {
			rc = -1; goto out;
		}
	}

out:	free(s_node);
	free(s_header);
	free(s_mbox);
	return(rc);
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
0
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;
}
Example #5
0
static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28)
{
	int rc;

	struct vc_mailbox *mailbox = dev_get_drvdata(dev);
	device_lock(dev);
	rc = mbox_write(mailbox, chan, data28);
	device_unlock(dev);

	return rc;
}
Example #6
0
int main()
{
  atexit(cleanup);
  mbox_create();
  mbox_read(STDIN_FILENO);

  for(;;)
    {
      mbox_write();
      mbox_log();
    }
}
Example #7
0
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);
    }
  }
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
0
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;
}