示例#1
0
static void
dp83902a_stop(struct nic_priv_data *dp)
{
	n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);	/* Brutal */
	n2k_outb(dp, DP_ISR, 0xFF);		/* Clear any pending interrupts */
	n2k_outb(dp, DP_IMR, 0x00);		/* Disable all interrupts */

	dp->running = false;
}
示例#2
0
/*
 * This routine is called to start the transmitter. It is split out from the
 * data handling routine so it may be called either when data becomes first
 * available or when an Tx interrupt occurs
 */
static void dp83902a_start_xmit(struct nic_priv_data *dp, int start_page, int len)
{
	n2k_outb(dp, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE));
	n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
	n2k_outb(dp, DP_TBCL, len & 0xFF);
	n2k_outb(dp, DP_TBCH, len >> 8);
	n2k_outb(dp, DP_TPSR, start_page);
	n2k_outb(dp, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);

	dp->tx_started = true;
}
示例#3
0
int get_prom(u8* mac_addr, u8* base_addr)
{
	u8 prom[32];
	int i, j;
	struct {
		u_char value, offset;
	} program_seq[] = {
		{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
		{0x48, EN0_DCFG},		/* Set byte-wide (0x48) access. */
		{0x00, EN0_RCNTLO},		/* Clear the count regs. */
		{0x00, EN0_RCNTHI},
		{0x00, EN0_IMR},		/* Mask completion irq. */
		{0xFF, EN0_ISR},
		{E8390_RXOFF, EN0_RXCR},	/* 0x20 Set to monitor */
		{E8390_TXOFF, EN0_TXCR},	/* 0x02 and loopback mode. */
		{32, EN0_RCNTLO},
		{0x00, EN0_RCNTHI},
		{0x00, EN0_RSARLO},		/* DMA starting at 0x0000. */
		{0x00, EN0_RSARHI},
		{E8390_RREAD+E8390_START, E8390_CMD},
	};

	PRINTK ("trying to get MAC via prom reading\n");

	pcnet_reset_8390 (base_addr);

	mdelay (10);

	for (i = 0; i < sizeof (program_seq) / sizeof (program_seq[0]); i++)
		n2k_outb (program_seq[i].value, program_seq[i].offset);

	PRINTK ("PROM:");
	for (i = 0; i < 32; i++) {
		prom[i] = n2k_inb (PCNET_DATAPORT);
		PRINTK (" %02x", prom[i]);
	}
	PRINTK ("\n");
	for (i = 0; i < NR_INFO; i++) {
		if ((prom[0] == hw_info[i].a0) &&
			(prom[2] == hw_info[i].a1) &&
			(prom[4] == hw_info[i].a2)) {
			PRINTK ("matched board %d\n", i);
			break;
		}
	}
	if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
		PRINTK ("on exit i is %d/%ld\n", i, NR_INFO);
		PRINTK ("MAC address is ");
		for (j = 0; j < 6; j++) {
			mac_addr[j] = prom[j << 1];
			PRINTK ("%02x:", mac_addr[i]);
		}
		PRINTK ("\n");
		return (i < NR_INFO) ? i : 0;
	}
	return 0;
}
示例#4
0
int get_prom(struct nic_priv_data *dp, u8* mac_addr)
{
	u8 prom[32];
	int i, j;
	struct {
		unsigned char value, offset;
	} program_seq[] = {
		{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
		{0x48, EN0_DCFG},		/* Set byte-wide (0x48) access. */
		{0x00, EN0_RCNTLO},		/* Clear the count regs. */
		{0x00, EN0_RCNTHI},
		{0x00, EN0_IMR},		/* Mask completion irq. */
		{0xFF, EN0_ISR},
		{E8390_RXOFF, EN0_RXCR},	/* 0x20 Set to monitor */
		{E8390_TXOFF, EN0_TXCR},	/* 0x02 and loopback mode. */
		{32, EN0_RCNTLO},
		{0x00, EN0_RCNTHI},
		{0x00, EN0_RSARLO},		/* DMA starting at 0x0000. */
		{0x00, EN0_RSARHI},
		{E8390_RREAD+E8390_START, E8390_CMD},
	};

	pcnet_reset_8390(dp);

	for (i = 0; i < sizeof (program_seq) / sizeof (program_seq[0]); i++)
		n2k_outb (dp, program_seq[i].value, program_seq[i].offset);

	for (i = 0; i < 32; i++) {
		prom[i] = n2k_inb (dp, PCNET_DATAPORT);
	}

	for (i = 0;; i++) {
		if (hw_info[i].dev_name == NULL) break;

		if ((prom[0] == hw_info[i].a0) &&
			(prom[2] == hw_info[i].a1) &&
			(prom[4] == hw_info[i].a2)) {
			vmm_printf("%s detected.\n", hw_info[i].dev_name);
			break;
		}
	}

	if ((prom[28] == 0x57) && (prom[30] == 0x57)) {
		vmm_printf ("MAC address is ");
		for (j = 0; j < 6; j++) {
			if (j) vmm_printf(":");
			mac_addr[j] = prom[j << 1];
			vmm_printf ("%02x", mac_addr[j]);
		}
		vmm_printf ("\n");
	}
	return VMM_OK;
}
示例#5
0
static void pcnet_reset_8390(void)
{
	int i, r;

	PRINTK("nic base is %lx\n", nic_base);

#if 1
	n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
	PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
	n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
	PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
	n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
	PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
#endif
	n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);

	n2k_outb(n2k_inb(nic_base + PCNET_RESET), PCNET_RESET);

	for (i = 0; i < 100; i++) {
		if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
			break;
		PRINTK("got %x in reset\n", r);
		my_udelay(100);
	}
	n2k_outb(ENISR_RESET, EN0_ISR); /* Ack intr. */

	if (i == 100)
		printf("pcnet_reset_8390() did not complete.\n");
} /* pcnet_reset_8390 */
示例#6
0
static void pcnet_reset_8390(struct nic_priv_data *dp)
{
	int i, r;

	n2k_outb(dp, E8390_CMD, E8390_NODMA + E8390_PAGE0+E8390_STOP);
	n2k_outb(dp, E8390_CMD, E8390_NODMA+E8390_PAGE1+E8390_STOP);
	n2k_outb(dp, E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_STOP);
	n2k_outb(dp, E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
	n2k_outb(dp, PCNET_RESET, n2k_inb(dp, PCNET_RESET));

	for (i = 0; i < 100; i++) {
		if ((r = (n2k_inb(dp, EN0_ISR) & ENISR_RESET)) != 0)
			break;
	}
	n2k_outb(dp, EN0_ISR, ENISR_RESET); /* Ack intr. */

	if (i == 100)
		vmm_printf("pcnet_reset_8390() did not complete.\n");
}
示例#7
0
/*
 * This function is called when a packet has been received. It's job is
 * to prepare to unload the packet from the hardware. Once the length of
 * the packet is known, the upper layer of the driver can be told. When
 * the upper layer is ready to unload the packet, the internal function
 * 'dp83902a_recv' will be called to actually fetch it from the hardware.
 */
static void dp83902a_RxEvent(struct nic_priv_data *dp)
{
	u8 rsr;
	u8 rcv_hdr[4];
	int i, len, pkt, cur = 0;

	rsr = n2k_inb(dp, DP_RSR);

	if (!(rsr & 0x01)) {
		return;
	}

	while (true) {
		/* Read incoming packet header */
		n2k_outb(dp, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START);
		n2k_outb(dp, DP_P1_CURP, cur);
		n2k_outb(dp, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
		pkt = n2k_inb(dp, DP_BNDRY);

		pkt += 1;
		if (pkt == dp->rx_buf_end)
			pkt = dp->rx_buf_start;

		if (pkt == cur) {
			break;
		}
		n2k_outb(dp, DP_RBCL, sizeof(rcv_hdr));
		n2k_outb(dp, DP_RBCH, 0);
		n2k_outb(dp, DP_RSAL, 0);
		n2k_outb(dp, DP_RSAH, pkt);
		if (dp->rx_next == pkt) {
			if (cur == dp->rx_buf_start)
				n2k_outb(dp, DP_BNDRY, dp->rx_buf_end - 1);
			else
				n2k_outb(dp, DP_BNDRY, cur - 1); /* Update pointer */
			return;
		}
		dp->rx_next = pkt;
		n2k_outb(dp, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
		n2k_outb(dp, DP_CR, DP_CR_RDMA | DP_CR_START);

		/* read header (get data size)*/
		for (i = 0; i < sizeof(rcv_hdr);) {
			DP_IN_DATA(dp->data, rcv_hdr[i++]);
		}

		len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);

		/* FIXME: Tell that data has been read */
		push_packet_len(dp, len);

		if (rcv_hdr[1] == dp->rx_buf_start)
			n2k_outb(dp, DP_BNDRY, dp->rx_buf_end - 1);
		else
			n2k_outb(dp, DP_BNDRY, rcv_hdr[1] - 1); /* Update pointer */
	}
}
示例#8
0
/*
 * This routine is called to send data to the hardware. It is known a-priori
 * that there is free buffer space (dp->tx_next).
 */
static void dp83902a_send(struct nic_priv_data *dp, u8 *data, int total_len, u32 key)
{
	int len, start_page, pkt_len, i;
	volatile int isr;

	len = pkt_len = total_len;
	if (pkt_len < IEEE_8023_MIN_FRAME)
		pkt_len = IEEE_8023_MIN_FRAME;

	start_page = dp->tx_next;
	if (dp->tx_next == dp->tx_buf1) {
		dp->tx1 = start_page;
		dp->tx1_len = pkt_len;
		dp->tx1_key = key;
		dp->tx_next = dp->tx_buf2;
	} else {
		dp->tx2 = start_page;
		dp->tx2_len = pkt_len;
		dp->tx2_key = key;
		dp->tx_next = dp->tx_buf1;
	}


	n2k_outb(dp, DP_ISR, DP_ISR_RDC);	/* Clear end of DMA */
	{
		/*
		 * Dummy read. The manual sez something slightly different,
		 * but the code is extended a bit to do what Hitachi's monitor
		 * does (i.e., also read data).
		 */

		u16 tmp;
		int len = 1;

		n2k_outb(dp, DP_RSAL, 0x100 - len);
		n2k_outb(dp, DP_RSAH, (start_page - 1) & 0xff);
		n2k_outb(dp, DP_RBCL, len);
		n2k_outb(dp, DP_RBCH, 0);
		n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
		DP_IN_DATA(dp->data, tmp);
	}

	/* Send data to device buffer(s) */
	n2k_outb(dp, DP_RSAL, 0);
	n2k_outb(dp, DP_RSAH, start_page);
	n2k_outb(dp, DP_RBCL, pkt_len & 0xFF);
	n2k_outb(dp, DP_RBCH, pkt_len >> 8);
	n2k_outb(dp, DP_CR, DP_CR_WDMA | DP_CR_START);

	/* Put data into buffer */
	while (len > 0) {
		DP_OUT_DATA(dp->data, *data++);
		len--;
	}

	if (total_len < pkt_len) {
		/* Padding to 802.3 length was required */
		for (i = total_len; i < pkt_len;) {
			i++;
			DP_OUT_DATA(dp->data, 0);
		}
	}

	/* Wait for DMA to complete */
	do {
		isr = n2k_inb(dp, DP_ISR);
	} while ((isr & DP_ISR_RDC) == 0);

	/* Then disable DMA */
	n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);

	/* Start transmit if not already going */
	if (!dp->tx_started) {
		if (start_page == dp->tx1) {
			dp->tx_int = 1; /* Expecting interrupt from BUF1 */
		} else {
			dp->tx_int = 2; /* Expecting interrupt from BUF2 */
		}
		dp83902a_start_xmit(dp, start_page, pkt_len);
	}
}
示例#9
0
/*
 * This function is called to "start up" the interface. It may be called
 * multiple times, even when the hardware is already running. It will be
 * called whenever something "hardware oriented" changes and should leave
 * the hardware ready to send/receive packets.
 */
static void
dp83902a_start(struct nic_priv_data *dp, u8 * enaddr)
{
	int i;

	n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
	n2k_outb(dp, DP_DCR, DP_DCR_INIT);
	n2k_outb(dp, DP_RBCH, 0);		/* Remote byte count */
	n2k_outb(dp, DP_RBCL, 0);
	n2k_outb(dp, DP_RCR, DP_RCR_MON);	/* Accept no packets */
	n2k_outb(dp, DP_TCR, DP_TCR_LOCAL);	/* Transmitter [virtually] off */
	n2k_outb(dp, DP_TPSR, dp->tx_buf1);	/* Transmitter start page */
	dp->tx1 = dp->tx2 = 0;
	dp->tx_next = dp->tx_buf1;
	dp->tx_started = false;
	dp->running = true;
	n2k_outb(dp, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */
	n2k_outb(dp, DP_BNDRY, dp->rx_buf_end - 1); /* Receive ring boundary */
	n2k_outb(dp, DP_PSTOP, dp->rx_buf_end);	/* Receive ring end page */
	dp->rx_next = dp->rx_buf_start - 1;
	dp->running = true;
	n2k_outb(dp, DP_ISR, 0xFF);		/* Clear any pending interrupts */
	n2k_outb(dp, DP_IMR, DP_IMR_All);	/* Enable all interrupts */
	n2k_outb(dp, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP);	/* Select page 1 */
	n2k_outb(dp, DP_P1_CURP, dp->rx_buf_start);	/* Current page - next free page for Rx */
	dp->running = true;
	for (i = 0; i < ETHER_ADDR_LEN; i++) {
		n2k_outb(dp, DP_P1_PAR0+i, enaddr[i]);
	}
	/* Enable and start device */
	n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
	n2k_outb(dp, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */
	n2k_outb(dp, DP_RCR, 0x00); /* No broadcast, no errors, no multicast */
	dp->running = true;
}