示例#1
0
static void rtl8139_resetrx(rtl8139 *rtl)
{
	rtl8139_stop(rtl);

	// reset the rx pointers
	RTL_WRITE_16(rtl, RT_RXBUFTAIL, TAIL_TO_TAILREG(0));
	RTL_WRITE_16(rtl, RT_RXBUFHEAD, 0);

	// start it back up
	RTL_WRITE_16(rtl, RT_INTRMASK, MYRT_INTS);

	// Enable RX/TX once more
	RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);
}
static void rtl8169_int(void* data)
{
    int rc = INT_NO_RESCHEDULE;
    rtl8169 *r = (rtl8169 *)data;
    uint16 istat;

    acquire_spinlock(&r->reg_spinlock);

    istat = RTL_READ_16(r, REG_ISR);
    SHOW_FLOW(3, "rtl8169_int: istat 0x%x\n", istat);
    if (istat == 0)
        goto done;

    if (istat & (IMR_ROK|IMR_RER|IMR_RDU|IMR_RXOVL)) {
        rc |= rtl8169_rxint(r, istat);
    }
    if (istat & (IMR_TOK|IMR_TER|IMR_TDU)) {
        rc |= rtl8169_txint(r, istat);
    }

    RTL_WRITE_16(r, REG_ISR, istat);

done:
    release_spinlock(&r->reg_spinlock);

    // TODO req reschedule if needed?
    (void) rc;
    //return rc;
}
示例#3
0
static int rtl8139_int(void* data)
{
	int rc = INT_NO_RESCHEDULE;
	rtl8139 *rtl = (rtl8139 *)data;

	acquire_spinlock(&rtl->reg_spinlock);

	// Disable interrupts
	RTL_WRITE_16(rtl, RT_INTRMASK, 0);

	for(;;) {
		uint16 status = RTL_READ_16(rtl, RT_INTRSTATUS);
		if(status)
			RTL_WRITE_16(rtl, RT_INTRSTATUS, status);
		else
			break;

		if(status & RT_INT_TX_OK || status & RT_INT_TX_ERR) {
			if(rtl8139_txint(rtl, status) == INT_RESCHEDULE)
				rc = INT_RESCHEDULE;
		}
		if(status & RT_INT_RX_ERR || status & RT_INT_RX_OK) {
			if(rtl8139_rxint(rtl, status) == INT_RESCHEDULE)
				rc = INT_RESCHEDULE;
		}
		if(status & RT_INT_RXBUF_OVERFLOW) {
			dprintf("RX buffer overflow!\n");
			dprintf("buf 0x%x, head 0x%x, tail 0x%x\n",
				RTL_READ_32(rtl, RT_RXBUF), RTL_READ_16(rtl, RT_RXBUFHEAD), RTL_READ_16(rtl, RT_RXBUFTAIL));
			RTL_WRITE_32(rtl, RT_RXMISSED, 0);
			RTL_WRITE_16(rtl, RT_RXBUFTAIL, TAIL_TO_TAILREG(RTL_READ_16(rtl, RT_RXBUFHEAD)));
		}
		if(status & RT_INT_RXFIFO_OVERFLOW) {
			dprintf("RX fifo overflow!\n");
		}
		if(status & RT_INT_RXFIFO_UNDERRUN) {
			dprintf("RX fifo underrun\n");
		}
	}

	// reenable interrupts
	RTL_WRITE_16(rtl, RT_INTRMASK, MYRT_INTS);

	release_spinlock(&rtl->reg_spinlock);

	return rc;
}
示例#4
0
static void rhine_resetrx(rhine *r)
{
	PANIC_UNIMPLEMENTED();
#if 0
	rhine_stop(r);

	// reset the rx pointers
	RTL_WRITE_16(r, RT_RXBUFTAIL, TAIL_TO_TAILREG(0));
	RTL_WRITE_16(r, RT_RXBUFHEAD, 0);

	// start it back up
	RTL_WRITE_16(r, RT_INTRMASK, MYRT_INTS);

	// Enable RX/TX once more
	RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);
#endif
}
示例#5
0
static void rhine_stop(rhine *r)
{
	PANIC_UNIMPLEMENTED();
#if 0
	// stop the rx and tx and mask all interrupts
	RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RESET);
	RTL_WRITE_16(r, RT_INTRMASK, 0);
#endif
}
示例#6
0
static int rhine_int(void* data)
{
	int rc = INT_NO_RESCHEDULE;
	rhine *r = (rhine *)data;
	uint16 istat;
	
	acquire_spinlock(&r->reg_spinlock);

	istat = RHINE_READ_16(r, RHINE_ISR0);
	dprintf("rhine_int: istat 0x%x\n", istat);	
	if (istat == 0)
		goto done;

	if (istat & 0x1) { 
		// packet received with no errors
		dprintf("packet received: status 0x%x, framelen 0x%x\n", 
				RXDESC(r, r->rx_head).status, RXDESC(r, r->rx_head).framelen);
		r->rx_head++;
	}
	
	RHINE_WRITE_16(r, RHINE_ISR0, istat);

#if 0
	// Disable interrupts
	RTL_WRITE_16(r, RT_INTRMASK, 0);

	for(;;) {
		uint16 status = RTL_READ_16(r, RT_INTRSTATUS);
		if(status)
			RTL_WRITE_16(r, RT_INTRSTATUS, status);
		else
			break;

		if(status & RT_INT_TX_OK || status & RT_INT_TX_ERR) {
			if(rhine_txint(r, status) == INT_RESCHEDULE)
				rc = INT_RESCHEDULE;
		}
		if(status & RT_INT_RX_ERR || status & RT_INT_RX_OK) {
			if(rhine_rxint(r, status) == INT_RESCHEDULE)
				rc = INT_RESCHEDULE;
		}
		if(status & RT_INT_RXBUF_OVERFLOW) {
			dprintf("RX buffer overflow!\n");
			dprintf("buf 0x%x, head 0x%x, tail 0x%x\n",
				RTL_READ_32(r, RT_RXBUF), RTL_READ_16(r, RT_RXBUFHEAD), RTL_READ_16(r, RT_RXBUFTAIL));
			RTL_WRITE_32(r, RT_RXMISSED, 0);
			RTL_WRITE_16(r, RT_RXBUFTAIL, TAIL_TO_TAILREG(RTL_READ_16(r, RT_RXBUFHEAD)));
		}
		if(status & RT_INT_RXFIFO_OVERFLOW) {
			dprintf("RX fifo overflow!\n");
		}
		if(status & RT_INT_RXFIFO_UNDERRUN) {
			dprintf("RX fifo underrun\n");
		}
	}

	// reenable interrupts
	RTL_WRITE_16(r, RT_INTRMASK, MYRT_INTS);
#endif

done:
	release_spinlock(&r->reg_spinlock);

	return rc;
}
示例#7
0
ssize_t rhine_rx(rhine *r, char *buf, ssize_t buf_len)
{
	PANIC_UNIMPLEMENTED();
#if 0
	rx_entry *entry;
	uint32 tail;
	uint16 len;
	int rc;
	bool release_sem = false;

//	dprintf("rhine_rx: entry\n");

	if(buf_len < 1500)
		return -1;

restart:
	sem_acquire(r->rx_sem, 1);
	mutex_lock(&r->lock);

	int_disable_interrupts();
	acquire_spinlock(&r->reg_spinlock);

	tail = TAILREG_TO_TAIL(RTL_READ_16(r, RT_RXBUFTAIL));
//	dprintf("tailreg = 0x%x, actual tail 0x%x\n", RTL_READ_16(r, RT_RXBUFTAIL), tail);
	if(tail == RTL_READ_16(r, RT_RXBUFHEAD)) {
		release_spinlock(&r->reg_spinlock);
		int_restore_interrupts();
		mutex_unlock(&r->lock);
		goto restart;
	}

	if(RTL_READ_8(r, RT_CHIPCMD) & RT_CMD_RX_BUF_EMPTY) {
		release_spinlock(&r->reg_spinlock);
		int_restore_interrupts();
		mutex_unlock(&r->lock);
		goto restart;
	}

	// grab another buffer
	entry = (rx_entry *)((uint8 *)r->rxbuf + tail);
//	dprintf("entry->status = 0x%x\n", entry->status);
//	dprintf("entry->len = 0x%x\n", entry->len);

	// see if it's an unfinished buffer
	if(entry->len == 0xfff0) {
		release_spinlock(&r->reg_spinlock);
		int_restore_interrupts();
		mutex_unlock(&r->lock);
		goto restart;
	}

	// figure the len that we need to copy
	len = entry->len - 4; // minus the crc

	// see if we got an error
	if((entry->status & RT_RX_STATUS_OK) == 0 || len > ETHERNET_MAX_SIZE) {
		// error, lets reset the card
		rhine_resetrx(r);
		release_spinlock(&r->reg_spinlock);
		int_restore_interrupts();
		mutex_unlock(&r->lock);
		goto restart;
	}

	// copy the buffer
	if(len > buf_len) {
		dprintf("rhine_rx: packet too large for buffer (len %d, buf_len %ld)\n", len, (long)buf_len);
		RTL_WRITE_16(r, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(r, RT_RXBUFHEAD)));
		rc = ERR_TOO_BIG;
		release_sem = true;
		goto out;
	}
	if(tail + len > 0xffff) {
//		dprintf("packet wraps around\n");
		memcpy(buf, (const void *)&entry->data[0], 0x10000 - (tail + 4));
		memcpy((uint8 *)buf + 0x10000 - (tail + 4), (const void *)r->rxbuf, len - (0x10000 - (tail + 4)));
	} else {
		memcpy(buf, (const void *)&entry->data[0], len);
	}
	rc = len;

	// calculate the new tail
	tail = ((tail + entry->len + 4 + 3) & ~3) % 0x10000;
//	dprintf("new tail at 0x%x, tailreg will say 0x%x\n", tail, TAIL_TO_TAILREG(tail));
	RTL_WRITE_16(r, RT_RXBUFTAIL, TAIL_TO_TAILREG(tail));

	if(tail != RTL_READ_16(r, RT_RXBUFHEAD)) {
		// we're at last one more packet behind
		release_sem = true;
	}

out:
	release_spinlock(&r->reg_spinlock);
	int_restore_interrupts();

	if(release_sem)
		sem_release(r->rx_sem, 1);
	mutex_unlock(&r->lock);

#if 0
{
	int i;
	dprintf("RX %x (%d)\n", buf, len);

	dprintf("dumping packet:");
	for(i=0; i<len; i++) {
		if(i%8 == 0)
			dprintf("\n");
		dprintf("0x%02x ", buf[i]);
	}
	dprintf("\n");
}
#endif

	return rc;
#endif
}
示例#8
0
int rhine_init(rhine *r)
{
	bigtime_t time;
	int err = -1;
	addr_t temp;
	int i;

	dprintf("rhine_init: r %p\n", r);

	r->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rhine_region", (void **)&r->virt_base,
		REGION_ADDR_ANY_ADDRESS, r->phys_size, LOCK_KERNEL|LOCK_RW, r->phys_base);
	if(r->region < 0) {
		dprintf("rhine_init: error creating memory mapped region\n");
		err = -1;
		goto err;
	}
	dprintf("rhine mapped at address 0x%lx\n", r->virt_base);

	/* create regions for tx and rx descriptors */
	r->rxdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_rxdesc", (void **)&r->rxdesc,
		REGION_ADDR_ANY_ADDRESS, RXDESC_COUNT * sizeof(struct rhine_rx_desc), REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	r->rxdesc_phys = vtophys(r->rxdesc);
	dprintf("rhine: rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys);
	r->txdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_txdesc", (void **)&r->txdesc,
		REGION_ADDR_ANY_ADDRESS, TXDESC_COUNT * sizeof(struct rhine_tx_desc), REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	r->txdesc_phys = vtophys(r->txdesc);
	dprintf("rhine: tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys);
	r->reg_spinlock = 0;

	/* stick all rx and tx buffers in a circular buffer */
	for (i=0; i < RXDESC_COUNT; i++) {
		RXDESC(r, i).status = 0;
		RXDESC(r, i).framelen = 0;
		RXDESC(r, i).buflen = 0;
		RXDESC(r, i).ptr = 0;
		if (i == RXDESC_COUNT-1)
			RXDESC(r, i).next = RXDESC_PHYS(r, 0);
		else
			RXDESC(r, i).next = RXDESC_PHYS(r, i + 1);
	}
	// XXX do same for tx


	r->rx_head = r->rx_tail = 0;

	/* reset the chip */
	time = system_time();
	RHINE_WRITE_16(r, RHINE_CR0, 0x8000); // reset the chip
	do {
		thread_snooze(10000); // 10ms
		if(system_time() - time > 1000000) {
			break;
		}
	} while(RHINE_READ_16(r, RHINE_CR0) & 0x8000);

	if (RHINE_READ_16(r, RHINE_CR0) & 0x8000) {
		dprintf("chip didn't reset, trying alternate method\n");
		RHINE_SETBITS_8(r, RHINE_MISC_CR1, 0x40);
		thread_snooze(10000);
	}

	/* read in the mac address */
	RHINE_WRITE_8(r, RHINE_EECSR, RHINE_READ_8(r, RHINE_EECSR) | (1<<5));
	r->mac_addr[0] = RHINE_READ_8(r, RHINE_PAR0); 
	r->mac_addr[1] = RHINE_READ_8(r, RHINE_PAR1);
   	r->mac_addr[2] = RHINE_READ_8(r, RHINE_PAR2);
	r->mac_addr[3] = RHINE_READ_8(r, RHINE_PAR3);
   	r->mac_addr[4] = RHINE_READ_8(r, RHINE_PAR4);
   	r->mac_addr[5] = RHINE_READ_8(r, RHINE_PAR5);
  	dprintf("rhine: mac addr %x:%x:%x:%x:%x:%x\n",
  		r->mac_addr[0], r->mac_addr[1], r->mac_addr[2],
  		r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]);

	/* set up the rx state */
	/* 64 byte fifo threshold, all physical/broadcast/multicast/small/error packets accepted */
	RHINE_WRITE_8(r, RHINE_RCR, (0<<5) | (1<<4) | (1<<3) | (1<<2) | (1<<1) | (1<<0));
	RHINE_WRITE_32(r, RHINE_RDA0, RXDESC_PHYS(r, r->rx_head));

	/* set up tx state */
	/* 64 byte fifo, default backup, default loopback mode */
	RHINE_WRITE_8(r, RHINE_TCR, 0);

	/* mask all interrupts */
	RHINE_WRITE_16(r, RHINE_IMR0, 0);

	/* clear all pending interrupts */
	RHINE_WRITE_16(r, RHINE_ISR0, 0xffff);
	
	/* set up the interrupt handler */
	int_set_io_interrupt_handler(r->irq, &rhine_int, r, "rhine");

	{
		static uint8 buf[2048];
		RXDESC(r, r->rx_tail).ptr = vtophys(buf);
		RXDESC(r, r->rx_tail).buflen = sizeof(buf);
		RXDESC(r, r->rx_tail).status = 0;
		RXDESC(r, r->rx_tail).framelen = RHINE_RX_OWNER;
		r->rx_tail++;

		RHINE_WRITE_16(r, RHINE_CR0, (1<<1) | (1<<3) | (1<<6));
	}

	/* unmask all interrupts */
	RHINE_WRITE_16(r, RHINE_IMR0, 0xffff);	

#if 0
	// try to reset the device
 	time = system_time();
	RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RESET);
	do {
		thread_snooze(10000); // 10ms
		if(system_time() - time > 1000000) {
			err = -1;
			goto err1;
		}
	} while((RTL_READ_8(r, RT_CHIPCMD) & RT_CMD_RESET));

	// create a rx and tx buf
	r->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_rxbuf", (void **)&r->rxbuf,
		REGION_ADDR_ANY_ADDRESS, 64*1024 + 16, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	r->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_txbuf", (void **)&r->txbuf,
		REGION_ADDR_ANY_ADDRESS, 8*1024, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);

	// set up the transmission buf and sem
	r->tx_sem = sem_create(4, "rhine_txsem");
	mutex_init(&r->lock, "rhine");
	r->txbn = 0;
	r->last_txbn = 0;
	r->rx_sem = sem_create(0, "rhine_rxsem");
	r->reg_spinlock = 0;

	// set up the interrupt handler
	int_set_io_interrupt_handler(r->irq, &rhine_int, r, "rhine");

	// read the mac address
	r->mac_addr[0] = RTL_READ_8(r, RT_IDR0);
	r->mac_addr[1] = RTL_READ_8(r, RT_IDR0 + 1);
	r->mac_addr[2] = RTL_READ_8(r, RT_IDR0 + 2);
	r->mac_addr[3] = RTL_READ_8(r, RT_IDR0 + 3);
  	r->mac_addr[4] = RTL_READ_8(r, RT_IDR0 + 4);
  	r->mac_addr[5] = RTL_READ_8(r, RT_IDR0 + 5);

  	dprintf("rhine: mac addr %x:%x:%x:%x:%x:%x\n",
  		r->mac_addr[0], r->mac_addr[1], r->mac_addr[2],
  		r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]);

	// enable writing to the config registers
	RTL_WRITE_8(r, RT_CFG9346, 0xc0);

	// reset config 1
	RTL_WRITE_8(r, RT_CONFIG1, 0);

	// Enable receive and transmit functions
	RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);

	// Set Rx FIFO threashold to 256, Rx size to 64k+16, 256 byte DMA burst
	RTL_WRITE_32(r, RT_RXCONFIG, 0x00009c00);

	// Set Tx 256 byte DMA burst
	RTL_WRITE_32(r, RT_TXCONFIG, 0x03000400);

	// Turn off lan-wake and set the driver-loaded bit
	RTL_WRITE_8(r, RT_CONFIG1, (RTL_READ_8(r, RT_CONFIG1) & ~0x30) | 0x20);

	// Enable FIFO auto-clear
	RTL_WRITE_8(r, RT_CONFIG4, RTL_READ_8(r, RT_CONFIG4) | 0x80);

	// go back to normal mode
	RTL_WRITE_8(r, RT_CFG9346, 0);

	// Setup RX buffers
	*(int *)r->rxbuf = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), r->rxbuf, &temp);
	dprintf("rx buffer will be at 0x%lx\n", temp);
	RTL_WRITE_32(r, RT_RXBUF, temp);

	// Setup TX buffers
	dprintf("tx buffer (virtual) is at 0x%lx\n", r->txbuf);
	*(int *)r->txbuf = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), r->txbuf, &temp);
	RTL_WRITE_32(r, RT_TXADDR0, temp);
	RTL_WRITE_32(r, RT_TXADDR1, temp + 2*1024);
	dprintf("first half of txbuf at 0x%lx\n", temp);
	*(int *)(r->txbuf + 4*1024) = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), r->txbuf + 4*1024, &temp);
	RTL_WRITE_32(r, RT_TXADDR2, temp);
	RTL_WRITE_32(r, RT_TXADDR3, temp + 2*1024);
	dprintf("second half of txbuf at 0x%lx\n", temp);

/*
	RTL_WRITE_32(r, RT_TXSTATUS0, RTL_READ_32(r, RT_TXSTATUS0) | 0xfffff000);
	RTL_WRITE_32(r, RT_TXSTATUS1, RTL_READ_32(r, RT_TXSTATUS1) | 0xfffff000);
	RTL_WRITE_32(r, RT_TXSTATUS2, RTL_READ_32(r, RT_TXSTATUS2) | 0xfffff000);
	RTL_WRITE_32(r, RT_TXSTATUS3, RTL_READ_32(r, RT_TXSTATUS3) | 0xfffff000);
*/
	// Reset RXMISSED counter
	RTL_WRITE_32(r, RT_RXMISSED, 0);

	// Enable receiving broadcast and physical match packets
//	RTL_WRITE_32(r, RT_RXCONFIG, RTL_READ_32(r, RT_RXCONFIG) | 0x0000000a);
	RTL_WRITE_32(r, RT_RXCONFIG, RTL_READ_32(r, RT_RXCONFIG) | 0x0000000f);

	// Filter out all multicast packets
	RTL_WRITE_32(r, RT_MAR0, 0);
	RTL_WRITE_32(r, RT_MAR0 + 4, 0);

	// Disable all multi-interrupts
	RTL_WRITE_16(r, RT_MULTIINTR, 0);

	RTL_WRITE_16(r, RT_INTRMASK, MYRT_INTS);
//	RTL_WRITE_16(r, RT_INTRMASK, 0x807f);

	// Enable RX/TX once more
	RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);

	RTL_WRITE_8(r, RT_CFG9346, 0);
#endif

	return 0;

err1:
	vm_delete_region(vm_get_kernel_aspace_id(), r->region);
err:
	return err;
}
static int rtl8169_init(rtl8169 *r)
{
    //bigtime_t time;
    int err = -1;
    //addr_t temp;
    //int i;

    hal_mutex_init(&r->lock,DEBUG_MSG_PREFIX);


    SHOW_FLOW(2, "rtl8169_init: r %p\n", r);

    /*
     r->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rtl8169_region", (void **)&r->virt_base, REGION_ADDR_ANY_ADDRESS, r->phys_size, LOCK_KERNEL|LOCK_RW, r->phys_base);
    if(r->region < 0) {
        SHOW_ERROR0(1, "rtl8169_init: error creating memory mapped region\n");
        err = -1;
        goto err;
    }*/

    size_t n_pages = BYTES_TO_PAGES(r->phys_size);

    hal_alloc_vaddress( (void **)&r->virt_base, n_pages); // alloc address of a page, but not memory
    hal_pages_control_etc( r->phys_base, (void *)r->virt_base, n_pages, page_map_io, page_rw, 0 );

    SHOW_INFO(2, "rtl8169 mapped at address 0x%lx\n", r->virt_base);

#if 0
    /* create regions for tx and rx descriptors */
    r->rxdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxdesc", (void **)&r->rxdesc,
                                                  REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
    r->rxdesc_phys = vtophys(r->rxdesc);
    SHOW_INFO(2, "rtl8169: rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys);
    r->txdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txdesc", (void **)&r->txdesc,
                                                  REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
    r->txdesc_phys = vtophys(r->txdesc);
    SHOW_INFO(2, "rtl8169: tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys);
    r->reg_spinlock = 0;

    /* create a large tx and rx buffer for the descriptors to point to */
    r->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxbuf", (void **)&r->rxbuf,
                                                 REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);
    r->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txbuf", (void **)&r->txbuf,
                                                 REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);
#endif

    hal_pv_alloc( &r->rxdesc_phys, (void**)&r->rxdesc, NUM_RX_DESCRIPTORS * DESCRIPTOR_LEN );
    hal_pv_alloc( &r->txdesc_phys, (void**)&r->txdesc, NUM_TX_DESCRIPTORS * DESCRIPTOR_LEN );

    SHOW_INFO(2, "rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys);
    SHOW_INFO(2, "tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys);

    hal_pv_alloc( &r->rxbuf_phys, (void**)&r->rxbuf, NUM_RX_DESCRIPTORS * BUFSIZE_PER_FRAME );
    hal_pv_alloc( &r->txbuf_phys, (void**)&r->txbuf, NUM_TX_DESCRIPTORS * BUFSIZE_PER_FRAME );

    /* create a receive sem */
    hal_sem_init( &r->rx_sem, "rtl8169 rx_sem");

    /* transmit sem */
    hal_sem_init(  &r->tx_sem, "rtl8169 tx_sem");

    /* reset the chip */
    int repeats = 100;
    RTL_WRITE_8(r, REG_CR, (1<<4)); // reset the chip, disable tx/rx
    do {
        hal_sleep_msec(10); // 10ms
        if(repeats -- <= 0 )
            break;
    } while(RTL_READ_8(r, REG_CR) & (1<<4));

    /* read in the mac address */
    r->mac_addr[0] = RTL_READ_8(r, REG_IDR0);
    r->mac_addr[1] = RTL_READ_8(r, REG_IDR1);
    r->mac_addr[2] = RTL_READ_8(r, REG_IDR2);
    r->mac_addr[3] = RTL_READ_8(r, REG_IDR3);
    r->mac_addr[4] = RTL_READ_8(r, REG_IDR4);
    r->mac_addr[5] = RTL_READ_8(r, REG_IDR5);
    SHOW_INFO(2, "rtl8169: mac addr %x:%x:%x:%x:%x:%x\n",
              r->mac_addr[0], r->mac_addr[1], r->mac_addr[2],
              r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]);

    /* some voodoo from BSD driver */
    RTL_WRITE_16(r, REG_CCR, RTL_READ_16(r, REG_CCR));
    RTL_SETBITS_16(r, REG_CCR, 0x3);

    /* mask all interrupts */
    RTL_WRITE_16(r, REG_IMR, 0);

    /* set up the tx/rx descriptors */
    rtl8169_setup_descriptors(r);

    /* enable tx/rx */
    RTL_SETBITS_8(r, REG_CR, (1<<3)|(1<<2));

    /* set up the rx state */
    /* 1024 byte dma threshold, 1024 dma max burst, CRC calc 8 byte+, accept all packets */
    RTL_WRITE_32(r, REG_RCR, (1<<16) | (6<<13) | (6<<8) | (0xf << 0));
    RTL_SETBITS_16(r, REG_CCR, (1<<5)); // rx checksum enable
    RTL_WRITE_16(r, REG_RMS, 1518); // rx mtu

    /* set up the tx state */
    RTL_WRITE_32(r, REG_TCR, (RTL_READ_32(r, REG_TCR) & ~0x1ff) | (6<<8)); // 1024 max burst dma
    RTL_WRITE_8(r, REG_MTPS, 0x3f); // max tx packet size (must be careful to not actually transmit more than mtu)

    /* set up the interrupt handler */
    //int_set_io_interrupt_handler(r->irq, &rtl8169_int, r, "rtl8169");
    if(hal_irq_alloc( r->irq, &rtl8169_int, r, HAL_IRQ_SHAREABLE ))
    {
        SHOW_ERROR( 0, "unable to allocate irq %d", r->irq );
        goto err1;
    }

    /* clear all pending interrupts */
    RTL_WRITE_16(r, REG_ISR, 0xffff);

    /* unmask interesting interrupts */
    RTL_WRITE_16(r, REG_IMR, IMR_SYSERR | IMR_LINKCHG | IMR_TER | IMR_TOK | IMR_RER | IMR_ROK | IMR_RXOVL);

    return 0;

err1:
    // TODO free what?
    //vm_delete_region(vm_get_kernel_aspace_id(), r->region);
//err:
    return err;
}
示例#10
0
int rtl8169_init(rtl8169 *r)
{
	bigtime_t time;
	int err = -1;
	addr_t temp;
	int i;

	SHOW_FLOW(2, "rtl8169_init: r %p\n", r);

	r->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rtl8169_region", (void **)&r->virt_base,
		REGION_ADDR_ANY_ADDRESS, r->phys_size, LOCK_KERNEL|LOCK_RW, r->phys_base);
	if(r->region < 0) {
		SHOW_ERROR0(1, "rtl8169_init: error creating memory mapped region\n");
		err = -1;
		goto err;
	}
	SHOW_INFO(2, "rtl8169 mapped at address 0x%lx\n", r->virt_base);

	/* create regions for tx and rx descriptors */
	r->rxdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxdesc", (void **)&r->rxdesc,
		REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	r->rxdesc_phys = vtophys(r->rxdesc);
	SHOW_INFO(2, "rtl8169: rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys);
	r->txdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txdesc", (void **)&r->txdesc,
		REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	r->txdesc_phys = vtophys(r->txdesc);
	SHOW_INFO(2, "rtl8169: tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys);
	r->reg_spinlock = 0;

	/* create a large tx and rx buffer for the descriptors to point to */
	r->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxbuf", (void **)&r->rxbuf,
			REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);
	r->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txbuf", (void **)&r->txbuf,
			REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);

	/* create a receive sem */
	r->rx_sem = sem_create(0, "rtl8169 rx_sem");

	/* transmit sem */
	r->tx_sem = sem_create(1, "rtl8169 tx_sem");

	/* reset the chip */
	time = system_time();
	RTL_WRITE_8(r, REG_CR, (1<<4)); // reset the chip, disable tx/rx
	do {
		thread_snooze(10000); // 10ms
		if(system_time() - time > 1000000) {
			break;
		}
	} while(RTL_READ_8(r, REG_CR) & (1<<4));

	/* read in the mac address */
	r->mac_addr[0] = RTL_READ_8(r, REG_IDR0); 
	r->mac_addr[1] = RTL_READ_8(r, REG_IDR1);
   	r->mac_addr[2] = RTL_READ_8(r, REG_IDR2);
	r->mac_addr[3] = RTL_READ_8(r, REG_IDR3);
   	r->mac_addr[4] = RTL_READ_8(r, REG_IDR4);
   	r->mac_addr[5] = RTL_READ_8(r, REG_IDR5);
  	SHOW_INFO(2, "rtl8169: mac addr %x:%x:%x:%x:%x:%x\n",
  		r->mac_addr[0], r->mac_addr[1], r->mac_addr[2],
  		r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]);

	/* some voodoo from BSD driver */
	RTL_WRITE_16(r, REG_CCR, RTL_READ_16(r, REG_CCR));
	RTL_SETBITS_16(r, REG_CCR, 0x3);

	/* mask all interrupts */
	RTL_WRITE_16(r, REG_IMR, 0);

	/* set up the tx/rx descriptors */
	rtl8169_setup_descriptors(r);

	/* enable tx/rx */
	RTL_SETBITS_8(r, REG_CR, (1<<3)|(1<<2));

	/* set up the rx state */
	/* 1024 byte dma threshold, 1024 dma max burst, CRC calc 8 byte+, accept all packets */
	RTL_WRITE_32(r, REG_RCR, (1<<16) | (6<<13) | (6<<8) | (0xf << 0)); 
	RTL_SETBITS_16(r, REG_CCR, (1<<5)); // rx checksum enable
	RTL_WRITE_16(r, REG_RMS, 1518); // rx mtu

	/* set up the tx state */
	RTL_WRITE_32(r, REG_TCR, (RTL_READ_32(r, REG_TCR) & ~0x1ff) | (6<<8)); // 1024 max burst dma
	RTL_WRITE_8(r, REG_MTPS, 0x3f); // max tx packet size (must be careful to not actually transmit more than mtu)

	/* set up the interrupt handler */
	int_set_io_interrupt_handler(r->irq, &rtl8169_int, r, "rtl8169");

	/* clear all pending interrupts */
	RTL_WRITE_16(r, REG_ISR, 0xffff);
	
	/* unmask interesting interrupts */
	RTL_WRITE_16(r, REG_IMR, IMR_SYSERR | IMR_LINKCHG | IMR_TER | IMR_TOK | IMR_RER | IMR_ROK | IMR_RXOVL);

	return 0;

err1:
	vm_delete_region(vm_get_kernel_aspace_id(), r->region);
err:
	return err;
}
示例#11
0
static void rtl8139_stop(rtl8139 *rtl)
{
	// stop the rx and tx and mask all interrupts
	RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RESET);
	RTL_WRITE_16(rtl, RT_INTRMASK, 0);
}
示例#12
0
int rtl8139_init(rtl8139 *rtl)
{
	bigtime_t time;
	int err = -1;
	addr_t temp;

	dprintf("rtl8139_init: rtl %p\n", rtl);

	rtl->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rtl8139_region", (void **)&rtl->virt_base,
		REGION_ADDR_ANY_ADDRESS, rtl->phys_size, LOCK_KERNEL|LOCK_RW, rtl->phys_base);
	if(rtl->region < 0) {
		dprintf("rtl8139_init: error creating memory mapped region\n");
		err = -1;
		goto err;
	}
	dprintf("rtl8139 mapped at address 0x%lx\n", rtl->virt_base);

	// try to reset the device
 	time = system_time();
	RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RESET);
	do {
		thread_snooze(10000); // 10ms
		if(system_time() - time > 1000000) {
			err = -1;
			goto err1;
		}
	} while((RTL_READ_8(rtl, RT_CHIPCMD) & RT_CMD_RESET));

	// create a rx and tx buf
	rtl->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8139_rxbuf", (void **)&rtl->rxbuf,
		REGION_ADDR_ANY_ADDRESS, 64*1024 + 16, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW);
	rtl->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8139_txbuf", (void **)&rtl->txbuf,
		REGION_ADDR_ANY_ADDRESS, 8*1024, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW);

	// set up the transmission buf and sem
	rtl->tx_sem = sem_create(4, "rtl8139_txsem");
	mutex_init(&rtl->lock, "rtl8139");
	rtl->txbn = 0;
	rtl->last_txbn = 0;
	rtl->rx_sem = sem_create(0, "rtl8139_rxsem");
	rtl->reg_spinlock = 0;

	// set up the interrupt handler
	int_set_io_interrupt_handler(rtl->irq, &rtl8139_int, rtl, "rtl8139");

	// read the mac address
	rtl->mac_addr[0] = RTL_READ_8(rtl, RT_IDR0);
	rtl->mac_addr[1] = RTL_READ_8(rtl, RT_IDR0 + 1);
	rtl->mac_addr[2] = RTL_READ_8(rtl, RT_IDR0 + 2);
	rtl->mac_addr[3] = RTL_READ_8(rtl, RT_IDR0 + 3);
  	rtl->mac_addr[4] = RTL_READ_8(rtl, RT_IDR0 + 4);
  	rtl->mac_addr[5] = RTL_READ_8(rtl, RT_IDR0 + 5);

  	dprintf("rtl8139: mac addr %x:%x:%x:%x:%x:%x\n",
  		rtl->mac_addr[0], rtl->mac_addr[1], rtl->mac_addr[2],
  		rtl->mac_addr[3], rtl->mac_addr[4], rtl->mac_addr[5]);

	// enable writing to the config registers
	RTL_WRITE_8(rtl, RT_CFG9346, 0xc0);

	// reset config 1
	RTL_WRITE_8(rtl, RT_CONFIG1, 0);

	// Enable receive and transmit functions
	RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);

	// Set Rx FIFO threashold to 256, Rx size to 64k+16, 256 byte DMA burst
	RTL_WRITE_32(rtl, RT_RXCONFIG, 0x00009c00);

	// Set Tx 256 byte DMA burst
	RTL_WRITE_32(rtl, RT_TXCONFIG, 0x03000400);

	// Turn off lan-wake and set the driver-loaded bit
	RTL_WRITE_8(rtl, RT_CONFIG1, (RTL_READ_8(rtl, RT_CONFIG1) & ~0x30) | 0x20);

	// Enable FIFO auto-clear
	RTL_WRITE_8(rtl, RT_CONFIG4, RTL_READ_8(rtl, RT_CONFIG4) | 0x80);

	// go back to normal mode
	RTL_WRITE_8(rtl, RT_CFG9346, 0);

	// Setup RX buffers
	*(int *)rtl->rxbuf = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->rxbuf, &temp);
	dprintf("rx buffer will be at 0x%lx\n", temp);
	RTL_WRITE_32(rtl, RT_RXBUF, temp);

	// Setup TX buffers
	dprintf("tx buffer (virtual) is at 0x%lx\n", rtl->txbuf);
	*(int *)rtl->txbuf = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf, &temp);
	RTL_WRITE_32(rtl, RT_TXADDR0, temp);
	RTL_WRITE_32(rtl, RT_TXADDR1, temp + 2*1024);
	dprintf("first half of txbuf at 0x%lx\n", temp);
	*(int *)(rtl->txbuf + 4*1024) = 0;
	vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf + 4*1024, &temp);
	RTL_WRITE_32(rtl, RT_TXADDR2, temp);
	RTL_WRITE_32(rtl, RT_TXADDR3, temp + 2*1024);
	dprintf("second half of txbuf at 0x%lx\n", temp);

/*
	RTL_WRITE_32(rtl, RT_TXSTATUS0, RTL_READ_32(rtl, RT_TXSTATUS0) | 0xfffff000);
	RTL_WRITE_32(rtl, RT_TXSTATUS1, RTL_READ_32(rtl, RT_TXSTATUS1) | 0xfffff000);
	RTL_WRITE_32(rtl, RT_TXSTATUS2, RTL_READ_32(rtl, RT_TXSTATUS2) | 0xfffff000);
	RTL_WRITE_32(rtl, RT_TXSTATUS3, RTL_READ_32(rtl, RT_TXSTATUS3) | 0xfffff000);
*/
	// Reset RXMISSED counter
	RTL_WRITE_32(rtl, RT_RXMISSED, 0);

	// Enable receiving broadcast and physical match packets
//	RTL_WRITE_32(rtl, RT_RXCONFIG, RTL_READ_32(rtl, RT_RXCONFIG) | 0x0000000a);
	RTL_WRITE_32(rtl, RT_RXCONFIG, RTL_READ_32(rtl, RT_RXCONFIG) | 0x0000000f);

	// Filter out all multicast packets
	RTL_WRITE_32(rtl, RT_MAR0, 0);
	RTL_WRITE_32(rtl, RT_MAR0 + 4, 0);

	// Disable all multi-interrupts
	RTL_WRITE_16(rtl, RT_MULTIINTR, 0);

	RTL_WRITE_16(rtl, RT_INTRMASK, MYRT_INTS);
//	RTL_WRITE_16(rtl, RT_INTRMASK, 0x807f);

	// Enable RX/TX once more
	RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE);

	RTL_WRITE_8(rtl, RT_CFG9346, 0);

	return 0;

err1:
	vm_delete_region(vm_get_kernel_aspace_id(), rtl->region);
err:
	return err;
}