Exemple #1
0
void
avr_register_io_write(
		avr_t *avr,
		avr_io_addr_t addr,
		avr_io_write_t writep,
		void * param)
{
	avr_io_addr_t a = AVR_DATA_TO_IO(addr);

	if (a >= MAX_IOs) {
		AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): IO address 0x%04x out of range (max 0x%04x).\n",
					a, MAX_IOs);
		abort();
	}
	/*
	 * Verifying that some other piece of code is not installed to watch write
	 * on this address. If there is, this code installs a "dispatcher" callback
	 * instead to handle multiple clients, otherwise, it continues as usual
	 */
	if (avr->io[a].w.param || avr->io[a].w.c) {
		if (avr->io[a].w.param != param || avr->io[a].w.c != writep) {
			// if the muxer not already installed, allocate a new slot
			if (avr->io[a].w.c != _avr_io_mux_write) {
				int no = avr->io_shared_io_count++;
				if (avr->io_shared_io_count > 4) {
					AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many shared IO registers.\n");
					abort();
				}
				AVR_LOG(avr, LOG_TRACE, "IO: avr_register_io_write(%04x): Installing muxer on register.\n", addr);
				avr->io_shared_io[no].used = 1;
				avr->io_shared_io[no].io[0].param = avr->io[a].w.param;
				avr->io_shared_io[no].io[0].c = avr->io[a].w.c;
				avr->io[a].w.param = (void*)(intptr_t)no;
				avr->io[a].w.c = _avr_io_mux_write;
			}
			int no = (intptr_t)avr->io[a].w.param;
			int d = avr->io_shared_io[no].used++;
			if (avr->io_shared_io[no].used > 4) {
				AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many callbacks on %04x.\n", addr);
				abort();
			}
			avr->io_shared_io[no].io[d].param = param;
			avr->io_shared_io[no].io[d].c = writep;
			return;
		}
	}

	avr->io[a].w.param = param;
	avr->io[a].w.c = writep;
}
Exemple #2
0
void
avr_register_io_read(
		avr_t *avr,
		avr_io_addr_t addr,
		avr_io_read_t readp,
		void * param)
{
	avr_io_addr_t a = AVR_DATA_TO_IO(addr);
	if (avr->io[a].r.param || avr->io[a].r.c) {
		if (avr->io[a].r.param != param || avr->io[a].r.c != readp) {
			AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(): Already registered, refusing to override.\n");
			AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(%04x : %p/%p): %p/%p\n", a,
					avr->io[a].r.c, avr->io[a].r.param, readp, param);
			abort();
		}
	}
	avr->io[a].r.param = param;
	avr->io[a].r.c = readp;
}
Exemple #3
0
avr_irq_t *
avr_iomem_getirq(
		avr_t * avr,
		avr_io_addr_t addr,
		const char * name,
		int index)
{
	if (index > 8)
		return NULL;
	avr_io_addr_t a = AVR_DATA_TO_IO(addr);
	if (avr->io[a].irq == NULL) {
		/*
		 * Prepare an array of names for the io IRQs. Ideally we'd love to have
		 * a proper name for these, but it's not possible at this time.
		 */
		char names[9 * 20];
		char * d = names;
		const char * namep[9];
		for (int ni = 0; ni < 9; ni++) {
			if (ni < 8)
				sprintf(d, "=avr.io%04x.%d", addr, ni);
			else
				sprintf(d, "8=avr.io%04x.all", addr);
			namep[ni] = d;
			d += strlen(d) + 1;
		}
		avr->io[a].irq = avr_alloc_irq(&avr->irq_pool, 0, 9, namep);
		// mark the pin ones as filtered, so they only are raised when changing
		for (int i = 0; i < 8; i++)
			avr->io[a].irq[i].flags |= IRQ_FLAG_FILTERED;
	}
	// if given a name, replace the default one...
	if (name) {
		int l = strlen(name);
		char n[l + 10];
		sprintf(n, "avr.io.%s", name);
		free((void*)avr->io[a].irq[index].name);
		avr->io[a].irq[index].name = strdup(n);
	}
	return avr->io[a].irq + index;
}
Exemple #4
0
/*
 * Set a register (r < 256)
 * if it's an IO register (> 31) also (try to) call any callback that was
 * registered to track changes to that register.
 */
static inline void _avr_set_r(avr_t * avr, uint8_t r, uint8_t v)
{
	REG_TOUCH(avr, r);

	if (r == R_SREG) {
		avr->data[R_SREG] = v;
		// unsplit the SREG
		SET_SREG_FROM(avr, v);
		SREG();
	}
	if (r > 31) {
		uint8_t io = AVR_DATA_TO_IO(r);
		if (avr->io[io].w.c)
			avr->io[io].w.c(avr, r, v, avr->io[io].w.param);
		else
			avr->data[r] = v;
		if (avr->io[io].irq) {
			avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
			for (int i = 0; i < 8; i++)
				avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);				
		}