Exemple #1
0
int dma_pulse_DRQ(int ch, Bit8u * buf)
{
    int ret = DMA_DACK;
    if (MASKED(DI(ch), CI(ch))) {
	q_printf("DMA: channel %i masked, DRQ ignored\n", ch);
	ret = DMA_NO_DACK;
    }
    if ((dma[DI(ch)].status & 0xf0) || dma[DI(ch)].request) {
	error("DMA: channel %i already active! (m=%#x s=%#x r=%#x)\n",
	      ch, dma[DI(ch)].chans[CI(ch)].mode, dma[DI(ch)].status,
	      dma[DI(ch)].request);
	ret = DMA_NO_DACK;
    }
#if 0
    q_printf("DMA: pulse DRQ on channel %d\n", ch);
#endif
    if (ret == DMA_DACK) {
	DMA_LOCK();
	dma[DI(ch)].status |= 1 << (CI(ch) + 4);
	memcpy(dma_data_bus, buf, 1 << DI(ch));
	dma_run_channel(DI(ch), CI(ch));
	memcpy(buf, dma_data_bus, 1 << DI(ch));
	DMA_UNLOCK();
    } else {
	memset(buf, 0xff, 1 << DI(ch));
    }
    return ret;
}
Exemple #2
0
static void dma_process_channel(int dma_idx, int chan_idx)
{
    struct dma_channel *chan = &dma[dma_idx].chans[chan_idx];
    void *addr = physaddr_to_unixaddr(
	    (chan->page << 16) | (chan->cur_addr.value << dma_idx));

    /* first, do the transfer */
    switch (DMA_TRANSFER_OP(chan->mode)) {
    case VERIFY:
	q_printf("DMA: verify mode does nothing\n");
	break;
    case WRITE:
	memcpy(addr, dma_data_bus, 1 << dma_idx);
	break;
    case READ:
	memcpy(dma_data_bus, addr, 1 << dma_idx);
	break;
    case INVALID:
	q_printf("DMA: invalid mode does nothing\n");
	break;
    }

    /* now advance the address */
    if ((dma[dma_idx].command & 3) != 3)
	chan->cur_addr.value += (DMA_ADDR_DEC(chan->mode) ? -1 : 1);

    /* and the counter */
    chan->cur_count.value--;
    if (chan->cur_count.value == 0xffff) {	/* overflow */
	if (DMA_AUTOINIT(chan->mode)) {
	    q_printf("DMA: controller %i, channel %i reinitialized\n",
		     dma_idx, chan_idx);
	    chan->cur_addr.value = chan->base_addr.value;
	    chan->cur_count.value = chan->base_count.value;
	} else {		/* TC */
	    q_printf("DMA: controller %i, channel %i TC\n", dma_idx,
		     chan_idx);
	    dma[dma_idx].status |= 1 << chan_idx;
	    dma[dma_idx].request &= ~(1 << chan_idx);
	    /* the datasheet says it gets automatically masked too */
	    dma[dma_idx].mask |= 1 << chan_idx;
	}
    }
}
Exemple #3
0
static void dma_process_channel(int dma_idx, int chan_idx)
{
    struct dma_channel *chan = &dma[dma_idx].chans[chan_idx];
    Bit32u addr = (chan->page << 16) | (chan->cur_addr.value << dma_idx);
    Bit8u mode = chan->mode;

    /* first, do the transfer */
    switch (mode & 3) {
    case 0:			/* verify */
	q_printf("DMA: verify mode does nothing\n");
	break;
    case 1:			/* write */
	MEMCPY_2DOS(addr, dma_data_bus, 1 << dma_idx);
	break;
    case 2:			/* read */
	MEMCPY_2UNIX(dma_data_bus, addr, 1 << dma_idx);
	break;
    case 3:			/* invalid */
	q_printf("DMA: invalid mode does nothing\n");
	break;
    }

    /* now advance the address */
    if (!(dma[dma_idx].command & 2))
	chan->cur_addr.value += (mode & 8) ? -1 : 1;

    /* and the counter */
    chan->cur_count.value--;
    if (chan->cur_count.value == 0xffff) {	/* overflow */
	if (mode & 4) {		/* auto-init */
	    q_printf("DMA: controller %i, channel %i reinitialized\n",
		     dma_idx, chan_idx);
	    chan->cur_addr.value = chan->base_addr.value;
	    chan->cur_count.value = chan->base_count.value;
	} else {		/* eop */
	    q_printf("DMA: controller %i, channel %i EOP\n", dma_idx,
		     chan_idx);
	    dma[dma_idx].status |= 1 << chan_idx;
	    dma[dma_idx].request &= ~(1 << chan_idx);
	    /* the datasheet says it gets automatically masked too */
	    dma[dma_idx].mask |= 1 << chan_idx;
	}
    }
}
Exemple #4
0
static void dma_soft_reset(int dma_idx)
{
    dma[dma_idx].command = 0;
    dma[dma_idx].status = 0;
    dma[dma_idx].request = 0;
    dma[dma_idx].tmp_reg = 0;
    dma[dma_idx].ff = 0;
    dma[dma_idx].mask = 0x0f;
    q_printf("DMA: Soft Reset on controller %i\n", dma_idx);
}
Exemple #5
0
void dma_init(void)
{
    emu_iodev_t io_device;

    /* 8237 DMA controller */
    io_device.read_portb = dma_io_read;
    io_device.write_portb = dma_io_write;
    io_device.read_portw = NULL;
    io_device.write_portw = NULL;
    io_device.read_portd = NULL;
    io_device.write_portd = NULL;
    io_device.irq = EMU_NO_IRQ;
    io_device.fd = -1;

    /*
     * XT Controller
     */
    io_device.start_addr = 0x0000;
    io_device.end_addr = 0x000F;
    io_device.handler_name = "DMA - XT Controller";
    port_register_handler(io_device, 0);

    /*
     * Page Registers (XT)
     */
    io_device.start_addr = 0x0081;
    io_device.end_addr = 0x0087;
    io_device.handler_name = "DMA - XT Pages";
    port_register_handler(io_device, 0);

    /*
     * AT Controller
     */
    io_device.start_addr = 0x00C0;
    io_device.end_addr = 0x00DE;
    io_device.handler_name = "DMA - AT Controller";
    port_register_handler(io_device, 0);

    /*
     * Page Registers (AT)
     */
    io_device.start_addr = 0x0089;
    io_device.end_addr = 0x008F;
    io_device.handler_name = "DMA - AT Pages";
    port_register_handler(io_device, 0);

    q_printf("DMA: DMA Controller initialized - 8 & 16 bit modes\n");
}
Exemple #6
0
static void dma_run_channel(int dma_idx, int chan_idx)
{
    int done = 0;
    long ticks = 0;
    while (!done &&
	   (HAVE_DRQ(dma_idx, chan_idx) || SW_ACTIVE(dma_idx, chan_idx))) {
	if (!MASKED(dma_idx, chan_idx) &&
	    !REACHED_TC(dma_idx, chan_idx) &&
	    !(dma[dma_idx].command & 4) &&
	    (DMA_TRANSFER_MODE(dma[dma_idx].chans[chan_idx].mode) != CASCADE)) {
	    dma_process_channel(dma_idx, chan_idx);
	    ticks++;
	} else {
	    done = 1;
	}
	dma_update_DRQ(dma_idx, chan_idx);
    }
    if (ticks > 1)
	q_printf("DMA: processed %lu (left %u) cycles on controller %i channel %i\n",
	     ticks, dma[dma_idx].chans[chan_idx].cur_count.value, dma_idx,
	     chan_idx);
}
Exemple #7
0
static void dma_io_write(ioport_t port, Bit8u value)
{
    switch (port) {

#define HANDLE_ADDR_WRITE(d_n, c_n) \
    case DMA##d_n##_ADDR_##c_n: \
	dma[d(d_n)].chans[d(c_n)].base_addr.byte[dma[d(d_n)].ff] = value; \
	dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff] = value; \
        q_printf("DMA%i: addr write: %#x to Channel %d byte %d\n", \
		d_n, value, d(c_n), dma[d(d_n)].ff); \
	dma[d(d_n)].ff ^= 1; \
	break
	HANDLE_X(ADDR_WRITE);

#define HANDLE_CNT_WRITE(d_n, c_n) \
    case DMA##d_n##_CNT_##c_n: \
	dma[d(d_n)].chans[d(c_n)].base_count.byte[dma[d(d_n)].ff] = value; \
	dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff] = value; \
	q_printf("DMA%i: count write: %#x to Channel %d byte %d\n", \
		d_n, value, d(c_n), dma[d(d_n)].ff); \
	dma[d(d_n)].ff ^= 1; \
	break
	HANDLE_X(CNT_WRITE);

#define HANDLE_PAGE_WRITE(d_n, c_n) \
    case DMA##d_n##_PAGE_##c_n: \
	dma[d(d_n)].chans[d(c_n)].page = value; \
	q_printf("DMA%i: page write: %#x to Channel %d\n", \
		d_n, value, d(c_n)); \
	break
	HANDLE_X(PAGE_WRITE);

    case DMA1_MASK_REG:
	if (value & 4) {
	    q_printf("DMA1: mask channel %i\n", value & 3);
	    dma[DMA1].mask |= 1 << (value & 3);
	} else {
	    q_printf("DMA1: unmask channel %i\n", value & 3);
	    dma[DMA1].mask &= ~(1 << (value & 3));
	    dma[DMA1].status &= ~(1 << (value & 3));
	}
	break;
    case DMA2_MASK_REG:
	if (value & 4) {
	    q_printf("DMA2: mask channel %i\n", value & 3);
	    dma[DMA2].mask |= 1 << (value & 3);
	} else {
	    q_printf("DMA2: unmask channel %i\n", value & 3);
	    dma[DMA2].mask &= ~(1 << (value & 3));
	    dma[DMA2].status &= ~(1 << (value & 3));
	}
	break;

    case DMA1_MODE_REG:
	dma[DMA1].chans[value & 3].mode = value >> 2;
	q_printf("DMA1: Write mode 0x%x to Channel %u\n", value >> 2,
		 value & 3);
	break;
    case DMA2_MODE_REG:
	dma[DMA2].chans[value & 3].mode = value >> 2;
	q_printf("DMA2: Write mode 0x%x to Channel %u\n", value >> 2,
		 value & 3);
	break;

    case DMA1_CMD_REG:
	dma[DMA1].command = value;
	q_printf("DMA1: Write 0x%x to Command reg\n", value);
	break;
    case DMA2_CMD_REG:
	dma[DMA2].command = value;
	q_printf("DMA2: Write 0x%x to Command reg\n", value);
	break;

    case DMA1_CLEAR_FF_REG:
	q_printf("DMA1: Clearing Output Flip-Flop\n");
	dma[DMA1].ff = 0;
	break;
    case DMA2_CLEAR_FF_REG:
	q_printf("DMA2: Clearing Output Flip-Flop\n");
	dma[DMA2].ff = 0;
	break;

    case DMA1_RESET_REG:
	q_printf("DMA1: Reset\n");
	dma_soft_reset(DMA1);
	break;
    case DMA2_RESET_REG:
	q_printf("DMA2: Reset\n");
	dma_soft_reset(DMA2);
	break;

    case DMA1_REQ_REG:
	if (value & 4) {
	    q_printf("DMA1: Setting request state %#x\n", value);
	    dma[DMA1].request |= 1 << (value & 3);
	} else {
	    q_printf("DMA1: Clearing request state %#x\n", value);
	    dma[DMA1].request &= ~(1 << (value & 3));
	}
	break;
    case DMA2_REQ_REG:
	if (value & 4) {
	    q_printf("DMA2: Setting request state %#x\n", value);
	    dma[DMA2].request |= 1 << (value & 3);
	} else {
	    q_printf("DMA2: Clearing request state %#x\n", value);
	    dma[DMA2].request &= ~(1 << (value & 3));
	}
	break;

    case DMA1_CLR_MASK_REG:
	q_printf("DMA1: Clearing masks\n");
	dma[DMA1].mask = 0;
	dma[DMA1].status &= 0xf0;
	break;
    case DMA2_CLR_MASK_REG:
	q_printf("DMA2: Clearing masks\n");
	dma[DMA2].mask = 0;
	dma[DMA2].status &= 0xf0;
	break;

    case DMA1_MASK_ALL_REG:
	q_printf("DMA1: Setting masks %#x\n", value);
	dma[DMA1].mask = value;
	dma[DMA1].status &= 0xf0;
	break;
    case DMA2_MASK_ALL_REG:
	q_printf("DMA2: Setting masks %#x\n", value);
	dma[DMA2].mask = value;
	dma[DMA2].status &= 0xf0;
	break;

    default:
	q_printf("DMA: Unhandled Write on 0x%04x\n", (Bit16u) port);
    }

    dma_process();		// Not needed in fact
}
Exemple #8
0
static Bit8u dma_io_read(ioport_t port)
{
    Bit8u r = 0xff;
    switch (port) {

#define HANDLE_CUR_ADDR_READ(d_n, c_n) \
    case DMA##d_n##_ADDR_##c_n: \
	r = dma[d(d_n)].chans[d(c_n)].cur_addr.byte[dma[d(d_n)].ff]; \
	q_printf("DMA%i: cur_addr read: %#x from Channel %d byte %d\n", \
		d_n, r, d(c_n), dma[d(d_n)].ff); \
	dma[d(d_n)].ff ^= 1; \
	break
	HANDLE_X(CUR_ADDR_READ);

#define HANDLE_CUR_CNT_READ(d_n, c_n) \
    case DMA##d_n##_CNT_##c_n: \
	r = dma[d(d_n)].chans[d(c_n)].cur_count.byte[dma[d(d_n)].ff]; \
	q_printf("DMA%i: cur_cnt read: %#x from Channel %d byte %d\n", \
		d_n, r, d(c_n), dma[d(d_n)].ff); \
	dma[d(d_n)].ff ^= 1; \
	break
	HANDLE_X(CUR_CNT_READ);

#define HANDLE_PAGE_READ(d_n, c_n) \
    case DMA##d_n##_PAGE_##c_n: \
	r = dma[d(d_n)].chans[d(c_n)].page; \
	q_printf("DMA%i: page read: %#x from Channel %d\n", \
		d_n, r, d(c_n)); \
	break
	HANDLE_X(PAGE_READ);

    case DMA1_STAT_REG:
	r = dma[DMA1].status;
	q_printf("DMA1: Read %u from Status reg\n", r);
	dma[DMA1].status &= 0xf0;	/* clear status bits */
	break;
    case DMA2_STAT_REG:
	r = dma[DMA2].status;
	q_printf("DMA2: Read %u from Status reg\n", r);
	dma[DMA2].status &= 0xf0;	/* clear status bits */
	break;

    case DMA1_TEMP_REG:
	r = dma[DMA1].tmp_reg;
	q_printf("DMA1: Read %u from temporary register unimplemented\n",
		 r);
	break;
    case DMA2_TEMP_REG:
	r = dma[DMA2].tmp_reg;
	q_printf("DMA2: Read %u from temporary register unimplemented\n",
		 r);
	break;

    default:
	q_printf("DMA: Unhandled Read on 0x%04x\n", (Bit16u) port);
    }

    dma_process();		// Not needed in fact

    return r;
}
Exemple #9
0
int main(int argc, char *argv[]) {
  /* test harness */
  int tests_passed = 0;
  int tests_failed = 0;

  /* create a queue with a size hint */
  printf("Creating queue\n");
  queue qp = q_create(20);

  /* how do we see if queue was propery initialized? */

  /* add and remove one element */
  int e1 = 42;

  q_add(qp, e1);
  printf("Test 1: ");
  q_printf(qp);
  printf("\n");

  /* length should have gone up by one */

  if ( q_length(qp) != 1 ) {
    printf("Test 1 failed, length %d should be 1\n", 
        q_length(qp));
    tests_failed++;
  }
  else {
    printf("Test 1 passed.\n");
    tests_passed++;
  }


  printf("Test 2: ");
  int e2 = q_remove(qp);
  q_printf(qp);
  printf("\n");

  if ( q_length(qp) != 0 ) {
    printf("Test 2.1 failed, length %d should be 0\n", 
        q_length(qp));
    tests_failed++;
  }
  else {
    printf("Test 2.1 passed.\n");
    tests_passed++;
  }

  if ( e1 != e2 ) {
    printf("Test 2.2 failed, e2 %d should equal e1 %d\n", 
        e2, e1);
    tests_failed++;
  }
  else {
    printf("Test 2.2 passed.\n");
    tests_passed++;
  }

  printf("Test 3: ");
  for (int i=1; i <= 10; i++) {
    q_add(qp, i);
  }
  q_printf(qp);
  printf("\n");
  for (int i=1; i<= 10; i++) {
    e1 = q_remove(qp);
    if ( q_length(qp) != 10-i ) {
      printf("Test 3.1 failed, length %d should be %d\n",
          q_length(qp), 10-i);
      tests_failed++;
    }
    else {
      tests_passed++;
    }
    if ( e1 != i ) {
      printf("Test 3.2 failed, element %d should be %d\n",
          e1, i);
      tests_failed++;
    }
    else {
      tests_passed++;
    }
  }


  printf("Test 4: ");
  for (int i=1; i <= 10; i++) {
    q_add(qp, i);
  }

  q_printf(qp);
  printf("\n");

  for (int i=0; i < 10; i++) {
    int expected = i + 1;
    int actual = q_get_item(qp, i);
    if(expected != actual) {
      printf("Test 4 failed, element #%d should be %d but was %d\n",
          i, expected, actual);
      tests_failed++;
    } else {
      tests_passed++;
    }
  }

  // Reset to empty
  for (int i=1; i <= 10; i++) {
    q_remove(qp);
  }

  q_add(qp, e1);
  printf("Test 5.1: ");
  q_printf(qp);
  printf("\n");

  /* length should have gone up by one */

  if ( q_length(qp) != 1 ) {
    printf("Test 5.1 failed, length %d should be 1 before deletion\n", 
        q_length(qp));
    tests_failed++;
  }
  else {
    int actual = q_delete_item(qp, 0);
    if( q_length(qp) != 0) {
      printf("Test 5.1 failed, length %d should be 0 after deletion\n", 
          q_length(qp));
      tests_failed++;
    } else if(actual != e1) {
      printf("Test 5.1 failed, element retrieved from deleted: Expected: %d; Actual: %d\n", 
          e1, actual);
      tests_failed++;
    } else {
      printf("Test 5.1 passed.\n");
      tests_passed++;
    }
  }

  printf("Test 5.2: ");
  for (int i=1; i <= 10; i++) {
    q_add(qp, i);
  }

  q_printf(qp);
  printf("\n");

  int deletedElement;

  deletedElement = q_delete_item(qp, 4);
  if(deletedElement != 5) {
    printf("Test 5.2 failed, element retrieved from deleted: Expected: 5; Actual: %d\n", 
        deletedElement);
    tests_failed++;
  }

  deletedElement = q_delete_item(qp, 4);
  if(deletedElement != 6) {
    printf("Test 5.2 failed, element retrieved from deleted: Expected: 6; Actual: %d\n", 
        deletedElement);
    tests_failed++;
  }

  q_printf(qp);
  printf("\n");

  if( q_length(qp) != 8) {
    printf("Test 5.2 failed, length %d should be 8 after deletion\n", 
        q_length(qp));
    tests_failed++;
  } else {
    if(q_get_item(qp, 4) != 7) {
      printf("Test 5.2 failed, value of element at index 4 after deletion: Expected: 7; Actual: %d\n", q_get_item(qp, 4));
      tests_failed++;
    } else {
      printf("Test 5.2 passed.\n");
      tests_passed++;
    }
  }

  /* a fatal test */
  if ( 0 ) {
    printf("Test 4: remove on empty queue\n");
    e2 = q_remove(qp);
    tests_failed++;
  }

  printf("Tests Passed: %d\n", tests_passed);
  printf("Tests Failed: %d\n", tests_failed);
}